diff --git a/.gitignore b/.gitignore index 7a5ebe7..4cf3ce0 100644 --- a/.gitignore +++ b/.gitignore @@ -15,5 +15,11 @@ docs/ coverage/ lcov.info +lcov*.info log/ +# Local verification output +.certora_internal/ +coverage_*.log +scratch_*.log +scratch_*.txt diff --git a/certora/AccessControl.conf b/certora/AccessControl.conf new file mode 100644 index 0000000..43482de --- /dev/null +++ b/certora/AccessControl.conf @@ -0,0 +1,23 @@ +{ + "files": [ + "certora/harness/WeightedECDSAValidatorHarness.sol" + ], + "verify": "WeightedECDSAValidatorHarness:certora/AccessControl.spec", + "solc": "solc8.30", + "solc_via_ir": true, + "solc_optimize": "20000", + "packages": [ + "src/=src/", + "account-abstraction/=dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/", + "solady/=dependencies/solady-0.1.26/src/", + "openzeppelin-contracts/contracts/=dependencies/@openzeppelin-contracts-5.5.0/", + "forge-std/=dependencies/forge-std-1.11.0/src/" + ], + "loop_iter": "3", + "optimistic_loop": true, + "optimistic_hashing": true, + "hashing_length_bound": "384", + "rule_sanity": "basic", + "global_timeout": 600, + "msg": "AC-01: validateUserOp success implies a current guardian signed (no signature-less success path)" +} diff --git a/certora/AccessControl.spec b/certora/AccessControl.spec new file mode 100644 index 0000000..9a834c4 --- /dev/null +++ b/certora/AccessControl.spec @@ -0,0 +1,111 @@ +/* + * AC-01 (audit Low, raised in FV as a signature-gating access-control invariant): + * validateUserOp returns a success validationData (i.e. NOT SIG_VALIDATION_FAILED_UINT) + * ONLY IF the address recovered from userOp.signature over toEthSignedMessageHash(userOpHash) + * is a CURRENT guardian for the calling kernel (guardian[recovered][msg.sender].weight != 0). + * + * Equivalently: any userOp whose signature does NOT recover to an enabled guardian yields + * SIG_VALIDATION_FAILED_UINT, regardless of proposal.status (Approved), getApproval.passed, + * or paymasterAndData contents. There is NO signature-less success path. + * + * Target : src/validators/WeightedECDSAValidator.sol:204-272 + * Success return sites: + * - Ongoing branch (line 259): gated by `passed && guardian[signer][sender].weight != 0` + * where signer = recover(toEthSignedMessageHash(userOpHash), lastSig) (line 248) + * - Approved/passed branch (line 268): gated by `guardian[signer][sender].weight != 0` + * where signer = recover(toEthSignedMessageHash(userOpHash), userOp.signature) (line 265) + * Pre-fix bug: the Approved/paymaster sub-branch returned VALID with NO signature recovery. + * + * MODELING (TCB-disclosed): + * - ECDSA.recover(bytes32,bytes memory) -> uninterpreted `recoverGhost(hash)`. + * - ECDSA.toEthSignedMessageHash(bytes32) -> uninterpreted `ethHashGhost(userOpHash)`. + * - getApproval(...) -> NONDET (attacker gets `passed` and `totalWeight` + * for free; SOUND over-approximation, and removes + * the unbounded guardian linked-list loop). + * recoverGhost is keyed on the *hash* argument only. This is sound for THIS property: the + * success gate depends solely on recover over toEthSignedMessageHash(userOpHash); collapsing + * distinct-signature-same-hash recoveries can only shrink the reachable state, never hide a + * success-with-non-guardian state (which is driven by the userOpHash recovery alone). + * + * TAUTOLOGY CHECK: the postcondition asserts an access-control OUTCOME (success => the + * userOpHash signer is an enabled guardian). It does not recompute recover or the weight + * lookup; it reads guardian weight and compares the return code. Observable, not tautological. + * + * REACHABILITY: two witness rules below prove (i) success IS reachable on the Approved branch + * with a real guardian signer (non-vacuous), and (ii) the exact pre-fix bypass + * (paymasterAndData set, signature recovering to a non-guardian) now returns FAILED. + * + * @author taek + */ + +using WeightedECDSAValidatorHarness as v; + +methods { + function weightOf(address, address) external returns (uint24) envfree; + + // Uninterpreted ECDSA.recover: deterministic per message hash. + function ECDSA.recover(bytes32 hash, bytes memory) internal returns (address) => recoverGhost(hash); + // Uninterpreted EIP-191 prefixing: deterministic per raw hash. + function ECDSA.toEthSignedMessageHash(bytes32 h) internal returns (bytes32) => ethHashGhost(h); + // EIP-712 typed-data hashing for the Approve struct hash (Ongoing loop only). NONDET is + // sound: those recoveries feed the getApproval-independent vote tally, never the final gate. + function _.toEthSignedMessageHash(bytes32 h) external => ethHashGhost(h) expect bytes32; + + // Guardian linked-list tally: fully symbolic (attacker-favourable). Removes the loop. + function getApproval(address, bytes32) external returns (uint256, bool) => NONDET; +} + +ghost recoverGhost(bytes32) returns address; +ghost ethHashGhost(bytes32) returns bytes32; + +definition FAILED() returns uint256 = 1; // SIG_VALIDATION_FAILED_UINT + +/* + * MAIN PROPERTY. + * If validateUserOp does NOT return FAILED, then the signer recovered from userOp.signature + * over toEthSignedMessageHash(userOpHash) is a current guardian of the calling kernel. + * Covers BOTH success branches (Ongoing line 259 and Approved/passed line 268) and every + * value of proposal.status / passed / paymasterAndData, because the assertion is on the + * return value irrespective of which branch produced it. + */ +rule successImpliesGuardianSigned(env e, WeightedECDSAValidator.PackedUserOperation userOp, bytes32 userOpHash) { + uint256 ret = v.validateUserOp(e, userOp, userOpHash); + + address recovered = recoverGhost(ethHashGhost(userOpHash)); + + assert ret != FAILED() => weightOf(recovered, e.msg.sender) != 0, + "validateUserOp returned success but the userOpHash signer is not a current guardian"; +} + +/* + * REACHABILITY WITNESS (i) -- success is reachable (non-vacuous). + * A userOp on the Approved branch whose signature recovers to a real guardian CAN succeed. + * Stated as a violated `assert false` under satisfiable preconditions: if the tool finds a + * model, success-with-guardian is reachable. + */ +rule successReachableWithGuardian(env e, WeightedECDSAValidator.PackedUserOperation userOp, bytes32 userOpHash) { + address recovered = recoverGhost(ethHashGhost(userOpHash)); + // recovered is an enabled guardian + require weightOf(recovered, e.msg.sender) != 0; + + uint256 ret = v.validateUserOp(e, userOp, userOpHash); + + satisfy ret != FAILED(); +} + +/* + * REACHABILITY WITNESS (ii) -- the exact pre-fix bypass is now BLOCKED. + * paymasterAndData is set and the signature recovers to a NON-guardian; the call must FAIL. + * (This is a specialization of the main rule pinned to the pre-fix exploit shape, kept + * separate so the counterexample, if any, isolates the paymaster path.) + */ +rule paymasterNonGuardianFails(env e, WeightedECDSAValidator.PackedUserOperation userOp, bytes32 userOpHash) { + require userOp.paymasterAndData.length != 0; // paymaster-sponsored + address recovered = recoverGhost(ethHashGhost(userOpHash)); + require weightOf(recovered, e.msg.sender) == 0; // signer is NOT a guardian + + uint256 ret = v.validateUserOp(e, userOp, userOpHash); + + assert ret == FAILED(), + "paymaster-sponsored op with non-guardian signature returned success (pre-fix bypass)"; +} diff --git a/certora/DSHmut.conf b/certora/DSHmut.conf new file mode 100644 index 0000000..fb22b6c --- /dev/null +++ b/certora/DSHmut.conf @@ -0,0 +1,22 @@ +{ + "files": [ + "certora/harness/DefaultSecurityHookHarness.sol" + ], + "verify": "DefaultSecurityHookHarness:certora/DSHmut.spec", + "solc": "solc8.30", + "solc_via_ir": true, + "solc_optimize": "20000", + "packages": [ + "src/=src/", + "account-abstraction/=dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/", + "solady/=dependencies/solady-0.1.26/src/", + "openzeppelin-contracts/contracts/=dependencies/@openzeppelin-contracts-5.5.0/", + "forge-std/=dependencies/forge-std-1.11.0/src/" + ], + "loop_iter": "3", + "optimistic_loop": true, + "optimistic_hashing": true, + "hashing_length_bound": "384", + "global_timeout": 600, + "msg": "DSH-ALLOW-01 mutation check: mutants must be violated" +} diff --git a/certora/DSHmut.spec b/certora/DSHmut.spec new file mode 100644 index 0000000..e529a5f --- /dev/null +++ b/certora/DSHmut.spec @@ -0,0 +1,44 @@ +methods { + function checkCall(address, uint256, bytes) external; + function selOf(bytes) external returns (bytes4) envfree; + function h_allowed(address, address) external returns (bool) envfree; + function h_allSelectorsAllowed(address, address) external returns (bool) envfree; + function h_selectorMapped(address, address, bytes4) external returns (bool) envfree; + function DefaultSecurityHook._isModule(address) internal returns (bool) => notAModule(); +} +function notAModule() returns bool { return false; } + +definition BLOCKED(bytes4 s) returns bool = + s == to_bytes4(0xa9059cbb) || s == to_bytes4(0x095ea7b3) || s == to_bytes4(0x23b872dd) + || s == to_bytes4(0x39509351) || s == to_bytes4(0xa457c2d7) || s == to_bytes4(0x42842e0e) + || s == to_bytes4(0xb88d4fde) || s == to_bytes4(0xa22cb465) || s == to_bytes4(0xf242432a) + || s == to_bytes4(0x2eb2c2d6); + +definition ALLOW_PASS(address acct, address target, bytes4 sel) returns bool = + h_allowed(acct, target) && ( h_allSelectorsAllowed(acct, target) || h_selectorMapped(acct, target, sel) ); + +// MUTANT: asserts the OPPOSITE of the real property. Must be VIOLATED (counterexample), +// proving the assert path is genuinely exercised (deny rule is not vacuous). +rule mutantDenyDoesNotRevert(address target, bytes data) { + env e; + require e.msg.value == 0; + address account = e.msg.sender; + require data.length == 4; + bytes4 sel = selOf(data); + require BLOCKED(sel); + require target != account; + require !ALLOW_PASS(account, target, sel); + checkCall@withrevert(e, target, 0, data); + assert !lastReverted, "MUTANT expected to be violated"; +} + +// MUTANT: allSelectorsAllowed but asserts it DOES revert. Must be VIOLATED. +rule mutantAllPassReverts(address target, uint256 value, bytes data) { + env e; + require e.msg.value == 0; + address account = e.msg.sender; + require h_allowed(account, target); + require h_allSelectorsAllowed(account, target); + checkCall@withrevert(e, target, value, data); + assert lastReverted, "MUTANT expected to be violated"; +} diff --git a/certora/DefaultSecurityHook.conf b/certora/DefaultSecurityHook.conf new file mode 100644 index 0000000..4c8ddf6 --- /dev/null +++ b/certora/DefaultSecurityHook.conf @@ -0,0 +1,23 @@ +{ + "files": [ + "certora/harness/DefaultSecurityHookHarness.sol" + ], + "verify": "DefaultSecurityHookHarness:certora/DefaultSecurityHook.spec", + "solc": "solc8.30", + "solc_via_ir": true, + "solc_optimize": "20000", + "packages": [ + "src/=src/", + "account-abstraction/=dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/", + "solady/=dependencies/solady-0.1.26/src/", + "openzeppelin-contracts/contracts/=dependencies/@openzeppelin-contracts-5.5.0/", + "forge-std/=dependencies/forge-std-1.11.0/src/" + ], + "loop_iter": "3", + "optimistic_loop": true, + "optimistic_hashing": true, + "hashing_length_bound": "384", + "rule_sanity": "basic", + "global_timeout": 600, + "msg": "DSH-ALLOW-01: allowlist gating exact - blocked non-allowlisted selector reverts" +} diff --git a/certora/DefaultSecurityHook.spec b/certora/DefaultSecurityHook.spec new file mode 100644 index 0000000..fcf28fb --- /dev/null +++ b/certora/DefaultSecurityHook.spec @@ -0,0 +1,137 @@ +/* + * DSH-ALLOW-01 — Allowlist gating is exact for blocked token selectors. + * + * Target: DefaultSecurityHook._checkCall (exposed via harness `checkCall`). + * + * OBSERVABLE property (not a recompute of _isBlockedSelector): + * Given `sel` (the leading-4-byte selector of `data`, exactly as _checkCall reads + * it) already CONSTRAINED to be one of the 10 blocked selectors — an INPUT + * constraint, NOT a postcondition re-derivation — and given a non-self / non-module + * / zero-value target: + * - if NOT ( allowed && (allSelectorsAllowed || selectorMapped) ) then checkCall + * MUST revert. Self / module / ETH branches are excluded by the preconditions, + * so the only reachable revert is TokenTransferNotAllowed. + * Conversely: + * - if allSelectorsAllowed for the target, checkCall MUST NOT revert regardless of + * selector or value. + * + * The allowlist facts are read via observable harness accessors + * (h_allowed / h_allSelectorsAllowed / h_selectorMapped) — state reads, not a + * reimplementation of blocked-set membership. `sel` comes from selOf (a calldata + * slice), the SAME key _checkCall uses for the mapping lookup. + */ + +methods { + function checkCall(address, uint256, bytes) external; // NOT envfree: reads msg.sender (the account) + function selOf(bytes) external returns (bytes4) envfree; // bytes4(data[:4]) as _checkCall reads it + function h_allowed(address, address) external returns (bool) envfree; + function h_allSelectorsAllowed(address, address) external returns (bool) envfree; + function h_selectorMapped(address, address, bytes4) external returns (bool) envfree; + + // _isModule(target) does a raw staticcall probe to `target`. We summarize the + // internal function directly to `false`, pinning the STATEMENT's "non-module" + // precondition: the module-revert branch is never taken, so a non-allowlisted + // blocked selector must flow to the TokenTransferNotAllowed branch. + // (The converse rule returns via the allowlist branch before _isModule is reached, + // so this summary does not affect it.) + function DefaultSecurityHook._isModule(address) internal returns (bool) => notAModule(); +} + +// Non-module summary for _isModule (see methods note). +function notAModule() returns bool { + return false; +} + +// The 10 blocked selectors (input-constraint constants; see tautology note above). +definition BLOCKED(bytes4 s) returns bool = + s == to_bytes4(0xa9059cbb) // transfer(address,uint256) + || s == to_bytes4(0x095ea7b3) // approve(address,uint256) + || s == to_bytes4(0x23b872dd) // transferFrom(address,address,uint256) + || s == to_bytes4(0x39509351) // increaseAllowance(address,uint256) + || s == to_bytes4(0xa457c2d7) // decreaseAllowance(address,uint256) + || s == to_bytes4(0x42842e0e) // safeTransferFrom(address,address,uint256) + || s == to_bytes4(0xb88d4fde) // safeTransferFrom(address,address,uint256,bytes) + || s == to_bytes4(0xa22cb465) // setApprovalForAll(address,bool) + || s == to_bytes4(0xf242432a) // safeTransferFrom(address,address,uint256,uint256,bytes) + || s == to_bytes4(0x2eb2c2d6); // safeBatchTransferFrom(...) + +// Observable "allowlisted pass" predicate over harness state reads. +definition ALLOW_PASS(address acct, address target, bytes4 sel) returns bool = + h_allowed(acct, target) && ( h_allSelectorsAllowed(acct, target) || h_selectorMapped(acct, target, sel) ); + +// --------------------------------------------------------------------------- +// MAIN RULE: deny direction (security-critical). +// A blocked selector to a non-self, non-module, zero-value target that is NOT +// allowlist-passing MUST revert. +// --------------------------------------------------------------------------- +rule blockedSelectorDenyReverts(address target, bytes data) { + env e; + require e.msg.value == 0; + address account = e.msg.sender; // account == msg.sender inside _checkCall + + require data.length == 4; // full selector determined, no trailing bytes + bytes4 sel = selOf(data); // == bytes4(data[:4]) as _checkCall reads it + + // INPUT constraint: selector is a blocked one (not a postcondition re-derivation). + require BLOCKED(sel); + + // Preconditions from the STATEMENT: non-self (target!=account), non-module + // (_isModule summarized false), zero value (value==0 arg below). + require target != account; + require !ALLOW_PASS(account, target, sel); + + checkCall@withrevert(e, target, /*value*/ 0, data); + + // With self / module / ETH branches excluded, the ONLY reachable revert is + // TokenTransferNotAllowed. Assert it reverts. + assert lastReverted, "Blocked, non-allowlisted, non-module, zero-value call did not revert"; +} + +// --------------------------------------------------------------------------- +// CONVERSE RULE: allSelectorsAllowed => never reverts regardless of selector/value. +// --------------------------------------------------------------------------- +rule allSelectorsAllowedNeverReverts(address target, uint256 value, bytes data) { + env e; + require e.msg.value == 0; + address account = e.msg.sender; + + require h_allowed(account, target); + require h_allSelectorsAllowed(account, target); + + checkCall@withrevert(e, target, value, data); + + assert !lastReverted, "allSelectorsAllowed target reverted"; +} + +// --------------------------------------------------------------------------- +// REACHABILITY WITNESS 1 (mandatory): deny branch is reachable. +// --------------------------------------------------------------------------- +rule witnessBlockedReverts(address target, bytes data) { + env e; + require e.msg.value == 0; + address account = e.msg.sender; + + require data.length == 4; + bytes4 sel = selOf(data); + require BLOCKED(sel); + require target != account; + require !ALLOW_PASS(account, target, sel); + + checkCall@withrevert(e, target, 0, data); + satisfy lastReverted, "no model where a blocked non-allowlisted call reverts"; +} + +// --------------------------------------------------------------------------- +// REACHABILITY WITNESS 2 (mandatory): pass branch is reachable. +// --------------------------------------------------------------------------- +rule witnessAllowlistedPasses(address target, bytes data) { + env e; + require e.msg.value == 0; + address account = e.msg.sender; + + require h_allowed(account, target); + require h_allSelectorsAllowed(account, target); + + checkCall@withrevert(e, target, 0, data); + satisfy !lastReverted, "no model where an allSelectorsAllowed call passes"; +} diff --git a/certora/DefaultSecurityHookBatch.conf b/certora/DefaultSecurityHookBatch.conf new file mode 100644 index 0000000..fbadd6c --- /dev/null +++ b/certora/DefaultSecurityHookBatch.conf @@ -0,0 +1,23 @@ +{ + "files": [ + "certora/harness/DefaultSecurityHookBatchHarness.sol" + ], + "verify": "DefaultSecurityHookBatchHarness:certora/DefaultSecurityHookBatch.spec", + "solc": "solc8.30", + "solc_via_ir": true, + "solc_optimize": "20000", + "packages": [ + "src/=src/", + "account-abstraction/=dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/", + "solady/=dependencies/solady-0.1.26/src/", + "openzeppelin-contracts/contracts/=dependencies/@openzeppelin-contracts-5.5.0/", + "forge-std/=dependencies/forge-std-1.11.0/src/" + ], + "loop_iter": "3", + "optimistic_loop": true, + "optimistic_hashing": true, + "hashing_length_bound": "384", + "rule_sanity": "basic", + "global_timeout": 600, + "msg": "DSH-BATCH-01 req-17 BATCH mode reverts whole tx on any deny-violating sub-call and all-clean batch returns" +} diff --git a/certora/DefaultSecurityHookBatch.spec b/certora/DefaultSecurityHookBatch.spec new file mode 100644 index 0000000..c323631 --- /dev/null +++ b/certora/DefaultSecurityHookBatch.spec @@ -0,0 +1,102 @@ +/* + * DSH-BATCH-01 (spec ^req-17, audit Medium): BATCH-mode all-or-nothing deny enforcement. + * + * PROPERTY (no partial acceptance): + * In BATCH mode, preCheck loops over the decoded sub-calls and invokes _checkCall on each + * (src/hooks/DefaultSecurityHook.sol, CALLTYPE_BATCH branch). A revert in ANY iteration + * aborts the whole call. Therefore: + * (1) if ANY sub-call is a deny violation, the WHOLE batch reverts (a bad sub-call can + * never slip through by being batched with clean sub-calls); and + * (2) a batch whose sub-calls are ALL allowlisted-clean returns without revert. + * + * TARGET / LOOP: + * The aggregation is the loop `for (i) { (t,v,d)=getExecution(pointers,i); _checkCall(t,v,d); }`. + * The harness `checkBatch(Call[])` is a faithful replica of that loop body: it calls the SAME + * internal `_checkCall` per element. This isolates the all-or-nothing revert aggregation + * (the ^req-17 claim) from LibERC7579's calldata-pointer decoding, which is a decoder concern. + * loop_iter=3 fully unrolls the N=2 batches used here. + * + * VIOLATION MODELED: a SELF-CALL to a non-allowlisted target. _checkCall reverts at + * `if (target == msg.sender) revert SelfCallNotAllowed()` BEFORE the _isModule probe, so the + * revert is deterministic and independent of the _isModule summary. + * CLEAN MODELED: an allowlisted target with allSelectorsAllowed. _checkCall returns at the + * first branch `if (entry.allowed) { if (allSelectorsAllowed) return; }`, also before _isModule. + * + * TAUTOLOGY CHECK: postconditions assert the aggregate revert / return outcome of checkBatch + * (lastReverted / !lastReverted). They do NOT recompute the per-call deny checks. Observable. + * + * REACHABILITY (mandatory): rule cleanBatchReturns_witness `satisfy`s a fully-clean 2-element + * batch that returns (non-vacuous); the deny rules assert on batches whose clean element + * proves the reverting element is not the only reachable configuration. + * + * MODELING (TCB-disclosed): + * - _isModule's low-level staticcall to target.isModuleType is an unresolved external call; + * summarized NONDET. SOUND and in fact never reached on the paths these rules exercise + * (both the self-call violation and the allowlisted-clean path short-circuit earlier). + * + * @author taek + */ + +methods { + function checkBatch(DefaultSecurityHookBatchHarness.Call[] calls) external; + function h_allowed(address account, address target) external returns (bool) envfree; + function h_allSelectorsAllowed(address account, address target) external returns (bool) envfree; + + // _isModule staticcall to arbitrary target: unresolved -> NONDET (sound; unreached here). + function _.isModuleType(uint256) external => NONDET; +} + +/* + * MAIN PROPERTY (DSH-BATCH-01): no partial acceptance. + * A 2-element batch: one element is a clean allowlisted call, the other is a self-call to a + * non-allowlisted target (a deny violation). Whichever position (bad in {0,1}) the violation + * occupies, the WHOLE checkBatch must revert. A bad sub-call cannot slip through by batching. + */ +rule anyBadSubcallRevertsWholeBatch(uint256 bad) { + env e; + address account = e.msg.sender; + + DefaultSecurityHookBatchHarness.Call[] calls; + require calls.length == 2; + require bad < 2; + uint256 good = bad == 0 ? 1 : 0; + + // The clean element: an allowlisted target with all selectors allowed (returns immediately). + address cleanTarget = calls[good].target; + require cleanTarget != account; // not a self-call + require h_allowed(account, cleanTarget); + require h_allSelectorsAllowed(account, cleanTarget); + + // The bad element: a self-call to a NON-allowlisted target (reverts: SelfCallNotAllowed). + require calls[bad].target == account; + require !h_allowed(account, account); + + checkBatch@withrevert(e, calls); + + assert lastReverted, + "a deny-violating sub-call slipped through by being batched with a clean sub-call"; +} + +/* + * CLEAN-BATCH RETURN (converse) + REACHABILITY WITNESS. + * A 2-element batch where BOTH sub-calls are allowlisted-clean must be able to return + * without reverting. `satisfy` proves this state is reachable (non-vacuous), simultaneously + * establishing the converse: an all-clean batch is NOT forced to revert. + */ +rule cleanBatchReturns_witness { + env e; + address account = e.msg.sender; + + DefaultSecurityHookBatchHarness.Call[] calls; + require calls.length == 2; + + address t0 = calls[0].target; + address t1 = calls[1].target; + require t0 != account && t1 != account; // no self-calls + require h_allowed(account, t0) && h_allSelectorsAllowed(account, t0); + require h_allowed(account, t1) && h_allSelectorsAllowed(account, t1); + + checkBatch@withrevert(e, calls); + + satisfy !lastReverted; +} diff --git a/certora/ECDSAValidator.conf b/certora/ECDSAValidator.conf new file mode 100644 index 0000000..fb032a9 --- /dev/null +++ b/certora/ECDSAValidator.conf @@ -0,0 +1,21 @@ +{ + "files": [ + "certora/harness/ECDSAValidatorHarness.sol" + ], + "verify": "ECDSAValidatorHarness:certora/ECDSAValidator.spec", + "solc": "solc8.30", + "solc_via_ir": true, + "solc_optimize": "20000", + "packages": [ + "src/=src/", + "account-abstraction/=dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/", + "solady/=dependencies/solady-0.1.26/src/", + "openzeppelin-contracts/contracts/=dependencies/@openzeppelin-contracts-5.5.0/", + "forge-std/=dependencies/forge-std-1.11.0/src/" + ], + "loop_iter": "3", + "optimistic_loop": true, + "rule_sanity": "basic", + "global_timeout": 1200, + "msg": "TOB-13 ECDSAValidator.validateUserOp success implies nonzero owner and recover image matches owner" +} diff --git a/certora/ECDSAValidator.spec b/certora/ECDSAValidator.spec new file mode 100644 index 0000000..19e4362 --- /dev/null +++ b/certora/ECDSAValidator.spec @@ -0,0 +1,126 @@ +/* + * TOB-13 (audit High, priv-esc): validateUserOp returns SIG_VALIDATION_SUCCESS_UINT (0) + * ONLY IF the configured owner != address(0) AND the recovered signer of userOpHash + * (or its eth-signed variant) equals owner. Contrapositive/observable form: + * + * return == SUCCESS => ( owner != 0 + * && ( recovered(userOpHash) == owner + * || recovered(ethHash) == owner ) ) + * + * Plus the anti-address(0)-match guard (the TOB-13 fix): + * + * owner == 0 => return == FAILED + * + * Target: src/validators/ECDSAValidator.sol validateUserOp :69-81 (owner==0 early-fail :77, + * _verifySignature gate :78), _verifySignature :60-67. + * + * ECDSA.tryRecoverCalldata is modeled UNINTERPRETED: `recovered(hash)` is a symbolic, + * attacker-controlled address, DETERMINISTIC in hash (same hash -> same recovered address). + * The two impl recover calls (raw userOpHash and eth-signed variant) map to two independent + * symbolic images. The proof covers AUTHORIZATION GATING, not ECDSA / ecrecover soundness. + * + * OBSERVABLE, NOT TAUTOLOGICAL: the assertion references the SAME uninterpreted oracle the + * impl consumes; it never re-derives elliptic-curve math. It relates the observable RETURN + * value to owner and the oracle image. + * + * @author taek + */ + +methods { + function validateUserOpHarness(bytes32) external returns (uint256); + function ownerOf(address) external returns (address) envfree; + function _recover(bytes32 hash) internal returns (address) => recovered(hash); + function _ethHash(bytes32 hash) internal returns (bytes32) => ethSignedHash(hash); +} + +// Uninterpreted, deterministic-per-hash recovery. Same hash -> same address. +ghost recovered(bytes32) returns address; + +// Uninterpreted, injective eth-signed-hash derivation. Same hash -> same eth-hash, and the +// eth-hash is never equal to the raw hash (the real keccak-prefix construction is collision- +// resistant), so the two recover queries hit genuinely independent oracle images. +ghost ethSignedHash(bytes32) returns bytes32 { + axiom forall bytes32 h. ethSignedHash(h) != h; + axiom forall bytes32 a. forall bytes32 b. a != b => ethSignedHash(a) != ethSignedHash(b); +} + +definition SUCCESS() returns uint256 = 0; +definition FAILED() returns uint256 = 1; + +/* + * MAIN PROPERTY (contrapositive, observable). + * If validateUserOp returns SUCCESS then owner != 0 AND at least one of the two recover + * oracle images equals owner. Uses the SAME `recovered` oracle the impl consumes -- no + * re-derivation of ECDSA math. + * + * We cannot name ethHash directly in CVL without recomputing the prefix, so we assert the + * disjunction over ALL hashes: SUCCESS with a nonzero owner implies there EXISTS a hash h + * with recovered(h) == owner. Because the impl only ever queries recovered at exactly two + * hashes and returns SUCCESS solely when one of those images matches owner, this is the + * tightest observable claim that avoids recomputing toEthSignedMessageHash. + */ +rule successImpliesOwnerRecovered(bytes32 userOpHash) { + env e; + require e.msg.value == 0; // validateUserOpHarness is view; msg.value irrelevant + + address owner = ownerOf(e.msg.sender); + + uint256 ret = validateUserOpHarness(e, userOpHash); + + // (1) owner must be nonzero on success. + assert ret == SUCCESS() => owner != 0, + "SUCCESS returned with unset owner (address(0)) -- TOB-13 guard broken"; + + // (2) on success, owner equals the recover oracle at the raw hash OR at the eth-signed + // hash. We express the eth-signed hash via the concrete solady computation. + assert ret == SUCCESS() => + ( recovered(userOpHash) == owner + || recovered(ethSignedHash(userOpHash)) == owner ), + "SUCCESS returned but neither recover image matches owner -- non-owner op validated"; +} + +/* + * ANTI-address(0)-MATCH GUARD (the explicit TOB-13 fix). + * owner == 0 must ALWAYS yield FAILED, regardless of what recover returns -- in particular + * even if recover returns address(0) (the classic failed-recovery sentinel), it must NOT be + * treated as a match against an unset (zero) owner. + */ +rule zeroOwnerAlwaysFails(bytes32 userOpHash) { + env e; + require ownerOf(e.msg.sender) == 0; + + uint256 ret = validateUserOpHarness(e, userOpHash); + + assert ret == FAILED(), + "owner == 0 did not fail -- address(0) recover match bypass (TOB-13)"; +} + +/* + * REACHABILITY WITNESS (i) -- SUCCESS is reachable (non-vacuous accept). + * There EXISTS a model with a nonzero owner whose raw-hash recover image equals owner and + * validateUserOp returns SUCCESS. + */ +rule witnessSuccessReachable(bytes32 userOpHash) { + env e; + address owner = ownerOf(e.msg.sender); + require owner != 0; + require recovered(userOpHash) == owner; // legitimate owner signature on the raw hash + + uint256 ret = validateUserOpHarness(e, userOpHash); + + satisfy ret == SUCCESS(), + "no reachable SUCCESS -- accept path is vacuous"; +} + +/* + * REACHABILITY WITNESS (ii) -- FAILURE is reachable (owner==0 branch is live). + */ +rule witnessZeroOwnerFailReachable(bytes32 userOpHash) { + env e; + require ownerOf(e.msg.sender) == 0; + + uint256 ret = validateUserOpHarness(e, userOpHash); + + satisfy ret == FAILED(), + "no reachable FAILED on the owner==0 branch"; +} diff --git a/certora/S01Probe.conf b/certora/S01Probe.conf new file mode 100644 index 0000000..c4e3887 --- /dev/null +++ b/certora/S01Probe.conf @@ -0,0 +1,23 @@ +{ + "files": [ + "certora/harness/S01Harness.sol" + ], + "verify": "S01Harness:certora/S01Probe.spec", + "solc": "solc8.30", + "solc_via_ir": true, + "solc_optimize": "20000", + "packages": [ + "src/=src/", + "account-abstraction/=dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/", + "solady/=dependencies/solady-0.1.26/src/", + "openzeppelin-contracts/contracts/=dependencies/@openzeppelin-contracts-5.5.0/", + "forge-std/=dependencies/forge-std-1.11.0/src/" + ], + "loop_iter": "3", + "optimistic_loop": true, + "optimistic_hashing": true, + "hashing_length_bound": "384", + "rule_sanity": "basic", + "global_timeout": 600, + "msg": "S-01: stale allowlist selector B cleared after setAllowlist drop (no APPROVE bypass)" +} diff --git a/certora/S01Probe.spec b/certora/S01Probe.spec new file mode 100644 index 0000000..54ab1a5 --- /dev/null +++ b/certora/S01Probe.spec @@ -0,0 +1,65 @@ +methods { + function setAllowlist(address target, bytes4[] selectors) external; + function isSelectorAllowed(address account, address target, bytes4 selector) external returns (bool) envfree; + function isInitialized(address account) external returns (bool) envfree; + function entryPristine(address account, address target, bytes4 selector) external returns (bool) envfree; + function selectorListLen(address account, address target) external returns (uint256) envfree; + function selectorMapped(address account, address target, bytes4 selector) external returns (bool) envfree; + function seedSingle(address account, address target, bytes4 sel) external; + function _.isModuleType(uint256) external => NONDET; +} + +// Isolated clear-loop test: seed selectorList=[b], then setAllowlist([a]); b must clear. +rule seededClearLoop(address target, bytes4 a, bytes4 b) { + env e; + address account = e.msg.sender; + require a != b; + seedSingle(e, account, target, b); + // sanity: seed took + require selectorMapped(account, target, b) == true; + require selectorListLen(account, target) == 1; + bytes4[] onlyA; + require onlyA.length == 1; + require onlyA[0] == a; + setAllowlist(e, target, onlyA); + assert selectorMapped(account, target, b) == false, "seeded b not cleared by setAllowlist([a])"; +} + +// After pristine start + set[A,B], both A and B are allowed, selectorList length 2. +rule afterFirstSet(address target, bytes4 a, bytes4 b) { + env e; + address account = e.msg.sender; + require isInitialized(account); + require a != b; + require entryPristine(account, target, a); + require entryPristine(account, target, b); + bytes4[] both; + require both.length == 2; + require both[0] == a; + require both[1] == b; + setAllowlist(e, target, both); + assert selectorListLen(account, target) == 2, "selectorList not length 2 after first set"; + assert selectorMapped(account, target, a) == true, "a not mapped after first set"; + assert selectorMapped(account, target, b) == true, "b not mapped after first set"; +} + +// After pristine + set[A,B] + set[A], B mapping is cleared. +rule afterSecondSet(address target, bytes4 a, bytes4 b) { + env e; + require e.msg.sender == e.msg.sender; + address account = e.msg.sender; + require isInitialized(account); + require a != b; + require entryPristine(account, target, a); + require entryPristine(account, target, b); + bytes4[] both; + require both.length == 2; + require both[0] == a; + require both[1] == b; + setAllowlist(e, target, both); + bytes4[] onlyA; + require onlyA.length == 1; + require onlyA[0] == a; + setAllowlist(e, target, onlyA); + assert selectorMapped(account, target, b) == false, "b mapping not cleared after second set"; +} diff --git a/certora/S01Probe4.conf b/certora/S01Probe4.conf new file mode 100644 index 0000000..7a15932 --- /dev/null +++ b/certora/S01Probe4.conf @@ -0,0 +1,23 @@ +{ + "files": [ + "certora/harness/S01Harness.sol" + ], + "verify": "S01Harness:certora/S01Probe.spec", + "solc": "solc8.30", + "solc_via_ir": true, + "solc_optimize": "20000", + "packages": [ + "src/=src/", + "account-abstraction/=dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/", + "solady/=dependencies/solady-0.1.26/src/", + "openzeppelin-contracts/contracts/=dependencies/@openzeppelin-contracts-5.5.0/", + "forge-std/=dependencies/forge-std-1.11.0/src/" + ], + "loop_iter": "4", + "optimistic_loop": true, + "optimistic_hashing": true, + "hashing_length_bound": "384", + "rule_sanity": "basic", + "global_timeout": 600, + "msg": "S-01: stale allowlist selector B cleared after setAllowlist drop (no APPROVE bypass)" +} diff --git a/certora/S01ProbeNoIR.conf b/certora/S01ProbeNoIR.conf new file mode 100644 index 0000000..ff76cbf --- /dev/null +++ b/certora/S01ProbeNoIR.conf @@ -0,0 +1,22 @@ +{ + "files": [ + "certora/harness/S01Harness.sol" + ], + "verify": "S01Harness:certora/S01Probe.spec", + "solc": "solc8.30", + "solc_via_ir": false, + "packages": [ + "src/=src/", + "account-abstraction/=dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/", + "solady/=dependencies/solady-0.1.26/src/", + "openzeppelin-contracts/contracts/=dependencies/@openzeppelin-contracts-5.5.0/", + "forge-std/=dependencies/forge-std-1.11.0/src/" + ], + "loop_iter": "3", + "optimistic_loop": true, + "optimistic_hashing": true, + "hashing_length_bound": "384", + "rule_sanity": "basic", + "global_timeout": 600, + "msg": "S-01 probe: seeded clear loop, via-ir OFF" +} \ No newline at end of file diff --git a/certora/S01StaleSelector.conf b/certora/S01StaleSelector.conf new file mode 100644 index 0000000..cced381 --- /dev/null +++ b/certora/S01StaleSelector.conf @@ -0,0 +1,21 @@ +{ + "files": [ + "certora/harness/S01Harness.sol" + ], + "verify": "S01Harness:certora/S01StaleSelector.spec", + "solc": "solc8.30", + "packages": [ + "src/=src/", + "account-abstraction/=dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/", + "solady/=dependencies/solady-0.1.26/src/", + "openzeppelin-contracts/contracts/=dependencies/@openzeppelin-contracts-5.5.0/", + "forge-std/=dependencies/forge-std-1.11.0/src/" + ], + "loop_iter": "3", + "optimistic_loop": true, + "optimistic_hashing": true, + "hashing_length_bound": "384", + "rule_sanity": "basic", + "global_timeout": 600, + "msg": "S-01: stale allowlist selector B cleared after setAllowlist drop (no APPROVE bypass)" +} diff --git a/certora/S01StaleSelector.spec b/certora/S01StaleSelector.spec new file mode 100644 index 0000000..c07fad4 --- /dev/null +++ b/certora/S01StaleSelector.spec @@ -0,0 +1,168 @@ +/* + * S-01 (audit HIGH regression, spec ^req-14): stale-selector clearing in _setAllowlist. + * + * PROPERTY: + * For an initialized account, given two distinct selectors A != B, calling + * setAllowlist(target, [A, B]) then setAllowlist(target, [A]) + * (both from the same account = msg.sender) leaves the account in a state where + * isSelectorAllowed(account, target, B) == false AND + * isSelectorAllowed(account, target, A) == true. + * The second setAllowlist must CLEAR the stale B mapping entry (the S-01 fix: the + * clear loop over entry.selectorList in _setAllowlist), otherwise B would remain + * permitted and — if B is a blocked token selector (APPROVE) — bypass the + * blocked-selector guard, draining tokens. + * + * Target : src/hooks/DefaultSecurityHook.sol + * _setAllowlist (selectorList tracking + clear loop; the S-01 fix) + * isSelectorAllowed (observable view read) + * _checkCall (blocked-selector revert path, via harness checkCall) + * + * TAUTOLOGY CHECK: the postcondition reads the observable mapping result via + * isSelectorAllowed and the revert outcome of checkCall. It never re-runs the clear + * loop or recomputes selectorList. Observable, not tautological. + * + * REACHABILITY: rule s01_reachability_witness proves the two setAllowlist calls both + * execute non-reverting under the precondition and land in the asserted final state + * (B false, A true) — rules out vacuous-by-unreachable-precondition. + * + * MODELING (TCB-disclosed): + * - The _isModule low-level staticcall to target.isModuleType is an unresolved external + * call; summarized NONDET. SOUND for the revert claim: were it to return true, + * _checkCall reverts EARLIER with ModuleCallNotAllowed — still a revert. + * - Compiled WITHOUT solc --via-ir (see .conf). The via-ir + optimizer pipeline + * mis-modeled the struct-embedded `mapping(bytes4=>bool) selectors` co-located with + * the `bytes4[] selectorList`: the clear-loop write `selectors[selectorList[i]]=false` + * did not alias the slot `isSelectorAllowed` reads, producing spurious CEs. The + * legacy (non-via-ir) codegen models this storage layout correctly; the Foundry + * regression test test_S01_StaleSelectorsAreClearedOnAllowlistUpdate independently + * confirms the impl is correct on real EVM semantics. + * - Freshly-initialized-account precondition asserted via entryPristine (the audit + * scenario). CVL cannot read the in-struct mapping, so pre-state cleanliness for A + * and B is pinned through this observable harness read — not a clear-loop recompute. + * + * @author taek + */ + +methods { + function setAllowlist(address target, bytes4[] selectors) external; + function isSelectorAllowed(address account, address target, bytes4 selector) external returns (bool) envfree; + function isInitialized(address account) external returns (bool) envfree; + function checkCall(address target, uint256 value, bytes data) external; + function approveSelector() external returns (bytes4) envfree; + function leadingSelector(bytes data) external returns (bytes4) envfree; + function entryPristine(address account, address target, bytes4 selector) external returns (bool) envfree; + + // _isModule staticcall to arbitrary target: unresolved -> NONDET (sound over-approx). + function _.isModuleType(uint256) external => NONDET; +} + +/* + * MAIN PROPERTY (S-01). + * Two setAllowlist calls from the same account; the second drops B from [A, B] to [A]. + * After the sequence, B must be de-permitted while A remains permitted. + */ +rule staleSelectorClearedAfterSetAllowlist(address target, bytes4 a, bytes4 b) { + env e1; + env e2; + + address account = e1.msg.sender; + require e2.msg.sender == account; // same account performs both calls + + require isInitialized(account); + require a != b; + + // Audit scenario: freshly-initialized hook, no prior allowlist for target. + // (CVL cannot see the mapping inside AllowlistEntry, so cleanliness is asserted + // via the observable entryPristine read — not a recompute of the clear loop.) + require entryPristine(account, target, a); + require entryPristine(account, target, b); + + bytes4[] both; + require both.length == 2; + require both[0] == a; + require both[1] == b; + setAllowlist(e1, target, both); + + bytes4[] onlyA; + require onlyA.length == 1; + require onlyA[0] == a; + setAllowlist(e2, target, onlyA); + + assert isSelectorAllowed(account, target, b) == false, + "stale selector B remained allowlist-permitted after being dropped"; + assert isSelectorAllowed(account, target, a) == true, + "selector A was incorrectly de-permitted"; +} + +/* + * BLOCKED-SELECTOR REVERT COROLLARY. + * If B is a blocked token selector (APPROVE), after the drop a call to target with a + * 4-byte calldata equal to B must revert in _checkCall (no allowlist bypass). + * `data` is a rule-parameter bytes constrained to length 4 with first-4-bytes == B. + */ +rule blockedStaleSelectorCallReverts(address target, bytes4 a, bytes data) { + env e1; + env e2; + env eCall; + + address account = e1.msg.sender; + require e2.msg.sender == account; + require eCall.msg.sender == account; + + bytes4 b = approveSelector(); // concrete blocked selector + require isInitialized(account); + require a != b; + + require entryPristine(account, target, a); + require entryPristine(account, target, b); + + // data = a call whose leading selector is B (>= 4 bytes). + require data.length >= 4; + require leadingSelector(data) == b; + + bytes4[] both; + require both.length == 2; + require both[0] == a; + require both[1] == b; + setAllowlist(e1, target, both); + + bytes4[] onlyA; + require onlyA.length == 1; + require onlyA[0] == a; + setAllowlist(e2, target, onlyA); + + checkCall@withrevert(eCall, target, 0, data); + + assert lastReverted, "blocked stale selector B was permitted through _checkCall"; +} + +/* + * REACHABILITY WITNESS (mandatory): both setAllowlist calls execute non-reverting and the + * asserted final state (B false, A true) is actually reachable. satisfy => non-vacuous. + */ +rule s01_reachability_witness(address target, bytes4 a, bytes4 b) { + env e1; + env e2; + + address account = e1.msg.sender; + require e2.msg.sender == account; + require isInitialized(account); + require a != b; + + require entryPristine(account, target, a); + require entryPristine(account, target, b); + + bytes4[] both; + require both.length == 2; + require both[0] == a; + require both[1] == b; + setAllowlist(e1, target, both); + + bytes4[] onlyA; + require onlyA.length == 1; + require onlyA[0] == a; + setAllowlist(e2, target, onlyA); + + satisfy isSelectorAllowed(account, target, b) == false + && isSelectorAllowed(account, target, a) == true; +} diff --git a/certora/S02StaleReinstall.conf b/certora/S02StaleReinstall.conf new file mode 100644 index 0000000..3e5f123 --- /dev/null +++ b/certora/S02StaleReinstall.conf @@ -0,0 +1,23 @@ +{ + "files": [ + "certora/harness/S02Harness.sol" + ], + "verify": "S02Harness:certora/S02StaleReinstall.spec", + "solc": "solc8.30", + "solc_via_ir": true, + "solc_optimize": "20000", + "packages": [ + "src/=src/", + "account-abstraction/=dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/", + "solady/=dependencies/solady-0.1.26/src/", + "openzeppelin-contracts/contracts/=dependencies/@openzeppelin-contracts-5.5.0/", + "forge-std/=dependencies/forge-std-1.11.0/src/" + ], + "loop_iter": "3", + "optimistic_loop": true, + "optimistic_hashing": true, + "hashing_length_bound": "384", + "rule_sanity": "basic", + "global_timeout": 600, + "msg": "S-02 (TOB-2): stale proposal from a prior installation never validates after reinstall" +} diff --git a/certora/S02StaleReinstall.spec b/certora/S02StaleReinstall.spec new file mode 100644 index 0000000..c159135 --- /dev/null +++ b/certora/S02StaleReinstall.spec @@ -0,0 +1,142 @@ +/* + * S-02 (TOB-2): a proposal created under a PRIOR installation can never validate for execution + * after a reinstall. + * + * Target: src/policies/TimelockPolicy.sol + * _policyOninstall :113 currentEpoch[id][msg.sender]++ (bump on every install) + * creation :227-232 stamps proposal.epoch = currentEpoch[id][account] + * _handleProposalExecutionInternal :256 if (proposal.epoch != currentEpoch) return FAILED + * + * PROPERTY (main, genuine trace — NOT a planted epoch): + * install(id) [epoch 0->1] -> createProposal(triple) [stamps epoch 1] + * uninstall(id) -> install(id) [reinstall, epoch 1->2] + * execUserOp(triple) == FAILED AND proposal stays Pending (never Executed). + * The staleness is produced by the REAL install bump, not by the spec choosing the epoch — so + * this witnesses the multi-step state machine the audit finding is about. + * + * TAUTOLOGY CHECK: the postcondition reads the OBSERVABLE execution return sentinel (FAILED==1) + * and the OBSERVABLE proposal status (statusOf on the real mapping). It never recomputes the + * epoch counter nor re-runs the :256 gate. The harness install/create/exec paths all run the + * REAL contract code (currentEpoch++ and the epoch comparison are the production expressions). + * Observable, not tautological. + * + * REACHABILITY (mandatory, non-vacuity): + * - reach_successWithoutReinstall: WITHOUT a reinstall the same trace EXECUTES successfully + * (non-FAILED, status Executed). Proves the failure in the main rule is a real epoch + * discriminator, not because execution always fails. + * - reach_staleCrossEpochState: the cross-epoch stale state (proposal.epoch < currentEpoch, + * status Pending) is actually reachable through the real bump. + * + * MODELING (TCB-disclosed): + * - solc 0.8.30 via-ir + optimizer (matches production build); Prover rule_sanity=basic. + * - One (account, callData, nonce) triple fixed across create/execute/read; keccak injectivity + * assumed via optimistic_hashing so all ops hit the same slot. No ECDSA in these paths. + * - Install driven through the real PolicyBase.onInstall; the wallet is the harness's + * msg.sender (currentEpoch keyed by msg.sender inside _policyOninstall). No unresolved + * external calls; no summaries needed. + * + * @author taek + */ + +methods { + function install(bytes32 id, bytes config) external; + function uninstall(bytes32 id, bytes data) external; + function createProposal(bytes32 id, address account, bytes callData, uint256 nonce, uint48 validAfter, uint48 validUntil) external; + function execUserOp(bytes32 id, address account, bytes callData, uint256 nonce) external returns (uint256); + function statusOf(bytes32 id, address wallet, address account, bytes callData, uint256 nonce) external returns (uint8) envfree; + function epochOf(bytes32 id, address wallet, address account, bytes callData, uint256 nonce) external returns (uint256) envfree; + function currentEpochOf(bytes32 id, address wallet) external returns (uint256) envfree; + function isInitialized(bytes32 id, address wallet) external returns (bool) envfree; + function ST_PENDING() external returns (uint8) envfree; + function sigFailedSentinel() external returns (uint256) envfree; +} + +/* --------------------------------------------------------------------------------------------- + * MAIN: proposal from a prior installation cannot validate after reinstall. + * + * `cfg1`/`cfg2` are symbolic install-config bytes handed to the REAL _policyOninstall. A + * non-@withrevert call whose config fails a guard (delay/exp/overflow, or the AlreadyInitialized + * check) is an infeasible path the Prover drops — so the rule reasons only over config bytes for + * which both installs actually succeed and the epoch really bumped 0->1 then 1->2. + * ------------------------------------------------------------------------------------------- */ +rule staleProposalNeverValidatesAfterReinstall( + bytes32 id, bytes callData, uint256 nonce, uint48 va, uint48 vu, bytes cfg1, bytes cfg2, bytes ucfg +) { + env eInstall1; env eCreate; env eUninstall; env eInstall2; env eExec; + + address account = eInstall1.msg.sender; + // The wallet in currentEpoch/config is keyed by the installer's msg.sender; keep one wallet. + require eUninstall.msg.sender == account; + require eInstall2.msg.sender == account; + + // Fresh start: never installed, epoch 0. + require !isInitialized(id, account); + require currentEpochOf(id, account) == 0; + + // Install #1: real _policyOninstall bumps epoch 0 -> 1. + install(eInstall1, id, cfg1); + + // Create a Pending proposal under installation #1 (stamps the real current epoch = 1). + createProposal(eCreate, id, account, callData, nonce, va, vu); + + // Reinstall: uninstall then install #2 -> real bump 1 -> 2. + uninstall(eUninstall, id, ucfg); + install(eInstall2, id, cfg2); + + // The proposal is now stale (epoch 1 != currentEpoch 2). + uint8 before = statusOf(id, account, account, callData, nonce); + uint256 result = execUserOp(eExec, id, account, callData, nonce); + uint8 after = statusOf(id, account, account, callData, nonce); + + assert result == sigFailedSentinel(), + "a proposal from a prior installation validated for execution after reinstall (TOB-2)"; + assert after == before, + "execution of a stale proposal changed its status"; +} + +/* --------------------------------------------------------------------------------------------- + * REACHABILITY #1 (mandatory): the SUCCESS path is reachable when there is NO reinstall. + * Same trace minus the reinstall must execute successfully -> the main-rule failure is a genuine + * epoch discriminator, not universal execution failure. + * ------------------------------------------------------------------------------------------- */ +rule reach_successWithoutReinstall( + bytes32 id, bytes callData, uint256 nonce, uint48 va, uint48 vu, bytes cfg1 +) { + env eInstall1; env eCreate; env eExec; + address account = eInstall1.msg.sender; + + require !isInitialized(id, account); + require currentEpochOf(id, account) == 0; + + install(eInstall1, id, cfg1); + createProposal(eCreate, id, account, callData, nonce, va, vu); + + uint256 result = execUserOp(eExec, id, account, callData, nonce); + + satisfy result != sigFailedSentinel() + && statusOf(id, account, account, callData, nonce) != ST_PENDING(); +} + +/* --------------------------------------------------------------------------------------------- + * REACHABILITY #2 (mandatory): a genuine cross-epoch stale state is reachable through the real + * install bump (proposal Pending, its stamped epoch strictly below currentEpoch). + * ------------------------------------------------------------------------------------------- */ +rule reach_staleCrossEpochState( + bytes32 id, bytes callData, uint256 nonce, uint48 va, uint48 vu, bytes cfg1, bytes cfg2, bytes ucfg +) { + env eInstall1; env eCreate; env eUninstall; env eInstall2; + address account = eInstall1.msg.sender; + require eUninstall.msg.sender == account; + require eInstall2.msg.sender == account; + + require !isInitialized(id, account); + require currentEpochOf(id, account) == 0; + + install(eInstall1, id, cfg1); + createProposal(eCreate, id, account, callData, nonce, va, vu); + uninstall(eUninstall, id, ucfg); + install(eInstall2, id, cfg2); + + satisfy statusOf(id, account, account, callData, nonce) == ST_PENDING() + && epochOf(id, account, account, callData, nonce) < currentEpochOf(id, account); +} diff --git a/certora/S03Probe.conf b/certora/S03Probe.conf new file mode 100644 index 0000000..c324f0b --- /dev/null +++ b/certora/S03Probe.conf @@ -0,0 +1,21 @@ +{ + "files": [ + "certora/harness/S03Harness.sol" + ], + "verify": "S03Harness:certora/S03Probe.spec", + "solc": "solc8.30", + "packages": [ + "src/=src/", + "account-abstraction/=dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/", + "solady/=dependencies/solady-0.1.26/src/", + "openzeppelin-contracts/contracts/=dependencies/@openzeppelin-contracts-5.5.0/", + "forge-std/=dependencies/forge-std-1.11.0/src/" + ], + "loop_iter": "2", + "optimistic_loop": true, + "optimistic_hashing": true, + "hashing_length_bound": "384", + "rule_sanity": "basic", + "global_timeout": 600, + "msg": "S-03 onUninstall clears all allowlist state and reinstall re-exposes nothing" +} diff --git a/certora/S03Probe.spec b/certora/S03Probe.spec new file mode 100644 index 0000000..9e615eb --- /dev/null +++ b/certora/S03Probe.spec @@ -0,0 +1,34 @@ +/* Probe: two-target uninstall — find why t1 survives. @author taek */ +methods { + function onInstall(bytes data) external; + function onUninstall(bytes data) external; + function setAllowlist(address target, bytes4[] selectors) external; + function isInitialized(address account) external returns (bool) envfree; + function isAllowlisted(address account, address target) external returns (bool) envfree; + function allowlistedTargetsLength(address account) external returns (uint256) envfree; + function entryPristine(address account, address target, bytes4 selector) external returns (bool) envfree; +} + +function setup2(env eI, env eS1, env eS2, address account, address t1, bytes4 s1, address t2) { + require eI.msg.sender == account; require eS1.msg.sender == account; require eS2.msg.sender == account; + require !isInitialized(account); + require entryPristine(account, t1, s1); + require t1 != t2; + bytes empty; require empty.length == 0; + onInstall(eI, empty); + bytes4[] sel1; require sel1.length == 1; require sel1[0] == s1; setAllowlist(eS1, t1, sel1); + bytes4[] sel2; require sel2.length == 0; setAllowlist(eS2, t2, sel2); +} + +// Find a CE where t1 survives uninstall. +rule findT1Survives(address t1, bytes4 s1, address t2) { + env eI; env eS1; env eS2; env eU; + address account = eI.msg.sender; require eU.msg.sender == account; + setup2(eI, eS1, eS2, account, t1, s1, t2); + require isAllowlisted(account, t1); + require isAllowlisted(account, t2); + require allowlistedTargetsLength(account) == 2; + bytes empty; require empty.length == 0; + onUninstall(eU, empty); + satisfy isAllowlisted(account, t1) == true; // can t1 survive? +} diff --git a/certora/S03StaleRoundtrip.conf b/certora/S03StaleRoundtrip.conf new file mode 100644 index 0000000..9d54d39 --- /dev/null +++ b/certora/S03StaleRoundtrip.conf @@ -0,0 +1,21 @@ +{ + "files": [ + "certora/harness/S03Harness.sol" + ], + "verify": "S03Harness:certora/S03StaleRoundtrip.spec", + "solc": "solc8.30", + "packages": [ + "src/=src/", + "account-abstraction/=dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/", + "solady/=dependencies/solady-0.1.26/src/", + "openzeppelin-contracts/contracts/=dependencies/@openzeppelin-contracts-5.5.0/", + "forge-std/=dependencies/forge-std-1.11.0/src/" + ], + "loop_iter": "2", + "optimistic_loop": true, + "optimistic_hashing": true, + "hashing_length_bound": "384", + "rule_sanity": "basic", + "global_timeout": 600, + "msg": "S-03 onUninstall clears all allowlist state and reinstall re-exposes nothing" +} diff --git a/certora/S03StaleRoundtrip.spec b/certora/S03StaleRoundtrip.spec new file mode 100644 index 0000000..2d529fd --- /dev/null +++ b/certora/S03StaleRoundtrip.spec @@ -0,0 +1,168 @@ +/* + * S-03 (audit regression, uninstall/reinstall stale-state): onUninstall clears ALL + * per-account allowlist state so no stale entry survives a reinstall roundtrip. + * + * PROPERTY: + * For an initialized account with a non-trivial allowlist covering BOTH branches of + * _setAllowlist: + * - target t1 with a real selector s1 (allSelectorsAllowed=false, selectorList=[s1]) + * - target t2 with empty selectors (allSelectorsAllowed=true) + * after onUninstall(): + * isAllowlisted(account, t1) == false + * isAllowlisted(account, t2) == false + * isSelectorAllowed(account, t1, s1) == false + * isSelectorAllowed(account, t2, ANY) == false + * allowlistedTargetsLength(account) == 0 + * and a subsequent onInstall() with empty data (reinstall) must NOT re-expose any prior + * selector: the same view reads stay false. + * + * Target : src/hooks/DefaultSecurityHook.sol + * onUninstall (clear loop over allowlistedTargets + delete + initialized=false) + * _clearAllowlist (zeroes selectors mapping, deletes selectorList, allowed/all=false) + * isAllowlisted / isSelectorAllowed (observable view reads) + * allowlistedTargets (observable length read via harness) + * + * TAUTOLOGY CHECK: the postcondition reads observable view outputs (isAllowlisted, + * isSelectorAllowed) and the allowlistedTargets length. It never re-runs the clear loop + * nor recomputes _clearAllowlist / selectorList zeroing. Observable, not tautological. + * + * REACHABILITY: rules s03_prestate_reachable and s03_post_read_reachable prove the + * non-trivial pre-state (both branches populated, initialized) and the post-uninstall + * observable read are actually reachable. satisfy => non-vacuous. + * + * MODELING (TCB-disclosed): + * - solc 0.8.30, LEGACY codegen (solc_via_ir OFF, see .conf). The via-ir + optimizer + * pipeline mis-models the struct-embedded `mapping(bytes4=>bool) selectors` co-located + * with `bytes4[] selectorList`, producing spurious CEs (same shape as DSH-STALE-01). + * Legacy codegen models this storage layout correctly. + * - Pre-state cleanliness pinned via entryPristine (observable READ, not a clear-loop + * recompute), because CVL cannot read the in-struct mapping directly. + * - loop_iter=2: allowlistedTargets bounded at 2 targets, each selectorList at <=1. + * + * @author taek + */ + +methods { + function onInstall(bytes data) external; + function onUninstall(bytes data) external; + function setAllowlist(address target, bytes4[] selectors) external; + function isInitialized(address account) external returns (bool) envfree; + function isAllowlisted(address account, address target) external returns (bool) envfree; + function isSelectorAllowed(address account, address target, bytes4 selector) external returns (bool) envfree; + function allowlistedTargetsLength(address account) external returns (uint256) envfree; + function entryPristine(address account, address target, bytes4 selector) external returns (bool) envfree; +} + +/* + * Sets up a non-trivial two-target allowlist for `account` covering both _setAllowlist + * branches, starting from a pristine uninitialized account. Returns nothing; leaves the + * hook installed with t1=[s1] and t2=all-selectors. + */ +function setupTwoTargets(env eInstall, env eSet1, env eSet2, address account, + address t1, bytes4 s1, address t2) { + // same account performs install + both sets + require eInstall.msg.sender == account; + require eSet1.msg.sender == account; + require eSet2.msg.sender == account; + + // pristine, uninitialized start (BOTH targets must start clean so both + // _setAllowlist calls take the push branch -> allowlistedTargets == [t1, t2]) + require !isInitialized(account); + require entryPristine(account, t1, s1); + require entryPristine(account, t2, s1); + require t1 != t2; + + bytes empty; + require empty.length == 0; + onInstall(eInstall, empty); // initialized = true, no configs + + // branch 1: t1 with a real selector s1 (allSelectorsAllowed = false) + bytes4[] sel1; + require sel1.length == 1; + require sel1[0] == s1; + setAllowlist(eSet1, t1, sel1); + + // branch 2: t2 with empty selectors (allSelectorsAllowed = true) + bytes4[] sel2; + require sel2.length == 0; + setAllowlist(eSet2, t2, sel2); +} + +/* + * MAIN PROPERTY (S-03). + * After onUninstall, no stale allowlist state survives, and a reinstall does not re-expose + * any prior selector. + */ +rule noStaleStateAfterUninstallRoundtrip(address t1, bytes4 s1, address t2, bytes4 anySel) { + env eInstall; env eSet1; env eSet2; env eUninstall; env eReinstall; + + address account = eInstall.msg.sender; + require eUninstall.msg.sender == account; + require eReinstall.msg.sender == account; + + setupTwoTargets(eInstall, eSet1, eSet2, account, t1, s1, t2); + + // Pre-state is actually populated (setup, not the fix under test). Pinning the + // tracked-target count to the concrete post-setup value (both pushes taken) tames the + // Prover's havoc of the mapping(address=>address[]) length so the onUninstall loop + // iterates over the real [t1, t2]. s03_prestate_reachable is a satisfy-witness proving + // allowlistedTargetsLength==2 with both targets allowlisted IS reachable -> not vacuous. + require isAllowlisted(account, t1); + require isAllowlisted(account, t2); + require allowlistedTargetsLength(account) == 2; + + bytes empty; + require empty.length == 0; + onUninstall(eUninstall, empty); + + // OBSERVABLE post-uninstall reads (not a recompute of _clearAllowlist). + assert isAllowlisted(account, t1) == false, "t1 remained allowlisted after uninstall"; + assert isAllowlisted(account, t2) == false, "t2 remained allowlisted after uninstall"; + assert isSelectorAllowed(account, t1, s1) == false, "s1 stayed permitted on t1 after uninstall"; + assert isSelectorAllowed(account, t2, anySel) == false, "t2 still permitted a selector after uninstall"; + assert allowlistedTargetsLength(account) == 0, "allowlistedTargets not emptied after uninstall"; + + // reinstall must not re-expose any prior selector + onInstall(eReinstall, empty); + assert isAllowlisted(account, t1) == false, "t1 re-exposed after reinstall"; + assert isAllowlisted(account, t2) == false, "t2 re-exposed after reinstall"; + assert isSelectorAllowed(account, t1, s1) == false, "s1 re-exposed on t1 after reinstall"; + assert isSelectorAllowed(account, t2, anySel) == false, "t2 selector re-exposed after reinstall"; +} + +/* + * REACHABILITY WITNESS 1 (mandatory): the non-trivial pre-state is reachable — both + * targets allowlisted with both branches exercised, account initialized. + */ +rule s03_prestate_reachable(address t1, bytes4 s1, address t2) { + env eInstall; env eSet1; env eSet2; + address account = eInstall.msg.sender; + + setupTwoTargets(eInstall, eSet1, eSet2, account, t1, s1, t2); + + satisfy isInitialized(account) + && isAllowlisted(account, t1) + && isAllowlisted(account, t2) + && isSelectorAllowed(account, t1, s1) + && allowlistedTargetsLength(account) == 2; +} + +/* + * REACHABILITY WITNESS 2 (mandatory): the post-uninstall observable read of a formerly-true + * selector is actually executed (not a dead branch) and yields false. + */ +rule s03_post_read_reachable(address t1, bytes4 s1, address t2) { + env eInstall; env eSet1; env eSet2; env eUninstall; + address account = eInstall.msg.sender; + require eUninstall.msg.sender == account; + + setupTwoTargets(eInstall, eSet1, eSet2, account, t1, s1, t2); + require isSelectorAllowed(account, t1, s1); // formerly true + + bytes empty; + require empty.length == 0; + onUninstall(eUninstall, empty); + + satisfy isSelectorAllowed(account, t1, s1) == false + && allowlistedTargetsLength(account) == 0; +} diff --git a/certora/TimelockPolicy.conf b/certora/TimelockPolicy.conf new file mode 100644 index 0000000..ae5799c --- /dev/null +++ b/certora/TimelockPolicy.conf @@ -0,0 +1,23 @@ +{ + "files": [ + "certora/harness/TimelockPolicyHarness.sol" + ], + "verify": "TimelockPolicyHarness:certora/TimelockPolicy.spec", + "solc": "solc8.30", + "solc_via_ir": true, + "solc_optimize": "20000", + "packages": [ + "src/=src/", + "account-abstraction/=dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/", + "solady/=dependencies/solady-0.1.26/src/", + "openzeppelin-contracts/contracts/=dependencies/@openzeppelin-contracts-5.5.0/", + "forge-std/=dependencies/forge-std-1.11.0/src/" + ], + "loop_iter": "3", + "optimistic_loop": true, + "optimistic_hashing": true, + "hashing_length_bound": "384", + "rule_sanity": "basic", + "global_timeout": 600, + "msg": "TL-LIFECYCLE-01: proposal state machine cannot be short-circuited (exec-once, cancel-only-from-Pending, no resurrection)" +} diff --git a/certora/TimelockPolicy.spec b/certora/TimelockPolicy.spec new file mode 100644 index 0000000..16ce2d4 --- /dev/null +++ b/certora/TimelockPolicy.spec @@ -0,0 +1,230 @@ +/* + * TL-LIFECYCLE-01: the inert-proposal state machine cannot be short-circuited. + * + * Target: src/policies/TimelockPolicy.sol + * _handleProposalExecutionInternal status gate :253 ("if status!=Pending return FAILED"), + * epoch gate :256, set Executed :259, return window :263 + * cancelProposal status gate :161-163 (revert ProposalNotPending), + * set Cancelled :165 + * + * The four observable sub-claims (all state-machine safety over multi-call sequences): + * (a) execution validates for the timelock window ONLY from status==Pending AND matching + * epoch; from None/Executed/Cancelled (or epoch mismatch) it returns FAILED and does + * NOT change the status. + * (b) execution moves Pending->Executed exactly once: a re-submitted identical userOp then + * returns FAILED (no double-execution). + * (c) cancelProposal acts ONLY on status==Pending — it reverts ProposalNotPending on any + * other status — and on success moves Pending->Cancelled. + * (d) a Cancelled proposal can never be executed and an Executed proposal can never be + * cancelled (no resurrection). + * + * TAUTOLOGY CHECK: every postcondition reads the OBSERVABLE result — the raw status enum via + * statusOf (a real `proposals` mapping read on the same key), the FAILED return sentinel (1), + * and the revert outcome of cancelProposal. No rule re-derives the status-enum arithmetic or + * re-runs a gate; the harness setters only PLANT pre-state, the transitions run the real + * internal/external functions. Observable, not tautological. + * + * REACHABILITY (mandatory, non-vacuity): rules reach_PendingToExecuted and + * reach_PendingToCancelled are `satisfy` witnesses proving both legitimate live transitions + * are actually reachable — the direct, sound evidence that the "never double-execute / never + * resurrect" claims are not vacuously true. (Note: Certora `basic` per-rule sanity's vacuity + * heuristic conservatively flags the assert-rules below, because it havocs the external + * `execUserOp` / `cancelProposal` calls in its vacuity variant and cannot then see a live + * non-reverting path — most obviously for the two `assert lastReverted` must-revert rules, + * where by design NO non-reverting path exists. The `satisfy` rules are the authoritative + * non-vacuity proof; sanity stays enabled and is not disabled to mask this.) + * + * MODELING (TCB-disclosed): + * - Same storage slot across execute/cancel/read is pinned by fixing ONE (account, callData, + * nonce) triple; keccak256 injectivity is assumed via optimistic_hashing (the real key and + * the harness read both compute keccak256(abi.encode(account, keccak256(callData), nonce)) + * — identical inputs => identical slot). callData length is bounded to hashing_length_bound; + * the key is a hash, so one representative length is fully general. No ECDSA involved. + * - execUserOp calls the REAL internal _handleProposalExecutionInternal directly with a + * calldata PackedUserOperation (no memory->calldata self-hop); the userOp's sender/callData/ + * nonce are constrained to the planted proposal's key. + * - Compiled WITH solc --via-ir (see .conf). The DSH-STALE-01 legacy-codegen decision was + * specifically to dodge a via-ir mis-modeling of a struct-EMBEDDED mapping (AllowlistEntry + * had `mapping(bytes4=>bool) selectors` co-located with a `bytes4[]`, and the clear-loop + * write did not alias reads). That hazard does NOT apply here: the `Proposal` struct has NO + * mapping members — only scalar fields (status, validAfter, validUntil, epoch) — so there is + * no in-struct-mapping aliasing to mis-model. Legacy codegen additionally cannot compile + * this contract (stack-too-deep in _handleProposalCreationInternal), so via-ir is required. + * The Foundry BTT suite independently confirms the impl on real EVM semantics. + * + * @author taek + */ + +methods { + function cancelProposal(bytes32 id, address account, bytes callData, uint256 nonce) external; + function execUserOp(bytes32 id, TimelockPolicyHarness.PackedUserOperation userOp, address account) external returns (uint256); + function statusOf(bytes32 id, address wallet, address account, bytes callData, uint256 nonce) external returns (uint8) envfree; + function epochOf(bytes32 id, address wallet, address account, bytes callData, uint256 nonce) external returns (uint256) envfree; + function initConfig(bytes32 id, address wallet, uint48 delay, uint48 expirationPeriod, address guardian, uint256 epoch) external envfree; + function plantProposal(bytes32 id, address wallet, address account, bytes callData, uint256 nonce, uint8 status, uint48 validAfter, uint48 validUntil, uint256 epoch) external envfree; + function currentEpoch(bytes32, address) external returns (uint256) envfree; +} + +// ProposalStatus enum ordinals (src/policies/TimelockPolicy.sol:43-48) and the ERC-4337 +// failure sentinel (SIG_VALIDATION_FAILED_UINT = 1). Literals, no envfree indirection. +definition ST_NONE() returns uint8 = 0; +definition ST_PENDING() returns uint8 = 1; +definition ST_EXECUTED() returns uint8 = 2; +definition ST_CANCELLED() returns uint8 = 3; +definition FAILED() returns uint256 = 1; + +// Install config with a definite current epoch, and plant an arbitrary starting proposal. +function setup(bytes32 id, address wallet, address account, bytes callData, uint256 nonce, + uint8 status, uint48 va, uint48 vu, uint256 propEpoch, uint256 curEpoch) { + require callData.length <= 32; // keep keccak within hashing_length_bound (key is a hash) + require status <= ST_CANCELLED(); // real enum universe {None,Pending,Executed,Cancelled} + initConfig(id, wallet, 1, 1, 0, curEpoch); + plantProposal(id, wallet, account, callData, nonce, status, va, vu, propEpoch); +} + +// Build a PackedUserOperation whose derived key targets the planted proposal (sender=account, +// same callData, same nonce). Returns the exec result of the REAL internal handler. +function execFor(env e, bytes32 id, address account, bytes callData, uint256 nonce) returns uint256 { + TimelockPolicyHarness.PackedUserOperation userOp; + require userOp.sender == account; + require userOp.callData == callData; // identical bytes => identical keccak(callData) => same slot key + require userOp.nonce == nonce; + return execUserOp(e, id, userOp, account); +} + +/* --------------------------------------------------------------------------------------------- + * (a) EXECUTION VALIDATES ONLY FROM Pending + MATCHING EPOCH. + * If (status != Pending) OR (epoch != currentEpoch), execUserOp returns FAILED and leaves the + * status unchanged. The Pending+match success case is covered positively in rule (b). + * ------------------------------------------------------------------------------------------- */ +rule execValidatesOnlyFromPendingMatchingEpoch( + bytes32 id, address account, bytes callData, uint256 nonce, + uint8 status, uint48 va, uint48 vu, uint256 propEpoch, uint256 curEpoch +) { + env e; + setup(id, account, account, callData, nonce, status, va, vu, propEpoch, curEpoch); + require status != ST_PENDING() || propEpoch != curEpoch; // the "should not validate" universe + + uint8 before = statusOf(id, account, account, callData, nonce); + uint256 result = execFor(e, id, account, callData, nonce); + uint8 after = statusOf(id, account, account, callData, nonce); + + assert result == FAILED(), + "execution validated (non-FAILED) from a non-Pending or epoch-mismatched proposal"; + assert after == before, + "execution changed proposal status despite not being executable"; +} + +/* --------------------------------------------------------------------------------------------- + * (b) EXECUTE-ONCE: Pending + matching epoch -> Executed, success; a second identical execUserOp + * returns FAILED (no double-execution). + * ------------------------------------------------------------------------------------------- */ +rule executeOncePendingToExecuted( + bytes32 id, address account, bytes callData, uint256 nonce, uint48 va, uint48 vu, uint256 epoch +) { + env e1; + env e2; + setup(id, account, account, callData, nonce, ST_PENDING(), va, vu, epoch, epoch); + + uint256 r1 = execFor(e1, id, account, callData, nonce); + uint8 mid = statusOf(id, account, account, callData, nonce); + + assert r1 != FAILED(), "first execution of a live Pending proposal failed"; + assert mid == ST_EXECUTED(), "first execution did not move Pending -> Executed"; + + uint256 r2 = execFor(e2, id, account, callData, nonce); + uint8 fin = statusOf(id, account, account, callData, nonce); + + assert r2 == FAILED(), "second execution of the same userOp validated -> DOUBLE EXECUTION"; + assert fin == ST_EXECUTED(), "status left Executed after a rejected second execution"; +} + +/* --------------------------------------------------------------------------------------------- + * (c) CANCEL ONLY FROM Pending. + * ------------------------------------------------------------------------------------------- */ +rule cancelRevertsUnlessPending( + bytes32 id, address account, bytes callData, uint256 nonce, + uint8 status, uint48 va, uint48 vu, uint256 propEpoch, uint256 curEpoch +) { + env e; + require e.msg.sender == account; // account is authorized to cancel + require e.msg.value == 0; + setup(id, account, account, callData, nonce, status, va, vu, propEpoch, curEpoch); + require status != ST_PENDING(); + + cancelProposal@withrevert(e, id, account, callData, nonce); + + assert lastReverted, + "cancelProposal succeeded on a non-Pending proposal (should revert ProposalNotPending)"; +} + +rule cancelPendingToCancelled( + bytes32 id, address account, bytes callData, uint256 nonce, + uint48 va, uint48 vu, uint256 propEpoch, uint256 curEpoch +) { + env e; + require e.msg.sender == account; + require e.msg.value == 0; + setup(id, account, account, callData, nonce, ST_PENDING(), va, vu, propEpoch, curEpoch); + + cancelProposal@withrevert(e, id, account, callData, nonce); + bool reverted = lastReverted; + uint8 after = statusOf(id, account, account, callData, nonce); + + assert !reverted, "cancel of a Pending proposal by the account reverted"; + assert after == ST_CANCELLED(), "cancel did not move Pending -> Cancelled"; +} + +/* --------------------------------------------------------------------------------------------- + * (d) NO RESURRECTION. + * ------------------------------------------------------------------------------------------- */ +rule cancelledNeverExecutes( + bytes32 id, address account, bytes callData, uint256 nonce, uint48 va, uint48 vu, uint256 epoch +) { + env e; + setup(id, account, account, callData, nonce, ST_CANCELLED(), va, vu, epoch, epoch); // even with epoch match + + uint256 result = execFor(e, id, account, callData, nonce); + uint8 after = statusOf(id, account, account, callData, nonce); + + assert result == FAILED(), "a Cancelled proposal validated for execution"; + assert after == ST_CANCELLED(), "a Cancelled proposal transitioned out of Cancelled"; +} + +rule executedNeverCancels( + bytes32 id, address account, bytes callData, uint256 nonce, + uint48 va, uint48 vu, uint256 propEpoch, uint256 curEpoch +) { + env e; + require e.msg.sender == account; + require e.msg.value == 0; + setup(id, account, account, callData, nonce, ST_EXECUTED(), va, vu, propEpoch, curEpoch); + + cancelProposal@withrevert(e, id, account, callData, nonce); + + assert lastReverted, "an Executed proposal was cancelled (should revert ProposalNotPending)"; +} + +/* --------------------------------------------------------------------------------------------- + * REACHABILITY WITNESSES (mandatory, non-vacuity). Both legitimate live transitions reachable. + * ------------------------------------------------------------------------------------------- */ +rule reach_PendingToExecuted( + bytes32 id, address account, bytes callData, uint256 nonce, uint48 va, uint48 vu, uint256 epoch +) { + env e; + setup(id, account, account, callData, nonce, ST_PENDING(), va, vu, epoch, epoch); + uint256 result = execFor(e, id, account, callData, nonce); + satisfy result != FAILED() + && statusOf(id, account, account, callData, nonce) == ST_EXECUTED(); +} + +rule reach_PendingToCancelled( + bytes32 id, address account, bytes callData, uint256 nonce, uint48 va, uint48 vu, uint256 epoch +) { + env e; + require e.msg.sender == account; + require e.msg.value == 0; + setup(id, account, account, callData, nonce, ST_PENDING(), va, vu, epoch, epoch); + cancelProposal(e, id, account, callData, nonce); + satisfy statusOf(id, account, account, callData, nonce) == ST_CANCELLED(); +} diff --git a/certora/WeightedECDSA.conf b/certora/WeightedECDSA.conf new file mode 100644 index 0000000..32cf01b --- /dev/null +++ b/certora/WeightedECDSA.conf @@ -0,0 +1,11 @@ +{ + "files": ["certora/harness/WeightedECDSAHarness.sol"], + "verify": "WeightedECDSAHarness:certora/WeightedECDSA.spec", + "solc": "solc8.30", + "solc_via_ir": true, + "solc_optimize": "20000", + "loop_iter": "2", + "optimistic_loop": true, + "rule_sanity": "basic", + "msg": "EC-01 WeightedECDSA isValidSignatureWithSender: duplicate signer never reaches threshold" +} diff --git a/certora/WeightedECDSA.spec b/certora/WeightedECDSA.spec new file mode 100644 index 0000000..9c5581b --- /dev/null +++ b/certora/WeightedECDSA.spec @@ -0,0 +1,123 @@ +/* + * EC-01 (audit High): isValidSignatureWithSender returns ERC1271_MAGICVALUE only when the + * summed weight of DISTINCT guardians reaches threshold. A duplicated single-guardian + * signature must NOT reach threshold. + * + * Target: src/validators/WeightedECDSAValidator.sol:294-320 + * Fix under test: the strictly-descending guard + * `if (signer >= prevSigner) return ERC1271_INVALID;` (line 310) + * runs BEFORE weight accumulation (line 314) + threshold return (line 315/316). + * + * ECDSA.recover is modeled UNINTERPRETED: recoveredSigner(i) is a symbolic, + * attacker-controlled address, DETERMINISTIC in the loop index i (same 65-byte slice + * data[i*65:(i+1)*65] -> same recovered address). The proof covers the aggregation/ordering + * logic, NOT ECDSA soundness. + * + * @author taek + */ + +methods { + function threshold() external returns (uint24) envfree; + function weightOf(address) external returns (uint24) envfree; + function isValidSignatureWithSender(uint256) external returns (bytes4) envfree; + function _recoverSigner(uint256 i) internal returns (address) => recoveredSigner(i); +} + +// Uninterpreted, deterministic per-index recovery. Same i -> same address. +ghost recoveredSigner(uint256) returns address; + +definition MAGIC() returns bytes4 = to_bytes4(0x1626ba7e); +definition INVALID() returns bytes4 = to_bytes4(0xffffffff); + +/* + * MAIN PROPERTY (the exact audit bug class, contrapositive). + * For a two-slice input where the two recovered signers are IDENTICAL (a duplicate) and a + * SINGLE copy of that signer's weight is below threshold, the function can NEVER accept. + * + * Pre-fix, iteration-0 added w (w 2w>=threshold -> + * MAGICVALUE. Post-fix, iteration-1's guard `signer >= prevSigner` (s == s) fires FIRST and + * returns INVALID before any second contribution. + * + * Observable: the RETURN value under a duplicate-signer precondition. It does NOT recompute + * recover or the running total; the claim is that a duplicate cannot double-count -> not a + * tautology (advanced sanity confirms the antecedent is reachable and the conclusion is + * non-trivial via the witness rules below). + */ +rule duplicateSignerNeverAccepts() { + address s0 = recoveredSigner(0); + address s1 = recoveredSigner(1); + + require to_mathint(s0) < 2^160 - 1; // exclude the sentinel corner + require s0 == s1; // duplicate: same 65-byte slice recovers same signer + require weightOf(s0) > 0; // s0 is a real guardian (loop genuinely counts) + require to_mathint(threshold()) > to_mathint(weightOf(s0)); // one copy alone is insufficient + + bytes4 ret = isValidSignatureWithSender(2); + + assert ret != MAGIC(), + "duplicate signer reached threshold via double-counting -- line-310 guard failed"; +} + +/* + * COMPLEMENT: a duplicate whose SINGLE copy already meets threshold IS accepted at + * iteration-0 (before the guard is even relevant). This proves the rule above is scoped to + * the genuine bug (double-counting) and not over-claiming that duplicates always reject. + */ +rule singleSufficientSignerAccepts() { + address s0 = recoveredSigner(0); + + // A recovered signer equal to the uint160-max sentinel is rejected by the very first + // ordering guard (prevSigner initializes to that sentinel); exclude that corner so the + // rule speaks to the weight logic. Any real guardian address is < 2^160-1. + require to_mathint(s0) < 2^160 - 1; + require to_mathint(weightOf(s0)) >= to_mathint(threshold()); + require threshold() != 0; + + bytes4 ret = isValidSignatureWithSender(1); + + assert ret == MAGIC(), + "a single guardian whose weight meets threshold must be accepted"; +} + +/* + * REACHABILITY WITNESS (i) -- non-vacuous ACCEPT via TWO DISTINCT signers. + * There EXISTS a two-slice input with distinct, strictly-descending signers whose combined + * weight reaches threshold and returns MAGICVALUE. Kills vacuity of the accept path. + */ +rule witnessTwoDistinctAccept() { + address s0 = recoveredSigner(0); + address s1 = recoveredSigner(1); + + require to_mathint(s0) < 2^160 - 1; // exclude the sentinel corner + require s0 > s1; // strictly descending -> distinct + require to_mathint(weightOf(s0)) < to_mathint(threshold()); // first alone insufficient + require to_mathint(weightOf(s0)) + to_mathint(weightOf(s1)) >= to_mathint(threshold()); // together sufficient + require threshold() != 0; + + bytes4 ret = isValidSignatureWithSender(2); + + satisfy ret == MAGIC(), + "no reachable accept from two distinct guardians summing to threshold"; +} + +/* + * REACHABILITY WITNESS (ii) -- the audit PoC is reachable AND discriminated. + * There EXISTS a duplicate (s0==s1) with 2w>=threshold>w that returns INVALID: the exact + * pre-fix exploit input, now correctly rejected. + */ +rule witnessDuplicatePoCRejected() { + address s0 = recoveredSigner(0); + address s1 = recoveredSigner(1); + + require s0 == s1; + uint24 w = weightOf(s0); + require w > 0; + require 2 * to_mathint(w) >= to_mathint(threshold()); // WOULD reach threshold if double-counted + require to_mathint(threshold()) > to_mathint(w); // one copy alone does NOT + + bytes4 ret = isValidSignatureWithSender(2); + + satisfy ret == INVALID(), + "audit PoC (duplicate, 2w>=threshold>w) not reachable as a rejection"; +} diff --git a/certora/WeightedECDSASigner.conf b/certora/WeightedECDSASigner.conf new file mode 100644 index 0000000..096eff2 --- /dev/null +++ b/certora/WeightedECDSASigner.conf @@ -0,0 +1,18 @@ +{ + "files": ["certora/harness/WeightedECDSASignerHarness.sol"], + "verify": "WeightedECDSASignerHarness:certora/WeightedECDSASigner.spec", + "packages": [ + "src/=src/", + "account-abstraction/=dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/", + "solady/=dependencies/solady-0.1.26/src/", + "openzeppelin-contracts/contracts/=dependencies/@openzeppelin-contracts-5.5.0/", + "forge-std/=dependencies/forge-std-1.11.0/src/" + ], + "solc": "solc8.30", + "solc_via_ir": true, + "solc_optimize": "20000", + "loop_iter": "2", + "optimistic_loop": true, + "rule_sanity": "basic", + "msg": "WECDSA-THRESHOLD-01 re-anchored - SIGNER checkSignature to real WeightedThresholdBase _verifySorted, duplicate signer never double-counts" +} diff --git a/certora/WeightedECDSASigner.spec b/certora/WeightedECDSASigner.spec new file mode 100644 index 0000000..9b8d09b --- /dev/null +++ b/certora/WeightedECDSASigner.spec @@ -0,0 +1,170 @@ +/* + * WECDSA-THRESHOLD-01 (RE-ANCHORED) — TOB-17 (no double-count) + TOB-16 (check-before-count + * ordering) + threshold-soundness for the SIGNER's installed ERC-1271 path, AFTER the EC-01 + * refactor moved the aggregation logic onto the shared WeightedThresholdBase. + * + * The pre-refactor version of this spec summarized an in-signer `_validateSignature` that no + * longer exists and the harness reimplemented the loop byte-for-byte. This version RE-ANCHORS the + * same observable property onto the MOVED code: the harness (certora/harness/WeightedECDSASigner- + * Harness.sol) derives from the real WeightedECDSASigner and drives the REAL, COMPILED base + * bytecode WeightedThresholdBase._verifySorted (src/base/WeightedThresholdBase.sol:38-93) exactly + * as reached through WeightedECDSASigner.checkSignature (:162-170) -> _verifySorted -> + * _guardianWeight (id-keyed guardian[signer][cfg][account], :122-129). No hand copy of the loop + * remains, so a behavioral drift introduced by the move would be caught here. + * + * OBSERVABLE PROPERTY (not a re-run of the summation loop): + * a duplicate signer (two slices recovering the same address) NEVER yields acceptance with that + * address's weight counted twice — the ascending gate `signer <= lastSigner` (base :61 / :79) + * fires on the equal second signer BEFORE its weight is added (base :71 / :87). + * + * ECDSA.tryRecoverCalldata is inline assembly the SMT engine cannot invert. It is summarized as an + * UNINTERPRETED, DETERMINISTIC ghost `recoveredSigner(i)` keyed on the RECOVERY CALL INDEX i. + * _verifySorted recovers slice 0 first (loop i=0) then the last slice in strict program order, so + * call index == slice index for the small slice counts these rules use (1 and 2). Same slice -> + * same call index -> same address. The proof covers ordering/threshold logic, NOT ECDSA soundness. + * TCB: solc8.30 (via-IR) + Certora solver; recovery abstracted; keccak default-modelled. + * + * @author taek + */ + +using WeightedECDSASignerHarness as h; + +methods { + // threshold()/weightOf() read guardian storage at (ID, msg.sender); env-bound so the account + // matches the msg.sender validateSignature drives _verifySorted with (same e passed to all three). + function threshold() external returns (uint24); + function weightOf(address) external returns (uint24); + // Recovery: summarized by monotonically increasing CALL INDEX -> recoveredSigner(index). + function _.tryRecoverCalldata(bytes32 hash, bytes calldata sigSlice) internal => recoverByIndex() expect address; +} + +// Uninterpreted, deterministic per-index recovery. Same call index -> same address. +ghost recoveredSigner(mathint) returns address; + +// Per-execution recovery-call counter (reset to 0 at the start of each rule). +ghost mathint recoverCallCount { + init_state axiom recoverCallCount == 0; +} + +// Summary body: return recoveredSigner(current count), then advance the counter. slice 0 is the +// first recover call (loop i=0), the last slice the second, matching recoveredSigner(0/1). +function recoverByIndex() returns address { + address r = recoveredSigner(recoverCallCount); + recoverCallCount = recoverCallCount + 1; + return r; +} + +definition MAGIC() returns bytes4 = to_bytes4(0x1626ba7e); +definition INVALID() returns bytes4 = to_bytes4(0xffffffff); + +// sig length for a given slice count (65 bytes/slice). +definition SIG2() returns mathint = 130; +definition SIG1() returns mathint = 65; + +/* + * MAIN PROPERTY (TOB-17 double-count, contrapositive) — the dispatched claim, RE-ANCHORED. + * For a two-slice input where the two recovered signers are IDENTICAL (a duplicate) and a SINGLE + * copy of that signer's weight is below threshold, the REAL base _verifySorted can NEVER accept. + * + * Under the ascending gate with sentinel 0: loop iteration i=0 processes slice 0 (adds w once, + * w same signer + require weightOf(e, s0) > 0; // s0 is a real guardian + require to_mathint(threshold(e)) > to_mathint(weightOf(e, s0)); // one copy alone is insufficient + + bytes4 ret = h.validateSignature(e, sigData); + + assert ret != MAGIC(), + "duplicate signer reached threshold via double-counting -- ascending gate failed"; +} + +/* + * COMPLEMENT / scoping: a single guardian whose weight already meets threshold IS accepted (via the + * real base). Proves the main rule is scoped to the double-counting bug, not over-claiming that + * duplicates always reject. With sigCount==1 the loop body (0 .. sigCount-2) is skipped; the + * last-slice pass processes slice 0: guard `s0 <= 0` is false (s0 != 0), weight added, threshold met. + */ +rule singleSufficientSignerAccepts() { + env e; + require recoverCallCount == 0; + bytes sigData; + require sigData.length == assert_uint256(SIG1()); // exactly one slice + + address s0 = recoveredSigner(0); + + require s0 != 0; // sentinel corner excluded + require to_mathint(weightOf(e, s0)) >= to_mathint(threshold(e)); + require threshold(e) != 0; + + bytes4 ret = h.validateSignature(e, sigData); + + assert ret == MAGIC(), + "a single guardian whose weight meets threshold must be accepted"; +} + +/* + * REACHABILITY WITNESS (i) — MANDATORY non-vacuous ACCEPT via TWO DISTINCT signers over the REAL + * base. There EXISTS a two-slice input with distinct, strictly-ascending signers whose combined + * weight reaches threshold and returns MAGICVALUE. Kills vacuity of the accept path. + */ +rule witnessTwoDistinctAccept() { + env e; + require recoverCallCount == 0; + bytes sigData; + require sigData.length == assert_uint256(SIG2()); + + address s0 = recoveredSigner(0); + address s1 = recoveredSigner(1); + + require s0 != 0; // sentinel excluded + require s0 < s1; // strictly ascending -> distinct + require to_mathint(weightOf(e, s0)) < to_mathint(threshold(e)); // first alone insufficient + require to_mathint(weightOf(e, s0)) + to_mathint(weightOf(e, s1)) >= to_mathint(threshold(e)); // together sufficient + require threshold(e) != 0; + + bytes4 ret = h.validateSignature(e, sigData); + + satisfy ret == MAGIC(), + "no reachable accept from two distinct guardians summing to threshold"; +} + +/* + * REACHABILITY WITNESS (ii) — the TOB-17 PoC is reachable AND discriminated over the REAL base. + * There EXISTS a duplicate (s0==s1) with 2w>=threshold>w that returns INVALID: the exact pre-fix + * exploit input, now correctly rejected by the check-before-count gate. + */ +rule witnessDuplicatePoCRejected() { + env e; + require recoverCallCount == 0; + bytes sigData; + require sigData.length == assert_uint256(SIG2()); + + address s0 = recoveredSigner(0); + address s1 = recoveredSigner(1); + + require s0 != 0; + require s0 == s1; + uint24 w = weightOf(e, s0); + require w > 0; + require 2 * to_mathint(w) >= to_mathint(threshold(e)); // WOULD reach threshold if double-counted + require to_mathint(threshold(e)) > to_mathint(w); // one copy alone does NOT + + bytes4 ret = h.validateSignature(e, sigData); + + satisfy ret == INVALID(), + "TOB-17 PoC (duplicate, 2w>=threshold>w) not reachable as a rejection"; +} diff --git a/certora/WeightedECDSAValidator.conf b/certora/WeightedECDSAValidator.conf new file mode 100644 index 0000000..4431a5a --- /dev/null +++ b/certora/WeightedECDSAValidator.conf @@ -0,0 +1,18 @@ +{ + "files": ["certora/harness/WeightedECDSAValidatorHarness.sol"], + "verify": "WeightedECDSAValidatorHarness:certora/WeightedECDSAValidator.spec", + "solc": "solc8.30", + "solc_via_ir": true, + "solc_optimize": "20000", + "packages": [ + "account-abstraction=dependencies/eth-infinitism-account-abstraction-0.8.0/contracts", + "solady=dependencies/solady-0.1.26/src", + "forge-std=dependencies/forge-std-1.11.0/src", + "openzeppelin-contracts/contracts=dependencies/@openzeppelin-contracts-5.5.0" + ], + "loop_iter": "3", + "optimistic_loop": true, + "rule_sanity": "basic", + "global_timeout": "900", + "msg": "RP-01 stale-approval non-replay across configVersion bump" +} diff --git a/certora/WeightedECDSAValidator.spec b/certora/WeightedECDSAValidator.spec new file mode 100644 index 0000000..69a82d4 --- /dev/null +++ b/certora/WeightedECDSAValidator.spec @@ -0,0 +1,145 @@ +/* + * RP-01 — Stale-approval non-replay across a config-version bump. + * + * Property (observable): after ANY lifecycle call that bumps the per-kernel config + * epoch (onInstall / onUninstall / renew), a proposal/vote fully written under a PRIOR + * epoch cannot make getApproval(kernel, H).passed become true. The only votes that can + * contribute to getApproval after a bump are those written at the CURRENT epoch key. + * + * Two lemmas the dispatch calls out: + * (a) key injectivity: configVersion(V0) != configVersion(V1) => key(V0,H) != key(V1,H). + * Discharged by Certora's default keccak256 modelling as an injective uninterpreted + * function (DISCLOSED TCB assumption: keccak collision-resistance). + * (b) getApproval keys off the current epoch: it reads voteStatus[ _key(current) ][..]. + * Discharged over the real getApproval / keyOf bytecode. + * + * Tautology check: postconditions assert an access/replay OUTCOME (the slot getApproval + * reads after a bump differs from the slot the stale vote lives in) — never recompute _key. + * Reachability check: `witness_*` rules use `satisfy` to prove the pre-rotation + * passed==true state AND the successful lifecycle transitions are reachable, so the + * safety rules are not vacuously true. rule_sanity is kept "basic". + * + * @author taek + */ + +methods { + function version(address) external returns (uint256) envfree; + function keyOf(address, bytes32) external returns (bytes32) envfree; + function getApproval(address, bytes32) external returns (uint256, bool) envfree; + function voteStatusAt(bytes32, address, address) external returns (WeightedECDSAValidator.VoteStatus) envfree; + function weightOf(address, address) external returns (uint24) envfree; + function isInitialized(address) external returns (bool) envfree; +} + +// =========================================================================== +// SAFETY — the epoch is bumped and the stale-vote slot is orphaned, per method. +// Each rule has non-reverting preconditions so its assertions are REACHABLE +// (kills the vacuity that a blanket parametric rule triggered). +// =========================================================================== + +/* renew: the exploit path from PoC_X02. Kernel must be initialized to renew. + * After renew, the epoch is bumped and the key for H changes, so the stale + * Approved vote at the old key is orphaned. */ +rule renewBumpsEpochAndOrphansStaleVote(address k, bytes32 h, address g) { + env e; + require e.msg.sender == k && k != 0; + require isInitialized(k); // reachability: renew requires init + require version(k) < max_uint256; // no epoch overflow (unreachable in practice) + + uint256 vBefore = version(k); + bytes32 oldKey = keyOf(k, h); + + address[] guardians; uint24[] weights; uint24 threshold; uint48 delay; + renew(e, guardians, weights, threshold, delay); + + uint256 vAfter = version(k); + bytes32 newKey = keyOf(k, h); + + assert vAfter == vBefore + 1, "renew bumps the epoch exactly once"; + assert newKey != oldKey, "RP-01: stale vote slot (oldKey) is orphaned; getApproval keys off newKey"; +} + +/* onUninstall: rotation via uninstall. Requires init; bumps epoch. */ +rule uninstallBumpsEpochAndOrphansStaleVote(address k, bytes32 h, address g) { + env e; + require e.msg.sender == k && k != 0; + require isInitialized(k); // reachability: onUninstall requires init + require version(k) < max_uint256; // no epoch overflow (unreachable in practice) + + uint256 vBefore = version(k); + bytes32 oldKey = keyOf(k, h); + + bytes uninstallData; + onUninstall(e, uninstallData); + + uint256 vAfter = version(k); + bytes32 newKey = keyOf(k, h); + + assert vAfter == vBefore + 1, "onUninstall bumps the epoch exactly once"; + assert newKey != oldKey, "RP-01: stale vote slot (oldKey) is orphaned by uninstall"; +} + +/* onInstall: (re)install after an uninstall. Requires NOT init; bumps epoch. */ +rule installBumpsEpochAndOrphansStaleVote(address k, bytes32 h, address g) { + env e; + require e.msg.sender == k && k != 0; + require !isInitialized(k); // reachability: onInstall requires NOT init + require version(k) < max_uint256; // no epoch overflow (unreachable in practice) + + uint256 vBefore = version(k); + bytes32 oldKey = keyOf(k, h); + + bytes installData; + onInstall(e, installData); + + uint256 vAfter = version(k); + bytes32 newKey = keyOf(k, h); + + assert vAfter == vBefore + 1, "onInstall bumps the epoch exactly once"; + assert newKey != oldKey, "RP-01: stale vote slot (oldKey) is orphaned by (re)install"; +} + +// =========================================================================== +// REACHABILITY WITNESSES (satisfy) — the safety rules above are NOT vacuous. +// =========================================================================== + +/* (i) Pre-rotation: getApproval CAN return passed==true. If this were unreachable, + * the whole replay property would be vacuous (approval never happens). */ +rule witness_approvalCanPass(address k, bytes32 h) { + uint256 approvals; bool passed; + approvals, passed = getApproval(k, h); + satisfy passed, "there exists a reachable state where getApproval passes (pre-rotation)"; +} + +/* (ii) The renew transition with a live stale vote actually succeeds (not revert-only). */ +rule witness_renewSucceedsWithStaleVote(address k, bytes32 h, address g) { + env e; + require e.msg.sender == k && k != 0; + require isInitialized(k); + bytes32 oldKey = keyOf(k, h); + require voteStatusAt(oldKey, g, k) == WeightedECDSAValidator.VoteStatus.Approved; + + address[] guardians; uint24[] weights; uint24 threshold; uint48 delay; + renew(e, guardians, weights, threshold, delay); + + satisfy version(k) == version(k), "renew reaches a non-reverting post-state with a stale vote present"; +} + +/* (iii) Post-rotation the SAME hash no longer passes off the stale vote alone: + * after renew, at the new key the vote for g is NA (stale vote did not carry over), + * so its weight is not counted. Reachable witness that the replay is blocked. */ +rule witness_staleVoteNotAtNewKey(address k, bytes32 h, address g) { + env e; + require e.msg.sender == k && k != 0; + require isInitialized(k); + bytes32 oldKey = keyOf(k, h); + require voteStatusAt(oldKey, g, k) == WeightedECDSAValidator.VoteStatus.Approved; + + address[] guardians; uint24[] weights; uint24 threshold; uint48 delay; + renew(e, guardians, weights, threshold, delay); + + bytes32 newKey = keyOf(k, h); + // The stale voter g has NO vote recorded at the post-rotation key. + satisfy voteStatusAt(newKey, g, k) == WeightedECDSAValidator.VoteStatus.NA, + "post-renew: the stale voter has no vote at the new epoch key (replay blocked)"; +} diff --git a/certora/WeightedThresholdBase.conf b/certora/WeightedThresholdBase.conf new file mode 100644 index 0000000..f56c4f3 --- /dev/null +++ b/certora/WeightedThresholdBase.conf @@ -0,0 +1,17 @@ +{ + "files": ["certora/harness/WeightedThresholdBaseHarness.sol"], + "verify": "WeightedThresholdBaseHarness:certora/WeightedThresholdBase.spec", + "solc": "solc8.30", + "solc_optimize": "20000", + "packages": [ + "account-abstraction=dependencies/eth-infinitism-account-abstraction-0.8.0/contracts", + "solady=dependencies/solady-0.1.26/src", + "forge-std=dependencies/forge-std-1.11.0/src", + "openzeppelin-contracts/contracts=dependencies/@openzeppelin-contracts-5.5.0" + ], + "loop_iter": "3", + "optimistic_loop": true, + "rule_sanity": "basic", + "global_timeout": "600", + "msg": "EC-01 WeightedThresholdBase._verifySorted on WeightedECDSAValidator adapter: distinct-signer threshold, duplicate never double-counts" +} diff --git a/certora/WeightedThresholdBase.spec b/certora/WeightedThresholdBase.spec new file mode 100644 index 0000000..59283dc --- /dev/null +++ b/certora/WeightedThresholdBase.spec @@ -0,0 +1,175 @@ +/* + * WeightedThresholdBase._verifySorted ON the WeightedECDSAValidator adapter (the refactor + * soundness claim). Target: shared core src/base/WeightedThresholdBase.sol:38-93 driven through + * the REAL adapter storage layout (src/validators/WeightedECDSAValidator.sol:171-178) -- + * threshold from weightedStorage[account].threshold, each weight from the inherited real + * _guardianWeight -> guardian[signer][account].weight. + * + * CLAIM (dispatched, Critical): isValidSignatureWithSender returns ERC1271_MAGICVALUE ONLY IF + * the summed weight of pairwise-DISTINCT, strictly-ASCENDING guardians reaches threshold; a + * DUPLICATED single-guardian signature can NEVER reach threshold. This is the auth-bypass class + * (one compromised guardian replayed to threshold). + * + * OBSERVABLE POSTCONDITION (NOT a re-sum): if result == MAGICVALUE then the recovered signers in + * the COUNTED prefix are pairwise DISTINCT (the structural invariant the ascending gate at :61/:79 + * establishes BEFORE the weight is counted at :71/:87). The rules assert over the processed-prefix + * ghost images only; they never recompute totalWeight. + * + * ECDSA.tryRecoverCalldata is called inline in _verifySorted (no override seam) so the loop is + * mirrored verbatim in the harness with recovery routed through _recoverSigner(i), summarized + * here as an UNINTERPRETED ghost DETERMINISTIC in the loop index i (same 65-byte slice -> + * same recovered address). Proof covers ordering/threshold aggregation on the adapter storage, + * NOT ECDSA soundness. + * + * TCB (this leg): solc 0.8.30 (via_ir) + Certora Prover SMT + trust-that-the-harness-loop-mirrors + * WeightedThresholdBase._verifySorted (line-by-line) + uninterpreted recovery. TCB-INDEPENDENT + * from the halmos verbatim-replica leg (different toolchain, different extraction). + * + * @author taek + */ + +methods { + // NOT envfree: the loop reads weightedStorage[msg.sender] and guardian[s][msg.sender], so + // each rule binds e.msg.sender to the `acc` the weightOf/thresholdOf reads are taken at. + function isValidSignatureWithSenderH(uint256) external returns (bytes4); + function weightOf(address, address) external returns (uint256) envfree; + function thresholdOf(address) external returns (uint256) envfree; + function _recoverSigner(uint256 i) internal returns (address) => recoveredSigner(i); +} + +// Uninterpreted, deterministic per-index recovery. Same slice (index) -> same address. +ghost recoveredSigner(uint256) returns address; + +definition MAGIC() returns bytes4 = to_bytes4(0x1626ba7e); +definition INVALID() returns bytes4 = to_bytes4(0xffffffff); + +// The account whose real storage the harness reads is msg.sender; we quantify weights via the +// envfree weightOf(account, signer). To keep the storage read and the assertion on the same +// account, all rules fix `acc` and require the weightOf reads to be taken at `acc`. Because +// isValidSignatureWithSenderH is envfree, Certora picks msg.sender freely; the weight the loop +// reads for signer s is guardian[s][msg.sender].weight, i.e. weightOf(msg.sender, s). We bind +// the reasoning to msg.sender implicitly by referencing weightOf on the same recovered signers. + +// =========================================================================== +// MAIN PROPERTY -- the dispatched claim (duplicate never double-counts). +// N=2 duplicate: one copy insufficient => can never accept. +// The ascending gate `s1 <= lastSigner(=s0)` (s1 == s0) fires BEFORE the second weight is +// counted, so a duplicate cannot reach threshold via double-counting. +// Observable: the RETURN value under a duplicate precondition; no re-sum of totalWeight. +// =========================================================================== +rule duplicateSignerNeverAccepts(address acc) { + env e; + require e.msg.sender == acc; // loop reads storage at `acc` + address s0 = recoveredSigner(0); + address s1 = recoveredSigner(1); + + require s0 != 0; // sentinel (address(0)) corner excluded + require s0 == s1; // duplicate slice -> same signer + require weightOf(acc, s0) > 0; // s0 is a real guardian for acc + require thresholdOf(acc) > weightOf(acc, s0); // one copy alone is insufficient + + bytes4 ret = isValidSignatureWithSenderH(e, 2); + + assert ret != MAGIC(), + "duplicate signer reached threshold via double-counting -- ascending gate at :61/:79 failed"; +} + +// =========================================================================== +// GENERALIZED (N=3): a FULLY-duplicated 3-slice input never double-counts to threshold. +// This is the sound N=3 generalization of the duplicate-never-double-counts claim over the +// COUNTED prefix (per dispatch: assert over the processed prefix only, never over unreached +// suffix indices). All three slices recover the SAME signer; one copy of its weight is +// insufficient. The ascending gate at :61 rejects the second (equal) signer's iteration BEFORE +// any second weight is counted, so the loop can never reach threshold -- no accept. +// Observable: the RETURN value; no re-sum of totalWeight. +// +// NOTE: we deliberately do NOT forbid a duplicate that sits in an UNREACHED suffix (e.g. s2==s0 +// while a distinct s0,s1 already reached threshold at i=1 and returned before s2 was recovered): +// that is a legitimate accept from a distinct counted set, and the earlier over-strong version +// of this rule was correctly falsified by exactly that case. +// =========================================================================== +rule fullyDuplicatedNeverAccepts(address acc) { + env e; + require e.msg.sender == acc; // loop reads storage at `acc` + address s0 = recoveredSigner(0); + address s1 = recoveredSigner(1); + address s2 = recoveredSigner(2); + + require s0 != 0; // sentinel corner excluded + require s0 == s1 && s1 == s2; // fully duplicated input + require weightOf(acc, s0) > 0; // s0 is a real guardian + require thresholdOf(acc) > weightOf(acc, s0); // one copy alone insufficient + + bytes4 ret = isValidSignatureWithSenderH(e, 3); + + assert ret != MAGIC(), + "fully-duplicated 3-slice input reached threshold via double-counting -- ascending gate failed"; +} + +// =========================================================================== +// SCOPING COMPLEMENT: a single guardian whose weight already meets threshold IS accepted. +// Proves the rules above are scoped to the double-count bug, not over-claiming duplicates +// always reject. sigCount==1: loop (0..sigCount-2) skipped, last pass processes slice 0; +// gate `s0 <= 0` false (s0 != 0), weight added, threshold met. +// =========================================================================== +rule singleSufficientSignerAccepts(address acc) { + env e; + require e.msg.sender == acc; // loop reads storage at `acc` + address s0 = recoveredSigner(0); + + require s0 != 0; + require weightOf(acc, s0) >= thresholdOf(acc); + require thresholdOf(acc) != 0; + + bytes4 ret = isValidSignatureWithSenderH(e, 1); + + assert ret == MAGIC(), + "a single guardian whose weight meets threshold must be accepted"; +} + +// =========================================================================== +// REACHABILITY WITNESS (i) -- MANDATORY. Non-vacuous ACCEPT via TWO DISTINCT guardians. +// There EXISTS a 2-slice input with distinct, strictly-ASCENDING signers whose combined real +// weights reach threshold and return MAGICVALUE. Kills vacuity of the accept branch. +// =========================================================================== +rule witnessTwoDistinctAccept(address acc) { + env e; + require e.msg.sender == acc; // loop reads storage at `acc` + address s0 = recoveredSigner(0); + address s1 = recoveredSigner(1); + + require s0 != 0; + require s0 < s1; // strictly ascending -> distinct + require weightOf(acc, s0) < thresholdOf(acc); // first alone insufficient + require weightOf(acc, s0) + weightOf(acc, s1) >= thresholdOf(acc); // together sufficient + require thresholdOf(acc) != 0; + + bytes4 ret = isValidSignatureWithSenderH(e, 2); + + satisfy ret == MAGIC(), + "no reachable accept from two distinct guardians summing to threshold on adapter storage"; +} + +// =========================================================================== +// REACHABILITY WITNESS (ii) -- MANDATORY discrimination. The audit PoC is reachable AND rejected. +// There EXISTS a duplicate (s0==s1) with 2w>=threshold>w that returns INVALID: the exact pre-fix +// exploit input, now correctly rejected by the ascending gate on adapter storage. +// =========================================================================== +rule witnessDuplicatePoCRejected(address acc) { + env e; + require e.msg.sender == acc; // loop reads storage at `acc` + address s0 = recoveredSigner(0); + address s1 = recoveredSigner(1); + + require s0 != 0; + require s0 == s1; + require weightOf(acc, s0) > 0; + require 2 * weightOf(acc, s0) >= thresholdOf(acc); // WOULD reach threshold if double-counted + require thresholdOf(acc) > weightOf(acc, s0); // one copy alone does NOT + require thresholdOf(acc) != 0; + + bytes4 ret = isValidSignatureWithSenderH(e, 2); + + satisfy ret == INVALID(), + "audit PoC (duplicate, 2w>=threshold>w) not reachable as a rejection on adapter storage"; +} diff --git a/certora/WeightedUserOpDedup.conf b/certora/WeightedUserOpDedup.conf new file mode 100644 index 0000000..cf210c0 --- /dev/null +++ b/certora/WeightedUserOpDedup.conf @@ -0,0 +1,11 @@ +{ + "files": ["certora/harness/WeightedUserOpDedupHarness.sol"], + "verify": "WeightedUserOpDedupHarness:certora/WeightedUserOpDedup.spec", + "solc": "solc8.30", + "solc_via_ir": true, + "solc_optimize": "20000", + "loop_iter": "2", + "optimistic_loop": true, + "rule_sanity": "basic", + "msg": "EC-02 WeightedThresholdBase._verifyUserOp: final==proposal signer never double-counts (real-bytecode de-dup)" +} diff --git a/certora/WeightedUserOpDedup.spec b/certora/WeightedUserOpDedup.spec new file mode 100644 index 0000000..b2bc39b --- /dev/null +++ b/certora/WeightedUserOpDedup.spec @@ -0,0 +1,141 @@ +/* + * EC-02-USEROP-DEDUP (certora leg of a RACE) -- WeightedThresholdBase._verifyUserOp + * split-UserOp de-dup / no-double-count. Source: src/base/WeightedThresholdBase.sol:102-176. + * + * DISPATCHED OBSERVABLE (Critical, contrapositive double-count): + * If the FINAL (finalHash) signer is the SAME guardian as the single proposalHash signer, and + * ONE copy of that guardian's weight w is below threshold while TWO copies would reach it + * (w < threshold <= 2w), then _verifyUserOp MUST return FALSE. i.e. the in-memory de-dup + * (:161-173) counts the final signer's weight AT MOST ONCE even when it also appears among the + * proposal signers -> a single guardian signing both the proposal and the final hash CANNOT + * reach threshold alone. This is an auth-bypass class bug if broken. + * + * WHY THIS IS THE TCB-INDEPENDENT LEG: + * The harness INHERITS the real WeightedThresholdBase and calls its REAL _verifyUserOp + * bytecode over REAL calldata `sigBytes`. Nothing in the aggregation / ordering / de-dup loop is + * re-implemented (contrast the Halmos verbatim replica). The ONLY summarized primitive is + * ECDSA.tryRecoverCalldata (an ecrecover precompile the solver cannot invert), replaced by a + * deterministic uninterpreted ghost keyed on the message `hash`: + * - the N-1 proposal slices recover against `proposalHash` -> recover(proposalHash) + * - the final slice recovers against `finalHash` -> recover(finalHash) + * These are INDEPENDENT symbolic addresses; the adversary is free to CHOOSE the final signer + * equal to the proposal signer (recover(finalHash) == recover(proposalHash)) -- exactly the + * double-count attack. Proof covers the base de-dup logic, NOT ECDSA soundness. (DISCLOSED TCB: + * solc8.30 + Certora solver + hash-keyed recover summary; real base bytecode otherwise.) + * + * TAUTOLOGY CHECK: the assertion is the RETURN value of _verifyUserOp under a + * final==proposal-signer precondition -- an observable outcome. It does not recompute the + * summation or re-run the de-dup scan. PASS. + * + * REACHABILITY CHECK (both mandatory, via `satisfy`): + * (i) satisfiability -- a legitimate split sigBytes (one proposal signer + a DIFFERENT final signer, + * weights summing >= threshold) returns TRUE (accept branch is live, not vacuous). + * (ii) discrimination -- the double-count attack input is REACHABLE as a rejection; if the + * de-dup were absent the same input would return true, so this proves the de-dup fires. + * + * @author taek + */ + +methods { + function weightOf(address) external returns (uint256) envfree; + function verifyUserOp(bytes32, bytes32, bytes, uint256) external returns (bool) envfree; + + // ECDSA.tryRecoverCalldata is summarized as a deterministic uninterpreted function of the + // message hash: same hash -> same recovered address. Distinct hashes (proposalHash vs + // finalHash) recover INDEPENDENT addresses, which the adversary may pin equal. + function ECDSA.tryRecoverCalldata(bytes32 hash, bytes calldata slice) internal returns (address) => + recover(hash); +} + +// Deterministic per-message recovery. Uninterpreted -> the adversary picks the value, but it is +// fixed per hash (a fixed 65-byte slice signing a fixed hash yields a fixed signer). +ghost recover(bytes32) returns address; + +// A 2-sigBytes split UserOp: sigBytes.length == 130 == one proposal slice (over proposalHash) + one final +// slice (over finalHash). sigCount-1 == 1 proposal signer; final slice is the last 65 bytes. +definition TWO_SIG_LEN() returns uint256 = 130; + +// --------------------------------------------------------------------------- +// MAIN PROPERTY (dispatched) -- de-dup: a guardian signing BOTH the proposal and the final hash +// double-counts to reach threshold alone => the base MUST reject. Contrapositive of the bug. +// --------------------------------------------------------------------------- +rule finalEqualsProposalNeverDoubleCounts(bytes32 pHash, bytes32 fHash) { + bytes sigBytes; + require sigBytes.length == TWO_SIG_LEN(); // exactly 1 proposal signer + 1 final signer + + address pSigner = recover(pHash); // the single proposalHash signer + address fSigner = recover(fHash); // the finalHash signer + + require fSigner == pSigner; // ADVERSARY: final signer == proposal signer + require pSigner != 0; // a real, non-sentinel guardian + + uint256 w = weightOf(pSigner); + require w > 0; // pSigner is a guardian (non-zero weight) + + // one copy is insufficient, two copies WOULD reach threshold -> the whole attack surface + uint256 threshold; + require to_mathint(threshold) > to_mathint(w); + require to_mathint(threshold) <= 2 * to_mathint(w); + + bool ok = verifyUserOp(pHash, fHash, sigBytes, threshold); + + assert !ok, + "de-dup broken: a guardian signing both proposal and final reached threshold alone"; +} + +// --------------------------------------------------------------------------- +// REACHABILITY WITNESS (i) -- the ACCEPT branch is live (non-vacuous). +// Two DISTINCT guardians: one proposal signer + a different final signer, weights sum >= threshold. +// --------------------------------------------------------------------------- +rule witnessDistinctSignersAccept(bytes32 pHash, bytes32 fHash) { + bytes sigBytes; + require sigBytes.length == TWO_SIG_LEN(); + + address pSigner = recover(pHash); + address fSigner = recover(fHash); + + require pSigner != 0 && fSigner != 0; + require pSigner != fSigner; // two DISTINCT guardians + + uint256 wp = weightOf(pSigner); + uint256 wf = weightOf(fSigner); + require wp > 0 && wf > 0; + + uint256 threshold; + require threshold > 0; + require to_mathint(wp) < to_mathint(threshold); // proposal signer alone insufficient + require to_mathint(wp) + to_mathint(wf) >= to_mathint(threshold); // together sufficient + + bool ok = verifyUserOp(pHash, fHash, sigBytes, threshold); + + satisfy ok, + "no reachable accept from two distinct guardians summing to threshold (accept vacuous)"; +} + +// --------------------------------------------------------------------------- +// REACHABILITY WITNESS (ii) -- the double-count ATTACK input is reachable as a REJECTION. +// The exact final==proposal PoC with 2w>=threshold>w returns false: proves the de-dup fires +// (absent de-dup, this same input would return true). +// --------------------------------------------------------------------------- +rule witnessDoubleCountPoCRejected(bytes32 pHash, bytes32 fHash) { + bytes sigBytes; + require sigBytes.length == TWO_SIG_LEN(); + + address pSigner = recover(pHash); + address fSigner = recover(fHash); + + require fSigner == pSigner; + require pSigner != 0; + + uint256 w = weightOf(pSigner); + require w > 0; + + uint256 threshold; + require to_mathint(threshold) > to_mathint(w); + require 2 * to_mathint(w) >= to_mathint(threshold); + + bool ok = verifyUserOp(pHash, fHash, sigBytes, threshold); + + satisfy !ok, + "double-count PoC (final==proposal, 2w>=threshold>w) not reachable as a rejection"; +} diff --git a/certora/harness/DefaultSecurityHookBatchHarness.sol b/certora/harness/DefaultSecurityHookBatchHarness.sol new file mode 100644 index 0000000..c47bf22 --- /dev/null +++ b/certora/harness/DefaultSecurityHookBatchHarness.sol @@ -0,0 +1,40 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import {DefaultSecurityHook} from "src/hooks/DefaultSecurityHook.sol"; + +/// @notice Certora harness for the DSH-BATCH-01 (spec ^req-17) all-or-nothing BATCH property. +/// Dedicated to that property to stay decoupled from the shared DefaultSecurityHookHarness. +/// +/// `checkBatch` is a faithful replica of the production BATCH branch of `preCheck`: +/// for (i) { (t,v,d) = getExecution(pointers,i); _checkCall(t,v,d); } +/// The loop body is the SAME internal `_checkCall` the production code invokes per decoded +/// pointer, so the all-or-nothing revert AGGREGATION is the real code. This isolates that +/// aggregation from LibERC7579's calldata-pointer decoding (a decoder concern, not ^req-17). +/// A revert in any iteration aborts the whole call, exactly as production. +/// @author taek +contract DefaultSecurityHookBatchHarness is DefaultSecurityHook { + /// @notice A single sub-call of a BATCH execution. + struct Call { + address target; + uint256 value; + bytes data; + } + + /// @notice Replica of the production CALLTYPE_BATCH loop over `_checkCall`. + function checkBatch(Call[] calldata calls) external view { + for (uint256 i; i < calls.length; i++) { + _checkCall(calls[i].target, calls[i].value, calls[i].data); + } + } + + // ---- read-only accessors into AllowlistEntry (mapping members are not auto-exposed) ---- + + function h_allowed(address account, address target) external view returns (bool) { + return allowlist[account][target].allowed; + } + + function h_allSelectorsAllowed(address account, address target) external view returns (bool) { + return allowlist[account][target].allSelectorsAllowed; + } +} diff --git a/certora/harness/DefaultSecurityHookHarness.sol b/certora/harness/DefaultSecurityHookHarness.sol new file mode 100644 index 0000000..f36f22f --- /dev/null +++ b/certora/harness/DefaultSecurityHookHarness.sol @@ -0,0 +1,45 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import {DefaultSecurityHook} from "src/hooks/DefaultSecurityHook.sol"; + +/// @notice Certora harness for DefaultSecurityHook. +/// Exposes the internal, view `_checkCall` as an external entrypoint so the +/// allowlist-gating property (DSH-ALLOW-01) can assert the observable revert/success +/// outcome directly, without routing through preCheck's calldata-decoding assembly +/// and LibERC7579 machinery. +/// +/// The `_isModule` internal probe is summarized in the spec (see methods block) so the +/// module branch is deterministic; here we only surface `_checkCall` and read-only +/// accessors into the AllowlistEntry struct (its mapping member is not auto-exposed). +/// @author taek +contract DefaultSecurityHookHarness is DefaultSecurityHook { + /// @notice External, reverting wrapper over the internal view `_checkCall`. + /// msg.sender here is the account (matches `_checkCall`'s use of msg.sender). + /// The spec constrains the leading 4 bytes of `data` to a blocked selector. + function checkCall(address target, uint256 value, bytes calldata data) external view { + _checkCall(target, value, data); + } + + /// @notice The leading-4-byte selector of `data`, exactly as `_checkCall` reads it + /// (`bytes4(data[:4])`). Lets the spec obtain the selector value CVL cannot slice, + /// and query the allowlist mapping with the SAME key `_checkCall` uses. This is a + /// calldata slice, not a reimplementation of blocked-set membership. + function selOf(bytes calldata data) external pure returns (bytes4) { + return bytes4(data[:4]); + } + + // ---- read-only accessors into AllowlistEntry (mapping member not auto-exposed) ---- + + function h_allowed(address account, address target) external view returns (bool) { + return allowlist[account][target].allowed; + } + + function h_allSelectorsAllowed(address account, address target) external view returns (bool) { + return allowlist[account][target].allSelectorsAllowed; + } + + function h_selectorMapped(address account, address target, bytes4 selector) external view returns (bool) { + return allowlist[account][target].selectors[selector]; + } +} diff --git a/certora/harness/ECDSAValidatorHarness.sol b/certora/harness/ECDSAValidatorHarness.sol new file mode 100644 index 0000000..fadbedd --- /dev/null +++ b/certora/harness/ECDSAValidatorHarness.sol @@ -0,0 +1,69 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import {ECDSA} from "solady/utils/ECDSA.sol"; +import {ECDSAValidator, ECDSAValidatorStorage} from "src/validators/ECDSAValidator.sol"; + +/// @title ECDSAValidatorHarness +/// @author taek +/// @notice Certora harness for ECDSAValidator.validateUserOp +/// (src/validators/ECDSAValidator.sol:69-81, _verifySignature :60-67). +/// +/// ECDSA.tryRecoverCalldata is elliptic-curve recovery the symbolic engine cannot +/// invert. Both recover calls inside _verifySignature are routed through the +/// overridable `_recover(hash)` below, which Certora replaces with an UNINTERPRETED +/// ghost `recovered(hash)`: a symbolic, attacker-controlled address that is +/// DETERMINISTIC in the hash (same hash -> same recovered address). The two distinct +/// hashes (userOpHash and its eth-signed variant) therefore map to two independent +/// symbolic addresses, faithfully modeling the two tryRecoverCalldata calls. +/// +/// The rest of the logic (owner==0 early-fail, the OR of the two recover checks, +/// the SUCCESS/FAILED return) is inherited byte-for-byte from the real contract via +/// the overridden _verifySignature, which is a line-for-line copy of the original +/// except recover is swapped for _recover. +contract ECDSAValidatorHarness is ECDSAValidator { + /// @dev Uninterpreted stand-in for ECDSA.tryRecoverCalldata(hash, sig). + /// Certora summarizes this as `recovered(hash)` (declared in the spec): a symbolic + /// address, attacker-controlled but DETERMINISTIC in hash. Body is a compile-only + /// placeholder never executed under the summary. + function _recover(bytes32 hash) internal view virtual returns (address) { + return address(uint160(uint256(hash))); + } + + /// @dev Stand-in for ECDSA.toEthSignedMessageHash(hash). Certora summarizes this as the + /// ghost `ethSignedHash(hash)` so BOTH the harness's second recover key and the + /// spec's assertion key are the SAME symbolic value (injective per hash). Body is a + /// compile-only placeholder; the concrete keccak is never executed under the summary. + function _ethHash(bytes32 hash) internal pure virtual returns (bytes32) { + return ECDSA.toEthSignedMessageHash(hash); + } + + /// @dev Line-for-line copy of ECDSAValidator._verifySignature (:60-67) with the two + /// ECDSA.tryRecoverCalldata(...) calls replaced by _recover(hash) and the eth-hash + /// derivation replaced by _ethHash(hash). + function _verifySignatureHarness(bytes32 hash, address signer) internal view returns (bool) { + if (signer == _recover(hash)) { + return true; + } + bytes32 ethHash = _ethHash(hash); + address recovered = _recover(ethHash); + return signer == recovered; + } + + /// @notice Port of validateUserOp (:69-81) reading real storage, routing recovery + /// through the uninterpreted _recover. `userOpHash` is passed directly (the + /// signature is fully captured by the uninterpreted recover, so it is elided). + function validateUserOpHarness(bytes32 userOpHash) external view returns (uint256) { + address owner = ecdsaValidatorStorage[msg.sender].owner; + // Fail if owner is not set (prevents matching with failed recovery returning address(0)). + if (owner == address(0)) return 1; // SIG_VALIDATION_FAILED_UINT + return _verifySignatureHarness(userOpHash, owner) + ? 0 // SIG_VALIDATION_SUCCESS_UINT + : 1; // SIG_VALIDATION_FAILED_UINT + } + + /// @notice Expose the owner slot for envfree reads in the spec. + function ownerOf(address account) external view returns (address) { + return ecdsaValidatorStorage[account].owner; + } +} diff --git a/certora/harness/S01Harness.sol b/certora/harness/S01Harness.sol new file mode 100644 index 0000000..7690560 --- /dev/null +++ b/certora/harness/S01Harness.sol @@ -0,0 +1,37 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import {DefaultSecurityHook} from "src/hooks/DefaultSecurityHook.sol"; + +/// @notice Dedicated Certora harness for the S-01 stale-selector regression property. +/// Kept separate from the shared DefaultSecurityHookHarness to avoid file collisions. +/// Exposes the internal view `_checkCall` (which keys off msg.sender as the account) and +/// the APPROVE blocked-selector constant. +/// @author taek +contract S01Harness is DefaultSecurityHook { + /// @notice External wrapper over internal view `_checkCall`; msg.sender is the account. + function checkCall(address target, uint256 value, bytes calldata data) external view { + _checkCall(target, value, data); + } + + /// @notice The ERC-20 approve selector — a blocked selector under _isBlockedSelector. + function approveSelector() external pure returns (bytes4) { + return APPROVE; + } + + /// @notice Leading 4-byte selector of `data` (mirrors `bytes4(data[:4])` in _checkCall). + /// Lets the spec constrain the selector without CVL calldata slicing. + function leadingSelector(bytes calldata data) external pure returns (bytes4) { + return bytes4(data[:4]); + } + + /// @notice True iff the (account,target) allowlist entry is pristine: not allowed, + /// no tracked selectors, and the specific selector unset. Lets the spec pin a clean + /// freshly-initialized start state (the audit scenario) — CVL cannot see the mapping + /// inside AllowlistEntry, so cleanliness must be asserted through this observable read. + function entryPristine(address account, address target, bytes4 selector) external view returns (bool) { + AllowlistEntry storage entry = allowlist[account][target]; + return + !entry.allowed && !entry.allSelectorsAllowed && entry.selectorList.length == 0 && !entry.selectors[selector]; + } +} diff --git a/certora/harness/S02Harness.sol b/certora/harness/S02Harness.sol new file mode 100644 index 0000000..c0bca08 --- /dev/null +++ b/certora/harness/S02Harness.sol @@ -0,0 +1,120 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import {PackedUserOperation} from "account-abstraction/interfaces/PackedUserOperation.sol"; +import {TimelockPolicy} from "src/policies/TimelockPolicy.sol"; + +/// @notice Certora harness for the TOB-2 stale-proposal-across-reinstall property (S-02). +/// +/// Unlike TimelockPolicyHarness (which PLANTS an arbitrary proposal.epoch to test the +/// epoch-gate in isolation), this harness drives the REAL epoch state machine end to end so +/// the proof witnesses the genuine trace: install (epoch bump) -> create (stamps currentEpoch) +/// -> reinstall (epoch bump) -> execute (must FAIL because the stamped epoch is now stale). +/// +/// It does NOT reimplement any transition: +/// - reinstall() calls the REAL onInstall (PolicyBase) which runs _policyOninstall and its +/// `currentEpoch[id][msg.sender]++`, the exact line under audit (:113). +/// - createProposal() stamps the proposal epoch with the REAL `currentEpoch[id][account]` +/// expression the production creation path uses (:227-232), on the fixed triple. +/// - execUserOp() calls the REAL _handleProposalExecutionInternal (:243), including the +/// epoch gate at :256. +/// - statusOf/epochOf/currentEpoch are observable reads of the real `proposals`/`currentEpoch`. +/// +/// The (account, callData, nonce) triple is fixed across create/execute/read so, under +/// optimistic_hashing (injective keccak), every operation lands on the same storage slot. +/// @author taek +contract S02Harness is TimelockPolicy { + /// @notice Drive the REAL install epoch bump for (id, wallet = the caller). + /// Calls the real internal `_policyOninstall` directly so `msg.sender` is the account that + /// invoked `install` (NOT the harness — that was the S02Harness v1 bug). In production the + /// ERC-7579 account itself calls the module's onInstall, so keying `currentEpoch` by + /// msg.sender is exactly the production semantics; here msg.sender == the installing account. + /// This runs the unmodified init guard + `currentEpoch[id][msg.sender]++`. First-ever install + /// goes 0 -> 1; a reinstall requires a prior uninstall. `config` is the abi.encode of + /// (delay, expirationPeriod, guardian) so `_policyOninstall`'s abi.decode succeeds. + function install(bytes32 id, bytes calldata config) external { + _policyOninstall(id, config); + } + + /// @notice Drive the REAL uninstall for (id, wallet = the caller). + function uninstall(bytes32 id, bytes calldata data) external { + _policyOnUninstall(id, data); + } + + /// @notice Create a Pending proposal at the fixed (account, callData, nonce) slot, stamping + /// the REAL current epoch (identical expression to the production creation path). Kept as a + /// thin wrapper so the spec can drive creation on a symbolic triple; the epoch value written + /// is not chosen by the spec — it is read live from `currentEpoch[id][account]`. + function createProposal( + bytes32 id, + address account, + bytes calldata callData, + uint256 nonce, + uint48 validAfter, + uint48 validUntil + ) external { + bytes32 userOpKey = keccak256(abi.encode(account, keccak256(callData), nonce)); + require(proposals[userOpKey][id][account].status == ProposalStatus.None, "exists"); + proposals[userOpKey][id][account] = Proposal({ + status: ProposalStatus.Pending, + validAfter: validAfter, + validUntil: validUntil, + epoch: currentEpoch[id][account] + }); + } + + /// @notice Drive the REAL execution transition on the fixed triple. + function execUserOp(bytes32 id, address account, bytes calldata callData, uint256 nonce) + external + returns (uint256) + { + PackedUserOperation memory userOp; + userOp.sender = account; + userOp.nonce = nonce; + userOp.callData = callData; + return this._execCalldata(id, userOp, account); + } + + function _execCalldata(bytes32 id, PackedUserOperation calldata userOp, address account) + external + returns (uint256) + { + require(msg.sender == address(this)); + return _handleProposalExecutionInternal(id, userOp, account); + } + + // ---- observable reads ---- + function statusOf(bytes32 id, address wallet, address account, bytes calldata callData, uint256 nonce) + external + view + returns (uint8) + { + bytes32 userOpKey = keccak256(abi.encode(account, keccak256(callData), nonce)); + return uint8(proposals[userOpKey][id][wallet].status); + } + + function epochOf(bytes32 id, address wallet, address account, bytes calldata callData, uint256 nonce) + external + view + returns (uint256) + { + bytes32 userOpKey = keccak256(abi.encode(account, keccak256(callData), nonce)); + return proposals[userOpKey][id][wallet].epoch; + } + + function currentEpochOf(bytes32 id, address wallet) external view returns (uint256) { + return currentEpoch[id][wallet]; + } + + function isInitialized(bytes32 id, address wallet) external view returns (bool) { + return timelockConfig[id][wallet].initialized; + } + + function ST_PENDING() external pure returns (uint8) { + return uint8(ProposalStatus.Pending); + } + + function sigFailedSentinel() external pure returns (uint256) { + return 1; + } +} diff --git a/certora/harness/S03Harness.sol b/certora/harness/S03Harness.sol new file mode 100644 index 0000000..93be9f4 --- /dev/null +++ b/certora/harness/S03Harness.sol @@ -0,0 +1,27 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import {DefaultSecurityHook} from "src/hooks/DefaultSecurityHook.sol"; + +/// @notice Dedicated Certora harness for the S-03 uninstall/reinstall stale-state property. +/// Follows the S01Harness pattern (kept separate to avoid file collisions). Exposes only +/// observable reads of storage that CVL cannot reach through the struct-embedded mapping; +/// it does NOT reimplement any clear logic. +/// @author taek +contract S03Harness is DefaultSecurityHook { + /// @notice Number of tracked targets for an account (observable read of allowlistedTargets). + function allowlistedTargetsLength(address account) external view returns (uint256) { + return allowlistedTargets[account].length; + } + + /// @notice True iff the (account,target) allowlist entry is pristine: not allowed, + /// no all-selectors flag, no tracked selectors, and the specific selector unset. + /// Lets the spec pin a clean freshly-initialized start state — CVL cannot see the + /// in-struct mapping, so pre-state cleanliness is asserted through this observable read. + /// It does NOT recompute the clear loop; it only READS the four observable fields. + function entryPristine(address account, address target, bytes4 selector) external view returns (bool) { + AllowlistEntry storage entry = allowlist[account][target]; + return + !entry.allowed && !entry.allSelectorsAllowed && entry.selectorList.length == 0 && !entry.selectors[selector]; + } +} diff --git a/certora/harness/TimelockPolicyHarness.sol b/certora/harness/TimelockPolicyHarness.sol new file mode 100644 index 0000000..ff24330 --- /dev/null +++ b/certora/harness/TimelockPolicyHarness.sol @@ -0,0 +1,93 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import {PackedUserOperation} from "account-abstraction/interfaces/PackedUserOperation.sol"; +import {TimelockPolicy} from "src/policies/TimelockPolicy.sol"; + +/// @notice Certora harness for TimelockPolicy's proposal state machine (TL-LIFECYCLE-01). +/// +/// The real execution/creation paths reconstruct the storage key from a +/// PackedUserOperation (keccak256(abi.encode(sender, keccak256(callData), nonce))) and +/// slice proposal fields out of the signature calldata — neither is tractable to drive +/// symbolically from CVL. This harness surfaces the SAME real transition logic keyed by an +/// explicit (account, callData, nonce) triple, so the spec can fix one triple across +/// execute / cancel / read and — under optimistic_hashing (injective keccak) — land on the +/// same storage slot every time. +/// +/// It does NOT reimplement the state machine: execUserOp builds a PackedUserOperation and +/// calls the real internal `_handleProposalExecutionInternal`; cancelProposal is the real +/// external function; statusOf reads the real `proposals` mapping. `plantProposal` and +/// `initConfig` only set pre-state (the "symbolic status over {None,Pending,Executed, +/// Cancelled}" universe and an initialized config) — pre-state, not transition logic. +/// @author taek +contract TimelockPolicyHarness is TimelockPolicy { + /// @notice Raw status of the proposal at the (account, callData, nonce) slot for (id, wallet). + /// Reads the real `proposals` mapping via the SAME key the transition functions compute. + function statusOf(bytes32 id, address wallet, address account, bytes calldata callData, uint256 nonce) + external + view + returns (uint8) + { + bytes32 userOpKey = keccak256(abi.encode(account, keccak256(callData), nonce)); + return uint8(proposals[userOpKey][id][wallet].status); + } + + /// @notice epoch of the proposal at the slot (for the epoch-match gate in execution). + function epochOf(bytes32 id, address wallet, address account, bytes calldata callData, uint256 nonce) + external + view + returns (uint256) + { + bytes32 userOpKey = keccak256(abi.encode(account, keccak256(callData), nonce)); + return proposals[userOpKey][id][wallet].epoch; + } + + /// @notice Drive the REAL execution transition for a proposal keyed by the given userOp. + /// Calls the real internal `_handleProposalExecutionInternal` directly with a calldata + /// PackedUserOperation — no memory->calldata self-hop — so the whole path inlines for the + /// Prover (keeps the sanity/vacuity engine able to see a live non-reverting path). The spec + /// constrains userOp.sender/callData/nonce to match the planted proposal's key. + /// Returns the ERC-4337 validation data (SIG_VALIDATION_FAILED_UINT == 1 on failure). + function execUserOp(bytes32 id, PackedUserOperation calldata userOp, address account) external returns (uint256) { + return _handleProposalExecutionInternal(id, userOp, account); + } + + // ---- pre-state setters (set the symbolic starting universe; NOT transition logic) ---- + + /// @notice Initialize config so the policy treats (id, wallet) as installed and gives a + /// current epoch. Sets currentEpoch to `epoch` so plantProposal can match/mismatch it. + function initConfig( + bytes32 id, + address wallet, + uint48 delay, + uint48 expirationPeriod, + address guardian, + uint256 epoch + ) external { + timelockConfig[id][wallet] = TimelockConfig({ + delay: delay, expirationPeriod: expirationPeriod, guardian: guardian, initialized: true + }); + currentEpoch[id][wallet] = epoch; + } + + /// @notice Plant an arbitrary proposal pre-state at the (account, callData, nonce) slot. + /// Lets the spec quantify status over {None, Pending, Executed, Cancelled}. + function plantProposal( + bytes32 id, + address wallet, + address account, + bytes calldata callData, + uint256 nonce, + uint8 status, + uint48 validAfter, + uint48 validUntil, + uint256 epoch + ) external { + bytes32 userOpKey = keccak256(abi.encode(account, keccak256(callData), nonce)); + proposals[userOpKey][id][wallet] = + Proposal({status: ProposalStatus(status), validAfter: validAfter, validUntil: validUntil, epoch: epoch}); + } + + // Status ordinals (ProposalStatus enum) and the SIG_VALIDATION_FAILED sentinel (1) are + // expressed as CVL `definition`s in the spec — no harness constant getters needed. +} diff --git a/certora/harness/WeightedECDSAHarness.sol b/certora/harness/WeightedECDSAHarness.sol new file mode 100644 index 0000000..733a5b3 --- /dev/null +++ b/certora/harness/WeightedECDSAHarness.sol @@ -0,0 +1,62 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import {ERC1271_MAGICVALUE, ERC1271_INVALID} from "src/types/Constants.sol"; + +/// @title WeightedECDSAHarness +/// @author taek +/// @notice Certora harness for WeightedECDSAValidator.isValidSignatureWithSender +/// (src/validators/WeightedECDSAValidator.sol:294-320). +/// +/// ECDSA.recover is a precompile the symbolic engine cannot invert, so it is +/// replaced by an overridable `_recoverSigner(index)` that Certora summarizes as an +/// UNINTERPRETED function returning a fully symbolic, attacker-controlled address. +/// Consistency (same signature slice -> same signer) is preserved by keying the +/// summary on the loop index i, a 1:1 image of the fixed 65-byte slice offset +/// `data[i*65:(i+1)*65]`. An adversary who submits the same slice twice therefore +/// recovers the SAME address twice; the spec's `s0 == s1` precondition forces exactly +/// that collision, replicating the audit PoC. +/// +/// Every other line is a byte-for-byte copy of the fixed implementation: the +/// line-310 strictly-descending guard runs BEFORE the line-314 accumulation and the +/// line-315/316 threshold return. +contract WeightedECDSAHarness { + uint24 public threshold; + // guardian weight lookup keyed by recovered signer address + mapping(address => uint24) public weightOf; + + /// @dev Uninterpreted stand-in for ECDSA.recover(hash, data[i*65:(i+1)*65]). + /// Certora replaces this call with the `recoveredSigner(i)` summary declared in the + /// spec: a symbolic address chosen by the adversary but DETERMINISTIC in `i` + /// (same slice -> same signer). The body below is only a compile placeholder. + function _recoverSigner(uint256 i) internal view virtual returns (address) { + return address(uint160(i)); + } + + /// @notice Exact port of WeightedECDSAValidator.isValidSignatureWithSender lines 294-320. + /// @param sigCount number of 65-byte signature slices = data.length / 65 + function isValidSignatureWithSender(uint256 sigCount) external view returns (bytes4) { + if (threshold == 0) { + return ERC1271_INVALID; + } + if (sigCount == 0) { + return ERC1271_INVALID; + } + uint256 totalWeight = 0; + address prevSigner = address(uint160(type(uint160).max)); + for (uint256 i = 0; i < sigCount; i++) { + address signer = _recoverSigner(i); + // Enforce strictly-descending order (rejects duplicates) BEFORE counting weight, + // otherwise a duplicated single-guardian signature could reach the threshold. + if (signer >= prevSigner) { + return ERC1271_INVALID; + } + prevSigner = signer; + totalWeight += weightOf[signer]; + if (totalWeight >= threshold) { + return ERC1271_MAGICVALUE; + } + } + return ERC1271_INVALID; + } +} diff --git a/certora/harness/WeightedECDSASignerHarness.sol b/certora/harness/WeightedECDSASignerHarness.sol new file mode 100644 index 0000000..4706256 --- /dev/null +++ b/certora/harness/WeightedECDSASignerHarness.sol @@ -0,0 +1,60 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import {WeightedECDSASigner} from "src/signers/WeightedECDSASigner.sol"; +import {ERC1271_MAGICVALUE, ERC1271_INVALID} from "src/types/Constants.sol"; + +/// @title WeightedECDSASignerHarness +/// @author taek +/// @notice Certora harness for the SIGNER's installed ERC-1271 path AFTER the EC-01 refactor moved +/// the aggregation logic onto the shared WeightedThresholdBase. This harness DERIVES from the +/// real WeightedECDSASigner and drives the REAL, COMPILED base bytecode +/// (WeightedThresholdBase._verifySorted, src/base/WeightedThresholdBase.sol:38-93) exactly as +/// reached through WeightedECDSASigner.checkSignature (src/signers/WeightedECDSASigner.sol +/// :162-170) -> _verifySorted -> _guardianWeight (id-keyed guardian[signer][cfg][account], +/// :122-129). +/// +/// RE-ANCHORING (WECDSA-THRESHOLD-01): the pre-refactor spec summarized an in-signer +/// `_validateSignature` that no longer exists and reimplemented the loop byte-for-byte. That +/// copy could silently drift from the moved code. This harness removes the copy — the loop, +/// ascending gate, check-before-count ordering and threshold `>=` all run as the real base +/// bytecode. Only ECDSA recovery is abstracted. +/// +/// RECOVER SUMMARY: ECDSA.tryRecoverCalldata is inline assembly the SMT engine cannot invert. +/// The spec (certora/WeightedECDSASigner.spec) summarizes it as an UNINTERPRETED, DETERMINISTIC +/// ghost `recoveredSigner(i)` keyed on the RECOVERY CALL INDEX i. _verifySorted recovers slice +/// 0 first (loop i=0), then the last slice, in strict program order, so call index == slice +/// index for the small slice counts these rules exercise (1 and 2): call#0 -> slice 0, +/// call#1 -> slice 1. Same slice -> same call index -> same address; a duplicate slice +/// recovers the SAME address, and the spec's `s0 == s1` precondition forces that collision +/// (the TOB-17 PoC). Identical `recoveredSigner(i)` semantics to the pre-refactor spec, now +/// re-anchored onto the moved base bytecode. +/// +/// Storage weights/threshold are read through `weightOf`/`threshold` accessors bound to the +/// FIXED `ID` and to `msg.sender` (the account _verifySorted uses); the Prover leaves that +/// storage symbolic, so the adversary chooses guardian weights. Proof covers aggregation/ +/// ordering, NOT ECDSA soundness. +contract WeightedECDSASignerHarness is WeightedECDSASigner { + bytes32 public constant ID = bytes32(uint256(0x1234)); // fixed permission id / cfg + bytes32 public constant HASH = bytes32(uint256(0x5678)); // fixed digest fed to _verifySorted + + /// @notice Real installed threshold for (ID, msg.sender), as read by checkSignature :168. + function threshold() external view returns (uint24) { + return weightedStorage[ID][msg.sender].threshold; + } + + /// @notice Real id-keyed guardian weight for `signer` at (ID, msg.sender), as read by + /// _guardianWeight (:122-129) inside the real _verifySorted. + function weightOf(address signer) external view returns (uint24) { + return guardian[signer][ID][msg.sender].weight; + } + + /// @notice Drives the REAL base _verifySorted over `sig`, returning the same bytes4 + /// checkSignature would (:169). sigCount = sig.length / 65; `sig` content is irrelevant + /// (recovery is summarized by call index), so the rule pins sig.length to fix the slice + /// count. `sig` is calldata because _verifySorted slices it as calldata. + function validateSignature(bytes calldata sig) external view returns (bytes4) { + uint256 t = weightedStorage[ID][msg.sender].threshold; + return _verifySorted(ID, msg.sender, HASH, sig, t) ? ERC1271_MAGICVALUE : ERC1271_INVALID; + } +} diff --git a/certora/harness/WeightedECDSAValidatorHarness.sol b/certora/harness/WeightedECDSAValidatorHarness.sol new file mode 100644 index 0000000..dc526b6 --- /dev/null +++ b/certora/harness/WeightedECDSAValidatorHarness.sol @@ -0,0 +1,37 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import {WeightedECDSAValidator, VoteStatus, ProposalStatus} from "src/validators/WeightedECDSAValidator.sol"; + +/// @notice Certora harness for WeightedECDSAValidator. +/// Exposes the internal epoch-namespaced key derivation and read-only accessors so the +/// stale-approval replay property (RP-01) can be stated over concrete storage slots +/// without having to reason about the guardian linked-list construction machinery. +/// @author taek +contract WeightedECDSAValidatorHarness is WeightedECDSAValidator { + /// @notice Public wrapper over the internal, configVersion-namespaced key. + function keyOf(address kernel, bytes32 hash) external view returns (bytes32) { + return _key(kernel, hash); + } + + /// @notice Raw vote-slot read at an explicit key (epoch already folded into `key`). + function voteStatusAt(bytes32 key, address g, address kernel) external view returns (VoteStatus) { + return voteStatus[key][g][kernel].status; + } + + /// @notice Read the current epoch. + function version(address kernel) external view returns (uint256) { + return configVersion[kernel]; + } + + /// @notice Guardian weight lookup for a (guardian, kernel) pair. + /// A guardian is "current/enabled" for `kernel` iff this is non-zero. + function weightOf(address g, address kernel) external view returns (uint24) { + return guardian[g][kernel].weight; + } + + /// @notice threshold for a kernel (weightedStorage[kernel].threshold). + function thresholdOf(address kernel) external view returns (uint24) { + return weightedStorage[kernel].threshold; + } +} diff --git a/certora/harness/WeightedThresholdBaseHarness.sol b/certora/harness/WeightedThresholdBaseHarness.sol new file mode 100644 index 0000000..37deec0 --- /dev/null +++ b/certora/harness/WeightedThresholdBaseHarness.sol @@ -0,0 +1,116 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import {ERC1271_MAGICVALUE, ERC1271_INVALID} from "src/types/Constants.sol"; +import {WeightedECDSAValidator} from "src/validators/WeightedECDSAValidator.sol"; + +/// @title WeightedThresholdBaseHarness +/// @author taek +/// @notice Certora harness for the ERC-1271 acceptance path of the REAL WeightedECDSAValidator +/// adapter over the SHARED WeightedThresholdBase._verifySorted +/// (src/base/WeightedThresholdBase.sol:38-93, adapter +/// src/validators/WeightedECDSAValidator.sol:171-178). +/// +/// Distinct from certora/harness/WeightedECDSAHarness.sol (EC-01): that harness is a +/// STANDALONE re-implementation with a fabricated `threshold`/`weightOf` and targets the +/// OLD strictly-DESCENDING validator. THIS harness inherits the real +/// WeightedECDSAValidator and drives the aggregation on the adapter's REAL storage +/// layout: threshold from `weightedStorage[account].threshold` and each weight from the +/// inherited `_guardianWeight(bytes32(0), account, signer)` -> `guardian[signer][account] +/// .weight`. That establishes the shared core is sound on the validator's storage layout +/// (the point of the refactor), TCB-independent from the halmos verbatim-replica leg. +/// +/// ECDSA.tryRecoverCalldata is elliptic-curve recovery the symbolic engine cannot invert +/// and is called inline inside the inherited _verifySorted (no override seam), so the loop +/// is re-expressed here VERBATIM against the shared base's semantics with recovery routed +/// through the overridable `_recoverSigner(i)` (summarized in the spec as an +/// UNINTERPRETED, DETERMINISTIC-in-index ghost: same 65-byte slice sig[i*65:(i+1)*65] -> +/// same recovered address). Every OTHER line -- the ascending gate `signer <= lastSigner` +/// at :61/:79 that runs BEFORE the weight is counted at :71/:87, the non-last zero-weight +/// REVERT at :68-70, the last zero-weight `return false` at :84-86, the `>=` threshold +/// at :72/:88 -- is a byte-for-byte mirror of WeightedThresholdBase._verifySorted, and +/// the weight/threshold reads hit the real validator storage. The proof covers the +/// ordering/threshold aggregation on the adapter's storage, NOT ECDSA soundness. +contract WeightedThresholdBaseHarness is WeightedECDSAValidator { + /// @dev Uninterpreted stand-in for ECDSA.tryRecoverCalldata(hash, sig[i*65:(i+1)*65]). + /// Certora replaces this with the `recoveredSigner(i)` ghost declared in the spec: a + /// symbolic address chosen by the adversary but DETERMINISTIC in the loop index `i`, + /// which is a 1:1 image of the fixed 65-byte slice offset. A duplicated slice therefore + /// recovers the SAME address; the spec's `s_i == s_j` precondition forces exactly that + /// collision (the audit PoC). Body is a compile-only placeholder never executed. + function _recoverSigner(uint256 i) internal view virtual returns (address) { + return address(uint160(i + 1)); + } + + /// @notice Byte-for-byte mirror of WeightedThresholdBase._verifySorted (:38-93) reading the + /// REAL adapter storage: `weightedStorage[msg.sender].threshold` for the threshold and + /// the inherited real `_guardianWeight(bytes32(0), msg.sender, signer)` for each + /// weight. Only ECDSA.tryRecoverCalldata is swapped for the summarized _recoverSigner. + /// @param sigCount number of 65-byte slices = data.length / 65. + /// @return ERC1271_MAGICVALUE on accept, ERC1271_INVALID otherwise (mirrors the adapter's + /// isValidSignatureWithSender wrapper at :171-178). + function isValidSignatureWithSenderH(uint256 sigCount) external view returns (bytes4) { + address account = msg.sender; + uint256 threshold = weightedStorage[account].threshold; + + // _verifySorted body ------------------------------------------------- + if (threshold == 0) { + return ERC1271_INVALID; + } + if (sigCount == 0) { + return ERC1271_INVALID; + } + + uint256 totalWeight = 0; + address signer; + address lastSigner = address(0); + + // Process all signatures except the last one. + for (uint256 i = 0; i < sigCount - 1; i++) { + signer = _recoverSigner(i); + + // Ascending gate (EC-01): ordering check BEFORE weight is counted. + if (signer <= lastSigner) { + return ERC1271_INVALID; + } + lastSigner = signer; + + uint256 guardianWeight = _guardianWeight(bytes32(0), account, signer); + // Non-last zero-weight signer REVERTS ZeroWeightSigner (gas-griefing guard). + if (guardianWeight == 0) { + _revertZeroWeightSigner(); + } + totalWeight += guardianWeight; + if (totalWeight >= threshold) { + return ERC1271_MAGICVALUE; + } + } + + // Process last signature (index sigCount - 1). + signer = _recoverSigner(sigCount - 1); + if (signer <= lastSigner) { + return ERC1271_INVALID; + } + uint256 lastWeight = _guardianWeight(bytes32(0), account, signer); + // Last signer with zero weight returns false (no revert). + if (lastWeight == 0) { + return ERC1271_INVALID; + } + totalWeight += lastWeight; + if (totalWeight >= threshold) { + return ERC1271_MAGICVALUE; + } + + return ERC1271_INVALID; + } + + /// @notice Real adapter weight lookup (guardian[signer][account].weight), envfree read. + function weightOf(address account, address signer) external view returns (uint256) { + return _guardianWeight(bytes32(0), account, signer); + } + + /// @notice Real adapter threshold (weightedStorage[account].threshold), envfree read. + function thresholdOf(address account) external view returns (uint256) { + return weightedStorage[account].threshold; + } +} diff --git a/certora/harness/WeightedUserOpDedupHarness.sol b/certora/harness/WeightedUserOpDedupHarness.sol new file mode 100644 index 0000000..165ccee --- /dev/null +++ b/certora/harness/WeightedUserOpDedupHarness.sol @@ -0,0 +1,62 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import {WeightedThresholdBase} from "src/base/WeightedThresholdBase.sol"; + +/// @title WeightedUserOpDedupHarness +/// @author taek +/// @notice Certora harness for the split-UserOp weighted-threshold path +/// WeightedThresholdBase._verifyUserOp (src/base/WeightedThresholdBase.sol:102-176). +/// +/// RACE / certora leg (EC-02-USEROP-DEDUP): this harness INHERITS the real +/// WeightedThresholdBase and calls its REAL _verifyUserOp bytecode. Nothing about the +/// aggregation / ordering / de-dup loop is re-implemented here (unlike the Halmos +/// verbatim replica). The only thing summarized away is ECDSA.tryRecoverCalldata, +/// which is an ecrecover-precompile the symbolic engine cannot invert; the CVL spec +/// replaces `ECDSA.tryRecoverCalldata(hash, slice)` with a deterministic ghost keyed on +/// the message `hash`. Because the N-1 proposal signatures are recovered against +/// `proposalHash` and the final signature against `finalHash`, the proposal-signer and +/// the final-signer recover to INDEPENDENT symbolic addresses -- and the adversary is +/// free to choose the final signer EQUAL to the (single) proposal signer, which is +/// exactly the double-count attack this proof must refute. +/// +/// DISCLOSED TCB: proof covers the real base aggregation/ordering/de-dup logic, NOT +/// ECDSA soundness. Real base bytecode makes this leg TCB-independent from the Halmos +/// replica leg. +contract WeightedUserOpDedupHarness is WeightedThresholdBase { + // Real guardian-weight mapping keyed by recovered signer address. + mapping(address => uint256) public weightOf; + + error ZeroWeightSigner(); + error SignersNotSorted(); + + function _revertZeroWeightSigner() internal pure override { + revert ZeroWeightSigner(); + } + + function _revertSignersNotSorted() internal pure override { + revert SignersNotSorted(); + } + + // ponytail: args named (cfg, account) purely to silence Certora's via_ir "unnamed argument" + // summary warning; only `signer` is used. + + /// @dev Weight lookup delegated to the real mapping; cfg/account are ignored in the harness + /// (single guardian set) -- the aggregation logic under test does not depend on them. + function _guardianWeight(bytes32 cfg, address account, address signer) internal view override returns (uint256) { + cfg; + account; + return weightOf[signer]; + } + + /// @notice Thin external wrapper over the REAL WeightedThresholdBase._verifyUserOp. + /// `sig` is real calldata, so the base's %65 / sigCount / slice-offset arithmetic and + /// its proposal loop + final-slice pass + de-dup scan all execute on real bytecode. + function verifyUserOp(bytes32 proposalHash, bytes32 finalHash, bytes calldata sig, uint256 threshold) + external + view + returns (bool) + { + return _verifyUserOp(bytes32(0), address(0), proposalHash, finalHash, sig, threshold); + } +} diff --git a/certora/probe.spec b/certora/probe.spec new file mode 100644 index 0000000..5110ae1 --- /dev/null +++ b/certora/probe.spec @@ -0,0 +1,10 @@ +methods { + function threshold() external returns (uint24) envfree; +} +rule retValueCheck() { + env e; + require e.msg.value == 0; + require threshold() == 0; + bytes4 ret = isValidSignatureWithSender(e, 2); + assert ret == to_bytes4(0xffffffff), "unexpected ret on threshold==0"; +} diff --git a/certora/probe2.conf b/certora/probe2.conf new file mode 100644 index 0000000..d6110f1 --- /dev/null +++ b/certora/probe2.conf @@ -0,0 +1,23 @@ +{ + "files": [ + "certora/harness/DefaultSecurityHookHarness.sol" + ], + "verify": "DefaultSecurityHookHarness:certora/probe2.spec", + "solc": "solc8.30", + "solc_via_ir": true, + "solc_optimize": "20000", + "packages": [ + "src/=src/", + "account-abstraction/=dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/", + "solady/=dependencies/solady-0.1.26/src/", + "openzeppelin-contracts/contracts/=dependencies/@openzeppelin-contracts-5.5.0/", + "forge-std/=dependencies/forge-std-1.11.0/src/" + ], + "loop_iter": "3", + "optimistic_loop": true, + "optimistic_hashing": true, + "hashing_length_bound": "384", + "rule_sanity": "basic", + "global_timeout": 600, + "msg": "DSH-ALLOW-01: allowlist gating exact - blocked non-allowlisted selector reverts" +} diff --git a/certora/probe2.spec b/certora/probe2.spec new file mode 100644 index 0000000..517514f --- /dev/null +++ b/certora/probe2.spec @@ -0,0 +1,15 @@ +methods { + function checkCall(address, uint256, bytes) external; + function h_selectorMapped(address, address, bytes4) external returns (bool) envfree; +} +function bindSel(bytes4 sel, bytes data) returns bool { + return data.length == 4 && data[0]==sel[0] && data[1]==sel[1] && data[2]==sel[2] && data[3]==sel[3]; +} +rule probeSel(address target, bytes data, bytes4 sel) { + env e; + require sel == to_bytes4(0x095ea7b3); + require bindSel(sel, data); + bool m = h_selectorMapped(e.msg.sender, target, sel); + checkCall@withrevert(e, target, 0, data); + assert true; +} diff --git a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/AccessManager.json b/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/AccessManager.json deleted file mode 100644 index a23407e..0000000 --- a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/AccessManager.json +++ /dev/null @@ -1,1175 +0,0 @@ -{ - "_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": "0x608060405234801561000f575f5ffd5b50604051612ca3380380612ca383398101604081905261002e91610441565b6001600160a01b03811661005c57604051630409d6d160e11b81525f60048201526024015b60405180910390fd5b6100685f82818061006f565b50506104bc565b5f6002600160401b03196001600160401b038616016100ac5760405163061c6a4360e21b81526001600160401b0386166004820152602401610053565b6001600160401b0385165f9081526001602090815260408083206001600160a01b038816845290915281205465ffffffffffff16159081156101a15763ffffffff85166100f76102b5565b6101019190610482565b905060405180604001604052808265ffffffffffff1681526020016101318663ffffffff166102c460201b60201c565b6001600160701b039081169091526001600160401b0389165f9081526001602090815260408083206001600160a01b038c16845282529091208351815494909201519092166601000000000000026001600160a01b031990931665ffffffffffff90911617919091179055610247565b6001600160401b0387165f9081526001602090815260408083206001600160a01b038a1684529091528120546101ed9166010000000000009091046001600160701b03169086906102cd565b6001600160401b0389165f9081526001602090815260408083206001600160a01b038c168452909152902080546001600160701b03909316660100000000000002600160301b600160a01b03199093169290921790915590505b6040805163ffffffff8616815265ffffffffffff831660208201528315158183015290516001600160a01b038816916001600160401b038a16917ff98448b987f1428e0e230e1f3c6e2ce15b5693eaf31827fbd0b1ec4b424ae7cf9181900360600190a35095945050505050565b5f6102bf42610373565b905090565b63ffffffff1690565b5f80806102e26001600160701b0387166103a9565b90505f61031d8563ffffffff168763ffffffff168463ffffffff1611610308575f610312565b61031288856104a0565b63ffffffff166103c7565b905063ffffffff811661032e6102b5565b6103389190610482565b925063ffffffff8616602083901b67ffffffff0000000016604085901b6dffffffffffff000000000000000016171793505050935093915050565b5f65ffffffffffff8211156103a5576040516306dfcc6560e41b81526030600482015260248101839052604401610053565b5090565b5f806103bd6001600160701b0384166103d7565b5090949350505050565b8082118183180281185b92915050565b5f80806103eb846103e66102b5565b6103f8565b9250925092509193909250565b6001600160501b03602083901c166001600160701b03831665ffffffffffff604085901c811690841681111561043057828282610434565b815f5f5b9250925092509250925092565b5f60208284031215610451575f5ffd5b81516001600160a01b0381168114610467575f5ffd5b9392505050565b634e487b7160e01b5f52601160045260245ffd5b65ffffffffffff81811683821601908111156103d1576103d161046e565b63ffffffff82811682821603908111156103d1576103d161046e565b6127da806104c95f395ff3fe6080604052600436106101db575f3560e01c80636d5115bd116100fd578063b700961311610092578063d22b598911610062578063d22b598914610636578063d6bb62c614610655578063f801a69814610674578063fe0776f5146106ad575f5ffd5b8063b7009613146105a8578063b7d2b162146105e3578063cc1b6c8114610602578063d1f856ee14610617575f5ffd5b8063a166aa89116100cd578063a166aa8914610501578063a64d95ce14610530578063abd9bd2a1461054f578063ac9650d81461057c575f5ffd5b80636d5115bd1461049157806375b238fc146104b0578063853551b8146104c357806394c7d7ee146104e2575f5ffd5b806330cae187116101735780634665096d116101435780634665096d146104035780634c1da1e2146104185780635296295214610437578063530dd45614610456575f5ffd5b806330cae1871461035c5780633adc277a1461037b5780633ca7c02a146103b15780634136a33c146103cb575f5ffd5b806318ff183c116101ae57806318ff183c146102b25780631cff79cd146102d157806325c471a0146102e45780633078f11414610303575f5ffd5b806308d6122d146101df5780630b0a93ba1461020057806312be87271461025f578063167bd39514610293575b5f5ffd5b3480156101ea575f5ffd5b506101fe6101f93660046120c0565b6106cc565b005b34801561020b575f5ffd5b5061024261021a366004612122565b6001600160401b039081165f9081526001602081905260409091200154600160401b90041690565b6040516001600160401b0390911681526020015b60405180910390f35b34801561026a575f5ffd5b5061027e610279366004612122565b61071e565b60405163ffffffff9091168152602001610256565b34801561029e575f5ffd5b506101fe6102ad36600461213b565b610758565b3480156102bd575f5ffd5b506101fe6102cc366004612176565b61076e565b61027e6102df3660046121df565b6107d0565b3480156102ef575f5ffd5b506101fe6102fe366004612242565b6108fc565b34801561030e575f5ffd5b5061032261031d366004612284565b61091e565b604051610256949392919065ffffffffffff948516815263ffffffff93841660208201529190921660408201529116606082015260800190565b348015610367575f5ffd5b506101fe61037636600461229e565b610982565b348015610386575f5ffd5b5061039a6103953660046122cf565b610994565b60405165ffffffffffff9091168152602001610256565b3480156103bc575f5ffd5b506102426001600160401b0381565b3480156103d6575f5ffd5b5061027e6103e53660046122cf565b5f90815260026020526040902054600160301b900463ffffffff1690565b34801561040e575f5ffd5b5062093a8061027e565b348015610423575f5ffd5b5061027e6104323660046122e6565b6109c5565b348015610442575f5ffd5b506101fe61045136600461229e565b6109f2565b348015610461575f5ffd5b50610242610470366004612122565b6001600160401b039081165f90815260016020819052604090912001541690565b34801561049c575f5ffd5b506102426104ab366004612316565b610a04565b3480156104bb575f5ffd5b506102425f81565b3480156104ce575f5ffd5b506101fe6104dd366004612342565b610a3e565b3480156104ed575f5ffd5b506101fe6104fc3660046121df565b610ad5565b34801561050c575f5ffd5b5061052061051b3660046122e6565b610b7f565b6040519015158152602001610256565b34801561053b575f5ffd5b506101fe61054a36600461235d565b610ba6565b34801561055a575f5ffd5b5061056e610569366004612385565b610bb8565b604051908152602001610256565b348015610587575f5ffd5b5061059b6105963660046123e5565b610bf0565b6040516102569190612423565b3480156105b3575f5ffd5b506105c76105c23660046124a7565b610cd5565b60408051921515835263ffffffff909116602083015201610256565b3480156105ee575f5ffd5b506101fe6105fd366004612284565b610d56565b34801561060d575f5ffd5b506206978061027e565b348015610622575f5ffd5b506105c7610631366004612284565b610d6d565b348015610641575f5ffd5b506101fe6106503660046124ef565b610de6565b348015610660575f5ffd5b5061027e61066f366004612385565b610df8565b34801561067f575f5ffd5b5061069361068e36600461250b565b610f4b565b6040805192835263ffffffff909116602083015201610256565b3480156106b8575f5ffd5b506101fe6106c7366004612284565b61108c565b6106d46110b5565b5f5b828110156107175761070f858585848181106106f4576106f4612578565b9050602002016020810190610709919061258c565b8461112c565b6001016106d6565b5050505050565b6001600160401b0381165f9081526001602081905260408220015461075290600160801b90046001600160701b03166111ad565b92915050565b6107606110b5565b61076a82826111cb565b5050565b6107766110b5565b604051637a9e5e4b60e01b81526001600160a01b038281166004830152831690637a9e5e4b906024015f604051808303815f87803b1580156107b6575f5ffd5b505af11580156107c8573d5f5f3e3d5ffd5b505050505050565b5f3381806107e08388888861123c565b91509150811580156107f6575063ffffffff8116155b15610849578287610807888861128d565b6040516381c6f24b60e01b81526001600160a01b0393841660048201529290911660248301526001600160e01b03191660448201526064015b60405180910390fd5b5f61085684898989610bb8565b90505f63ffffffff831615158061087c575061087182610994565b65ffffffffffff1615155b1561088d5761088a826112a4565b90505b6003546108a38a61089e8b8b61128d565b6113a2565b6003819055506108ea8a8a8a8080601f0160208091040260200160405190810160405280939291908181526020018383808284375f920191909152503492506113c7915050565b506003559450505050505b9392505050565b6109046110b5565b61091883836109128661071e565b84611493565b50505050565b6001600160401b0382165f9081526001602090815260408083206001600160a01b03851684529091528120805465ffffffffffff81169291829182919061097490600160301b90046001600160701b03166116d9565b969991985096509350505050565b61098a6110b5565b61076a82826116fa565b5f8181526002602052604081205465ffffffffffff166109b38161179d565b6109bd57806108f5565b5f9392505050565b6001600160a01b0381165f90815260208190526040812060010154610752906001600160701b03166111ad565b6109fa6110b5565b61076a82826117cb565b6001600160a01b0382165f908152602081815260408083206001600160e01b0319851684529091529020546001600160401b031692915050565b610a466110b5565b6001600160401b0383161580610a6457506001600160401b03838116145b15610a8d5760405163061c6a4360e21b81526001600160401b0384166004820152602401610840565b826001600160401b03167f1256f5b5ecb89caec12db449738f2fbcd1ba5806cf38f35413f4e5c15bf6a4508383604051610ac89291906125cf565b60405180910390a2505050565b60408051638fb3603760e01b80825291513392918391638fb36037916004808201926020929091908290030181865afa158015610b14573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610b3891906125ea565b6001600160e01b03191614610b6b57604051630641fee960e31b81526001600160a01b0382166004820152602401610840565b610717610b7a85838686610bb8565b6112a4565b6001600160a01b03165f90815260208190526040902060010154600160701b900460ff1690565b610bae6110b5565b61076a828261187c565b5f84848484604051602001610bd09493929190612605565b604051602081830303815290604052805190602001209050949350505050565b604080515f815260208101909152606090826001600160401b03811115610c1957610c19612676565b604051908082528060200260200182016040528015610c4c57816020015b6060815260200190600190039081610c375790505b5091505f5b83811015610ccd57610ca830868684818110610c6f57610c6f612578565b9050602002810190610c81919061268a565b85604051602001610c94939291906126cc565b60405160208183030381529060405261198b565b838281518110610cba57610cba612578565b6020908102919091010152600101610c51565b505092915050565b5f5f610ce084610b7f565b15610cef57505f905080610d4e565b306001600160a01b03861603610d1357610d098484611a0d565b5f91509150610d4e565b5f610d1e8585610a04565b90505f5f610d2c8389610d6d565b9150915081610d3c575f5f610d46565b63ffffffff811615815b945094505050505b935093915050565b610d5e6110b5565b610d688282611a23565b505050565b5f8067fffffffffffffffe196001600160401b03851601610d935750600190505f610ddf565b5f5f610d9f868661091e565b5050915091508165ffffffffffff165f14158015610dd45750610dc0611b0c565b65ffffffffffff168265ffffffffffff1611155b93509150610ddf9050565b9250929050565b610dee6110b5565b61076a8282611b1b565b5f3381610e05858561128d565b90505f610e1488888888610bb8565b5f8181526002602052604081205491925065ffffffffffff9091169003610e515760405163060a299b60e41b815260048101829052602401610840565b826001600160a01b0316886001600160a01b031614610eea575f610e755f85610d6d565b5090505f610e8f610e8961021a8b87610a04565b86610d6d565b50905081158015610e9e575080155b15610ee757604051630ff89d4760e21b81526001600160a01b038087166004830152808c1660248301528a1660448201526001600160e01b031985166064820152608401610840565b50505b5f81815260026020526040808220805465ffffffffffff1916908190559051600160301b90910463ffffffff1691829184917fbd9ac67a6e2f6463b80927326310338bcbb4bdb7936ce1365ea3e01067e7b9f791a398975050505050505050565b5f803381610f5b8289898961123c565b9150505f8163ffffffff16610f6e611b0c565b610f7891906126ef565b905063ffffffff82161580610fae57505f8665ffffffffffff16118015610fae57508065ffffffffffff168665ffffffffffff16105b15610fbf5782896108078a8a61128d565b610fd98665ffffffffffff168265ffffffffffff16611bd6565b9550610fe7838a8a8a610bb8565b9450610ff285611be5565b5f8581526002602052604090819020805465ffffffffffff891669ffffffffffffffffffff19821617600160301b9182900463ffffffff90811660010190811692830291909117909255915190955086907f82a2da5dee54ea8021c6545b4444620291e07ee83be6dd57edb175062715f3b490611078908a9088908f908f908f9061270d565b60405180910390a350505094509492505050565b6001600160a01b0381163314610d5e57604051635f159e6360e01b815260040160405180910390fd5b335f806110c3838236611c31565b9150915081610d68578063ffffffff165f0361111d575f6110e48136611cf4565b5060405163f07e038f60e01b81526001600160a01b03871660048201526001600160401b03821660248201529092506044019050610840565b610918610b7a84305f36610bb8565b6001600160a01b0383165f818152602081815260408083206001600160e01b0319871680855290835292819020805467ffffffffffffffff19166001600160401b038716908117909155905192835292917f9ea6790c7dadfd01c9f8b9762b3682607af2c7e79e05a9f9fdf5580dde949151910160405180910390a3505050565b5f5f6111c1836001600160701b03166116d9565b5090949350505050565b6001600160a01b0382165f81815260208190526040908190206001018054841515600160701b0260ff60701b19909116179055517f90d4e7bb7e5d933792b3562e1741306f8be94837e1348dacef9b6f1df56eb1389061123090841515815260200190565b60405180910390a25050565b5f80306001600160a01b0386160361126257611259868585611c31565b91509150611284565b6004831061127e5761127986866105c2878761128d565b611259565b505f9050805b94509492505050565b5f61129b600482848661264f565b6108f591612752565b5f8181526002602052604081205465ffffffffffff811690600160301b900463ffffffff168183036112ec5760405163060a299b60e41b815260048101859052602401610840565b6112f4611b0c565b65ffffffffffff168265ffffffffffff16111561132757604051630c65b5bd60e11b815260048101859052602401610840565b6113308261179d565b1561135157604051631e2975b960e21b815260048101859052602401610840565b5f84815260026020526040808220805465ffffffffffff191690555163ffffffff83169186917f76a2a46953689d4861a5d3f6ed883ad7e6af674a21f8e162707159fc9dde614d9190a39392505050565b6001600160a01b0382165f9081526001600160e01b03198216602052604081206108f5565b6060814710156113f35760405163cf47918160e01b815247600482015260248101839052604401610840565b5f6113ff858486611eda565b905080801561142057505f3d118061142057505f856001600160a01b03163b115b156114355761142d611eef565b9150506108f5565b801561145f57604051639996b31560e01b81526001600160a01b0386166004820152602401610840565b3d156114725761146d611f08565b61148b565b60405163d6bda27560e01b815260040160405180910390fd5b509392505050565b5f67fffffffffffffffe196001600160401b038616016114d15760405163061c6a4360e21b81526001600160401b0386166004820152602401610840565b6001600160401b0385165f9081526001602090815260408083206001600160a01b038816845290915281205465ffffffffffff16159081156115c1578463ffffffff1661151c611b0c565b61152691906126ef565b905060405180604001604052808265ffffffffffff1681526020016115548663ffffffff1663ffffffff1690565b6001600160701b039081169091526001600160401b0389165f9081526001602090815260408083206001600160a01b038c1684528252909120835181549490920151909216600160301b026001600160a01b031990931665ffffffffffff9091161791909117905561166b565b6001600160401b0387165f9081526001602090815260408083206001600160a01b038a16845290915281205461160a91600160301b9091046001600160701b0316908690611f13565b6001600160401b0389165f9081526001602090815260408083206001600160a01b038c168452909152902080546001600160701b03909316600160301b0273ffffffffffffffffffffffffffff000000000000199093169290921790915590505b6040805163ffffffff8616815265ffffffffffff831660208201528315158183015290516001600160a01b038816916001600160401b038a16917ff98448b987f1428e0e230e1f3c6e2ce15b5693eaf31827fbd0b1ec4b424ae7cf9181900360600190a35095945050505050565b5f5f5f6116ed846116e8611b0c565b611fb9565b9250925092509193909250565b6001600160401b038216158061171857506001600160401b03828116145b156117415760405163061c6a4360e21b81526001600160401b0383166004820152602401610840565b6001600160401b038281165f818152600160208190526040808320909101805467ffffffffffffffff19169486169485179055517f1fd6dd7631312dfac2205b52913f99de03b4d7e381d5d27d3dbfe0713e6e63409190a35050565b5f6117a6611b0c565b65ffffffffffff166117bb62093a80846126ef565b65ffffffffffff16111592915050565b6001600160401b03821615806117e957506001600160401b03828116145b156118125760405163061c6a4360e21b81526001600160401b0383166004820152602401610840565b6001600160401b038281165f81815260016020819052604080832090910180546fffffffffffffffff00000000000000001916600160401b958716958602179055517f7a8059630b897b5de4c08ade69f8b90c3ead1f8596d62d10b6c4d14a0afb4ae29190a35050565b67fffffffffffffffe196001600160401b038316016118b95760405163061c6a4360e21b81526001600160401b0383166004820152602401610840565b6001600160401b0382165f908152600160208190526040822001546118f290600160801b90046001600160701b03168362069780611f13565b6001600160401b0385165f818152600160208190526040918290200180546001600160701b03909516600160801b026dffffffffffffffffffffffffffff60801b199095169490941790935591519092507ffeb69018ee8b8fd50ea86348f1267d07673379f72cffdeccec63853ee8ce8b4890610ac8908590859063ffffffff92909216825265ffffffffffff16602082015260400190565b60605f6119988484612005565b90508080156119b957505f3d11806119b957505f846001600160a01b03163b115b156119ce576119c6611eef565b915050610752565b80156119f857604051639996b31560e01b81526001600160a01b0385166004820152602401610840565b3d1561147257611a06611f08565b5092915050565b5f611a1883836113a2565b600354149392505050565b5f67fffffffffffffffe196001600160401b03841601611a615760405163061c6a4360e21b81526001600160401b0384166004820152602401610840565b6001600160401b0383165f9081526001602090815260408083206001600160a01b038616845290915281205465ffffffffffff169003611aa257505f610752565b6001600160401b0383165f8181526001602090815260408083206001600160a01b038716808552925280832080546001600160a01b0319169055519092917ff229baa593af28c41b1d16b748cd7688f0c83aaf92d4be41c44005defe84c16691a350600192915050565b5f611b1642612018565b905090565b6001600160a01b0382165f90815260208190526040812060010154611b4d906001600160701b03168362069780611f13565b6001600160a01b0385165f818152602081815260409182902060010180546dffffffffffffffffffffffffffff19166001600160701b039690961695909517909455805163ffffffff8716815265ffffffffffff841694810194909452919350917fa56b76017453f399ec2327ba00375dbfb1fd070ff854341ad6191e6a2e2de19c9101610ac8565b5f8282188284110282186108f5565b5f8181526002602052604090205465ffffffffffff168015801590611c105750611c0e8161179d565b155b1561076a5760405163813e945960e01b815260048101839052602401610840565b5f806004831015611c4657505f905080610d4e565b306001600160a01b03861603611c6957610d0930611c64868661128d565b611a0d565b5f5f5f611c768787611cf4565b92509250925082158015611c8e5750611c8e30610b7f565b15611ca1575f5f94509450505050610d4e565b5f5f611cad848b610d6d565b9150915081611cc6575f5f965096505050505050610d4e565b611cdc8363ffffffff168263ffffffff16611bd6565b63ffffffff8116159b909a5098505050505050505050565b5f80806004841015611d0d57505f915081905080611ed3565b5f611d18868661128d565b90506001600160e01b031981166310a6aa3760e31b1480611d4957506001600160e01b031981166330cae18760e01b145b80611d6457506001600160e01b0319811663294b14a960e11b145b80611d7f57506001600160e01b03198116635326cae760e11b145b80611d9a57506001600160e01b0319811663d22b598960e01b145b15611daf5760015f5f93509350935050611ed3565b6001600160e01b0319811663063fc60f60e21b1480611dde57506001600160e01b0319811663167bd39560e01b145b80611df957506001600160e01b031981166308d6122d60e01b145b15611e38575f611e0d60246004888a61264f565b810190611e1a91906122e6565b90505f611e26826109c5565b600196505f95509350611ed392505050565b6001600160e01b0319811663012e238d60e51b1480611e6757506001600160e01b03198116635be958b160e11b145b15611ebf575f611e7b60246004888a61264f565b810190611e889190612122565b90506001611eb1826001600160401b039081165f90815260016020819052604090912001541690565b5f9450945094505050611ed3565b5f611eca3083610a04565b5f935093509350505b9250925092565b5f5f5f83516020850186885af1949350505050565b6040513d81523d5f602083013e3d602001810160405290565b6040513d5f823e3d81fd5b5f5f5f611f28866001600160701b03166111ad565b90505f611f638563ffffffff168763ffffffff168463ffffffff1611611f4e575f611f58565b611f588885612788565b63ffffffff16611bd6565b90508063ffffffff16611f74611b0c565b611f7e91906126ef565b925063ffffffff8616602083901b67ffffffff0000000016604085901b6dffffffffffff000000000000000016171793505050935093915050565b69ffffffffffffffffffff602083901c166001600160701b03831665ffffffffffff604085901c8116908416811115611ff457828282611ff8565b815f5f5b9250925092509250925092565b5f5f5f835160208501865af49392505050565b5f65ffffffffffff82111561204a576040516306dfcc6560e41b81526030600482015260248101839052604401610840565b5090565b6001600160a01b0381168114612062575f5ffd5b50565b5f5f83601f840112612075575f5ffd5b5081356001600160401b0381111561208b575f5ffd5b6020830191508360208260051b8501011115610ddf575f5ffd5b80356001600160401b03811681146120bb575f5ffd5b919050565b5f5f5f5f606085870312156120d3575f5ffd5b84356120de8161204e565b935060208501356001600160401b038111156120f8575f5ffd5b61210487828801612065565b90945092506121179050604086016120a5565b905092959194509250565b5f60208284031215612132575f5ffd5b6108f5826120a5565b5f5f6040838503121561214c575f5ffd5b82356121578161204e565b91506020830135801515811461216b575f5ffd5b809150509250929050565b5f5f60408385031215612187575f5ffd5b82356121928161204e565b9150602083013561216b8161204e565b5f5f83601f8401126121b2575f5ffd5b5081356001600160401b038111156121c8575f5ffd5b602083019150836020828501011115610ddf575f5ffd5b5f5f5f604084860312156121f1575f5ffd5b83356121fc8161204e565b925060208401356001600160401b03811115612216575f5ffd5b612222868287016121a2565b9497909650939450505050565b803563ffffffff811681146120bb575f5ffd5b5f5f5f60608486031215612254575f5ffd5b61225d846120a5565b9250602084013561226d8161204e565b915061227b6040850161222f565b90509250925092565b5f5f60408385031215612295575f5ffd5b612192836120a5565b5f5f604083850312156122af575f5ffd5b6122b8836120a5565b91506122c6602084016120a5565b90509250929050565b5f602082840312156122df575f5ffd5b5035919050565b5f602082840312156122f6575f5ffd5b81356108f58161204e565b6001600160e01b031981168114612062575f5ffd5b5f5f60408385031215612327575f5ffd5b82356123328161204e565b9150602083013561216b81612301565b5f5f5f60408486031215612354575f5ffd5b6121fc846120a5565b5f5f6040838503121561236e575f5ffd5b612377836120a5565b91506122c66020840161222f565b5f5f5f5f60608587031215612398575f5ffd5b84356123a38161204e565b935060208501356123b38161204e565b925060408501356001600160401b038111156123cd575f5ffd5b6123d9878288016121a2565b95989497509550505050565b5f5f602083850312156123f6575f5ffd5b82356001600160401b0381111561240b575f5ffd5b61241785828601612065565b90969095509350505050565b5f602082016020835280845180835260408501915060408160051b8601019250602086015f5b8281101561249b57603f19878603018452815180518087528060208301602089015e5f602082890101526020601f19601f83011688010196505050602082019150602084019350600181019050612449565b50929695505050505050565b5f5f5f606084860312156124b9575f5ffd5b83356124c48161204e565b925060208401356124d48161204e565b915060408401356124e481612301565b809150509250925092565b5f5f60408385031215612500575f5ffd5b82356123778161204e565b5f5f5f5f6060858703121561251e575f5ffd5b84356125298161204e565b935060208501356001600160401b03811115612543575f5ffd5b61254f878288016121a2565b909450925050604085013565ffffffffffff8116811461256d575f5ffd5b939692955090935050565b634e487b7160e01b5f52603260045260245ffd5b5f6020828403121561259c575f5ffd5b81356108f581612301565b81835281816020850137505f828201602090810191909152601f909101601f19169091010190565b602081525f6125e26020830184866125a7565b949350505050565b5f602082840312156125fa575f5ffd5b81516108f581612301565b6001600160a01b038581168252841660208201526060604082018190525f9061263190830184866125a7565b9695505050505050565b634e487b7160e01b5f52601160045260245ffd5b5f5f8585111561265d575f5ffd5b83861115612669575f5ffd5b5050820193919092039150565b634e487b7160e01b5f52604160045260245ffd5b5f5f8335601e1984360301811261269f575f5ffd5b8301803591506001600160401b038211156126b8575f5ffd5b602001915036819003821315610ddf575f5ffd5b828482375f8382015f815283518060208601835e5f910190815295945050505050565b65ffffffffffff81811683821601908111156107525761075261263b565b65ffffffffffff861681526001600160a01b038581166020830152841660408201526080606082018190525f9061274790830184866125a7565b979650505050505050565b80356001600160e01b03198116906004841015611a06576001600160e01b031960049490940360031b84901b1690921692915050565b63ffffffff82811682821603908111156107525761075261263b56fea264697066735822122060e0ebb1399afaee0084d5c4fe440fac74d536214d8b1fb3279afcec922b6e2d64736f6c634300081b0033", - "deployedBytecode": "0x6080604052600436106101db575f3560e01c80636d5115bd116100fd578063b700961311610092578063d22b598911610062578063d22b598914610636578063d6bb62c614610655578063f801a69814610674578063fe0776f5146106ad575f5ffd5b8063b7009613146105a8578063b7d2b162146105e3578063cc1b6c8114610602578063d1f856ee14610617575f5ffd5b8063a166aa89116100cd578063a166aa8914610501578063a64d95ce14610530578063abd9bd2a1461054f578063ac9650d81461057c575f5ffd5b80636d5115bd1461049157806375b238fc146104b0578063853551b8146104c357806394c7d7ee146104e2575f5ffd5b806330cae187116101735780634665096d116101435780634665096d146104035780634c1da1e2146104185780635296295214610437578063530dd45614610456575f5ffd5b806330cae1871461035c5780633adc277a1461037b5780633ca7c02a146103b15780634136a33c146103cb575f5ffd5b806318ff183c116101ae57806318ff183c146102b25780631cff79cd146102d157806325c471a0146102e45780633078f11414610303575f5ffd5b806308d6122d146101df5780630b0a93ba1461020057806312be87271461025f578063167bd39514610293575b5f5ffd5b3480156101ea575f5ffd5b506101fe6101f93660046120c0565b6106cc565b005b34801561020b575f5ffd5b5061024261021a366004612122565b6001600160401b039081165f9081526001602081905260409091200154600160401b90041690565b6040516001600160401b0390911681526020015b60405180910390f35b34801561026a575f5ffd5b5061027e610279366004612122565b61071e565b60405163ffffffff9091168152602001610256565b34801561029e575f5ffd5b506101fe6102ad36600461213b565b610758565b3480156102bd575f5ffd5b506101fe6102cc366004612176565b61076e565b61027e6102df3660046121df565b6107d0565b3480156102ef575f5ffd5b506101fe6102fe366004612242565b6108fc565b34801561030e575f5ffd5b5061032261031d366004612284565b61091e565b604051610256949392919065ffffffffffff948516815263ffffffff93841660208201529190921660408201529116606082015260800190565b348015610367575f5ffd5b506101fe61037636600461229e565b610982565b348015610386575f5ffd5b5061039a6103953660046122cf565b610994565b60405165ffffffffffff9091168152602001610256565b3480156103bc575f5ffd5b506102426001600160401b0381565b3480156103d6575f5ffd5b5061027e6103e53660046122cf565b5f90815260026020526040902054600160301b900463ffffffff1690565b34801561040e575f5ffd5b5062093a8061027e565b348015610423575f5ffd5b5061027e6104323660046122e6565b6109c5565b348015610442575f5ffd5b506101fe61045136600461229e565b6109f2565b348015610461575f5ffd5b50610242610470366004612122565b6001600160401b039081165f90815260016020819052604090912001541690565b34801561049c575f5ffd5b506102426104ab366004612316565b610a04565b3480156104bb575f5ffd5b506102425f81565b3480156104ce575f5ffd5b506101fe6104dd366004612342565b610a3e565b3480156104ed575f5ffd5b506101fe6104fc3660046121df565b610ad5565b34801561050c575f5ffd5b5061052061051b3660046122e6565b610b7f565b6040519015158152602001610256565b34801561053b575f5ffd5b506101fe61054a36600461235d565b610ba6565b34801561055a575f5ffd5b5061056e610569366004612385565b610bb8565b604051908152602001610256565b348015610587575f5ffd5b5061059b6105963660046123e5565b610bf0565b6040516102569190612423565b3480156105b3575f5ffd5b506105c76105c23660046124a7565b610cd5565b60408051921515835263ffffffff909116602083015201610256565b3480156105ee575f5ffd5b506101fe6105fd366004612284565b610d56565b34801561060d575f5ffd5b506206978061027e565b348015610622575f5ffd5b506105c7610631366004612284565b610d6d565b348015610641575f5ffd5b506101fe6106503660046124ef565b610de6565b348015610660575f5ffd5b5061027e61066f366004612385565b610df8565b34801561067f575f5ffd5b5061069361068e36600461250b565b610f4b565b6040805192835263ffffffff909116602083015201610256565b3480156106b8575f5ffd5b506101fe6106c7366004612284565b61108c565b6106d46110b5565b5f5b828110156107175761070f858585848181106106f4576106f4612578565b9050602002016020810190610709919061258c565b8461112c565b6001016106d6565b5050505050565b6001600160401b0381165f9081526001602081905260408220015461075290600160801b90046001600160701b03166111ad565b92915050565b6107606110b5565b61076a82826111cb565b5050565b6107766110b5565b604051637a9e5e4b60e01b81526001600160a01b038281166004830152831690637a9e5e4b906024015f604051808303815f87803b1580156107b6575f5ffd5b505af11580156107c8573d5f5f3e3d5ffd5b505050505050565b5f3381806107e08388888861123c565b91509150811580156107f6575063ffffffff8116155b15610849578287610807888861128d565b6040516381c6f24b60e01b81526001600160a01b0393841660048201529290911660248301526001600160e01b03191660448201526064015b60405180910390fd5b5f61085684898989610bb8565b90505f63ffffffff831615158061087c575061087182610994565b65ffffffffffff1615155b1561088d5761088a826112a4565b90505b6003546108a38a61089e8b8b61128d565b6113a2565b6003819055506108ea8a8a8a8080601f0160208091040260200160405190810160405280939291908181526020018383808284375f920191909152503492506113c7915050565b506003559450505050505b9392505050565b6109046110b5565b61091883836109128661071e565b84611493565b50505050565b6001600160401b0382165f9081526001602090815260408083206001600160a01b03851684529091528120805465ffffffffffff81169291829182919061097490600160301b90046001600160701b03166116d9565b969991985096509350505050565b61098a6110b5565b61076a82826116fa565b5f8181526002602052604081205465ffffffffffff166109b38161179d565b6109bd57806108f5565b5f9392505050565b6001600160a01b0381165f90815260208190526040812060010154610752906001600160701b03166111ad565b6109fa6110b5565b61076a82826117cb565b6001600160a01b0382165f908152602081815260408083206001600160e01b0319851684529091529020546001600160401b031692915050565b610a466110b5565b6001600160401b0383161580610a6457506001600160401b03838116145b15610a8d5760405163061c6a4360e21b81526001600160401b0384166004820152602401610840565b826001600160401b03167f1256f5b5ecb89caec12db449738f2fbcd1ba5806cf38f35413f4e5c15bf6a4508383604051610ac89291906125cf565b60405180910390a2505050565b60408051638fb3603760e01b80825291513392918391638fb36037916004808201926020929091908290030181865afa158015610b14573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610b3891906125ea565b6001600160e01b03191614610b6b57604051630641fee960e31b81526001600160a01b0382166004820152602401610840565b610717610b7a85838686610bb8565b6112a4565b6001600160a01b03165f90815260208190526040902060010154600160701b900460ff1690565b610bae6110b5565b61076a828261187c565b5f84848484604051602001610bd09493929190612605565b604051602081830303815290604052805190602001209050949350505050565b604080515f815260208101909152606090826001600160401b03811115610c1957610c19612676565b604051908082528060200260200182016040528015610c4c57816020015b6060815260200190600190039081610c375790505b5091505f5b83811015610ccd57610ca830868684818110610c6f57610c6f612578565b9050602002810190610c81919061268a565b85604051602001610c94939291906126cc565b60405160208183030381529060405261198b565b838281518110610cba57610cba612578565b6020908102919091010152600101610c51565b505092915050565b5f5f610ce084610b7f565b15610cef57505f905080610d4e565b306001600160a01b03861603610d1357610d098484611a0d565b5f91509150610d4e565b5f610d1e8585610a04565b90505f5f610d2c8389610d6d565b9150915081610d3c575f5f610d46565b63ffffffff811615815b945094505050505b935093915050565b610d5e6110b5565b610d688282611a23565b505050565b5f8067fffffffffffffffe196001600160401b03851601610d935750600190505f610ddf565b5f5f610d9f868661091e565b5050915091508165ffffffffffff165f14158015610dd45750610dc0611b0c565b65ffffffffffff168265ffffffffffff1611155b93509150610ddf9050565b9250929050565b610dee6110b5565b61076a8282611b1b565b5f3381610e05858561128d565b90505f610e1488888888610bb8565b5f8181526002602052604081205491925065ffffffffffff9091169003610e515760405163060a299b60e41b815260048101829052602401610840565b826001600160a01b0316886001600160a01b031614610eea575f610e755f85610d6d565b5090505f610e8f610e8961021a8b87610a04565b86610d6d565b50905081158015610e9e575080155b15610ee757604051630ff89d4760e21b81526001600160a01b038087166004830152808c1660248301528a1660448201526001600160e01b031985166064820152608401610840565b50505b5f81815260026020526040808220805465ffffffffffff1916908190559051600160301b90910463ffffffff1691829184917fbd9ac67a6e2f6463b80927326310338bcbb4bdb7936ce1365ea3e01067e7b9f791a398975050505050505050565b5f803381610f5b8289898961123c565b9150505f8163ffffffff16610f6e611b0c565b610f7891906126ef565b905063ffffffff82161580610fae57505f8665ffffffffffff16118015610fae57508065ffffffffffff168665ffffffffffff16105b15610fbf5782896108078a8a61128d565b610fd98665ffffffffffff168265ffffffffffff16611bd6565b9550610fe7838a8a8a610bb8565b9450610ff285611be5565b5f8581526002602052604090819020805465ffffffffffff891669ffffffffffffffffffff19821617600160301b9182900463ffffffff90811660010190811692830291909117909255915190955086907f82a2da5dee54ea8021c6545b4444620291e07ee83be6dd57edb175062715f3b490611078908a9088908f908f908f9061270d565b60405180910390a350505094509492505050565b6001600160a01b0381163314610d5e57604051635f159e6360e01b815260040160405180910390fd5b335f806110c3838236611c31565b9150915081610d68578063ffffffff165f0361111d575f6110e48136611cf4565b5060405163f07e038f60e01b81526001600160a01b03871660048201526001600160401b03821660248201529092506044019050610840565b610918610b7a84305f36610bb8565b6001600160a01b0383165f818152602081815260408083206001600160e01b0319871680855290835292819020805467ffffffffffffffff19166001600160401b038716908117909155905192835292917f9ea6790c7dadfd01c9f8b9762b3682607af2c7e79e05a9f9fdf5580dde949151910160405180910390a3505050565b5f5f6111c1836001600160701b03166116d9565b5090949350505050565b6001600160a01b0382165f81815260208190526040908190206001018054841515600160701b0260ff60701b19909116179055517f90d4e7bb7e5d933792b3562e1741306f8be94837e1348dacef9b6f1df56eb1389061123090841515815260200190565b60405180910390a25050565b5f80306001600160a01b0386160361126257611259868585611c31565b91509150611284565b6004831061127e5761127986866105c2878761128d565b611259565b505f9050805b94509492505050565b5f61129b600482848661264f565b6108f591612752565b5f8181526002602052604081205465ffffffffffff811690600160301b900463ffffffff168183036112ec5760405163060a299b60e41b815260048101859052602401610840565b6112f4611b0c565b65ffffffffffff168265ffffffffffff16111561132757604051630c65b5bd60e11b815260048101859052602401610840565b6113308261179d565b1561135157604051631e2975b960e21b815260048101859052602401610840565b5f84815260026020526040808220805465ffffffffffff191690555163ffffffff83169186917f76a2a46953689d4861a5d3f6ed883ad7e6af674a21f8e162707159fc9dde614d9190a39392505050565b6001600160a01b0382165f9081526001600160e01b03198216602052604081206108f5565b6060814710156113f35760405163cf47918160e01b815247600482015260248101839052604401610840565b5f6113ff858486611eda565b905080801561142057505f3d118061142057505f856001600160a01b03163b115b156114355761142d611eef565b9150506108f5565b801561145f57604051639996b31560e01b81526001600160a01b0386166004820152602401610840565b3d156114725761146d611f08565b61148b565b60405163d6bda27560e01b815260040160405180910390fd5b509392505050565b5f67fffffffffffffffe196001600160401b038616016114d15760405163061c6a4360e21b81526001600160401b0386166004820152602401610840565b6001600160401b0385165f9081526001602090815260408083206001600160a01b038816845290915281205465ffffffffffff16159081156115c1578463ffffffff1661151c611b0c565b61152691906126ef565b905060405180604001604052808265ffffffffffff1681526020016115548663ffffffff1663ffffffff1690565b6001600160701b039081169091526001600160401b0389165f9081526001602090815260408083206001600160a01b038c1684528252909120835181549490920151909216600160301b026001600160a01b031990931665ffffffffffff9091161791909117905561166b565b6001600160401b0387165f9081526001602090815260408083206001600160a01b038a16845290915281205461160a91600160301b9091046001600160701b0316908690611f13565b6001600160401b0389165f9081526001602090815260408083206001600160a01b038c168452909152902080546001600160701b03909316600160301b0273ffffffffffffffffffffffffffff000000000000199093169290921790915590505b6040805163ffffffff8616815265ffffffffffff831660208201528315158183015290516001600160a01b038816916001600160401b038a16917ff98448b987f1428e0e230e1f3c6e2ce15b5693eaf31827fbd0b1ec4b424ae7cf9181900360600190a35095945050505050565b5f5f5f6116ed846116e8611b0c565b611fb9565b9250925092509193909250565b6001600160401b038216158061171857506001600160401b03828116145b156117415760405163061c6a4360e21b81526001600160401b0383166004820152602401610840565b6001600160401b038281165f818152600160208190526040808320909101805467ffffffffffffffff19169486169485179055517f1fd6dd7631312dfac2205b52913f99de03b4d7e381d5d27d3dbfe0713e6e63409190a35050565b5f6117a6611b0c565b65ffffffffffff166117bb62093a80846126ef565b65ffffffffffff16111592915050565b6001600160401b03821615806117e957506001600160401b03828116145b156118125760405163061c6a4360e21b81526001600160401b0383166004820152602401610840565b6001600160401b038281165f81815260016020819052604080832090910180546fffffffffffffffff00000000000000001916600160401b958716958602179055517f7a8059630b897b5de4c08ade69f8b90c3ead1f8596d62d10b6c4d14a0afb4ae29190a35050565b67fffffffffffffffe196001600160401b038316016118b95760405163061c6a4360e21b81526001600160401b0383166004820152602401610840565b6001600160401b0382165f908152600160208190526040822001546118f290600160801b90046001600160701b03168362069780611f13565b6001600160401b0385165f818152600160208190526040918290200180546001600160701b03909516600160801b026dffffffffffffffffffffffffffff60801b199095169490941790935591519092507ffeb69018ee8b8fd50ea86348f1267d07673379f72cffdeccec63853ee8ce8b4890610ac8908590859063ffffffff92909216825265ffffffffffff16602082015260400190565b60605f6119988484612005565b90508080156119b957505f3d11806119b957505f846001600160a01b03163b115b156119ce576119c6611eef565b915050610752565b80156119f857604051639996b31560e01b81526001600160a01b0385166004820152602401610840565b3d1561147257611a06611f08565b5092915050565b5f611a1883836113a2565b600354149392505050565b5f67fffffffffffffffe196001600160401b03841601611a615760405163061c6a4360e21b81526001600160401b0384166004820152602401610840565b6001600160401b0383165f9081526001602090815260408083206001600160a01b038616845290915281205465ffffffffffff169003611aa257505f610752565b6001600160401b0383165f8181526001602090815260408083206001600160a01b038716808552925280832080546001600160a01b0319169055519092917ff229baa593af28c41b1d16b748cd7688f0c83aaf92d4be41c44005defe84c16691a350600192915050565b5f611b1642612018565b905090565b6001600160a01b0382165f90815260208190526040812060010154611b4d906001600160701b03168362069780611f13565b6001600160a01b0385165f818152602081815260409182902060010180546dffffffffffffffffffffffffffff19166001600160701b039690961695909517909455805163ffffffff8716815265ffffffffffff841694810194909452919350917fa56b76017453f399ec2327ba00375dbfb1fd070ff854341ad6191e6a2e2de19c9101610ac8565b5f8282188284110282186108f5565b5f8181526002602052604090205465ffffffffffff168015801590611c105750611c0e8161179d565b155b1561076a5760405163813e945960e01b815260048101839052602401610840565b5f806004831015611c4657505f905080610d4e565b306001600160a01b03861603611c6957610d0930611c64868661128d565b611a0d565b5f5f5f611c768787611cf4565b92509250925082158015611c8e5750611c8e30610b7f565b15611ca1575f5f94509450505050610d4e565b5f5f611cad848b610d6d565b9150915081611cc6575f5f965096505050505050610d4e565b611cdc8363ffffffff168263ffffffff16611bd6565b63ffffffff8116159b909a5098505050505050505050565b5f80806004841015611d0d57505f915081905080611ed3565b5f611d18868661128d565b90506001600160e01b031981166310a6aa3760e31b1480611d4957506001600160e01b031981166330cae18760e01b145b80611d6457506001600160e01b0319811663294b14a960e11b145b80611d7f57506001600160e01b03198116635326cae760e11b145b80611d9a57506001600160e01b0319811663d22b598960e01b145b15611daf5760015f5f93509350935050611ed3565b6001600160e01b0319811663063fc60f60e21b1480611dde57506001600160e01b0319811663167bd39560e01b145b80611df957506001600160e01b031981166308d6122d60e01b145b15611e38575f611e0d60246004888a61264f565b810190611e1a91906122e6565b90505f611e26826109c5565b600196505f95509350611ed392505050565b6001600160e01b0319811663012e238d60e51b1480611e6757506001600160e01b03198116635be958b160e11b145b15611ebf575f611e7b60246004888a61264f565b810190611e889190612122565b90506001611eb1826001600160401b039081165f90815260016020819052604090912001541690565b5f9450945094505050611ed3565b5f611eca3083610a04565b5f935093509350505b9250925092565b5f5f5f83516020850186885af1949350505050565b6040513d81523d5f602083013e3d602001810160405290565b6040513d5f823e3d81fd5b5f5f5f611f28866001600160701b03166111ad565b90505f611f638563ffffffff168763ffffffff168463ffffffff1611611f4e575f611f58565b611f588885612788565b63ffffffff16611bd6565b90508063ffffffff16611f74611b0c565b611f7e91906126ef565b925063ffffffff8616602083901b67ffffffff0000000016604085901b6dffffffffffff000000000000000016171793505050935093915050565b69ffffffffffffffffffff602083901c166001600160701b03831665ffffffffffff604085901c8116908416811115611ff457828282611ff8565b815f5f5b9250925092509250925092565b5f5f5f835160208501865af49392505050565b5f65ffffffffffff82111561204a576040516306dfcc6560e41b81526030600482015260248101839052604401610840565b5090565b6001600160a01b0381168114612062575f5ffd5b50565b5f5f83601f840112612075575f5ffd5b5081356001600160401b0381111561208b575f5ffd5b6020830191508360208260051b8501011115610ddf575f5ffd5b80356001600160401b03811681146120bb575f5ffd5b919050565b5f5f5f5f606085870312156120d3575f5ffd5b84356120de8161204e565b935060208501356001600160401b038111156120f8575f5ffd5b61210487828801612065565b90945092506121179050604086016120a5565b905092959194509250565b5f60208284031215612132575f5ffd5b6108f5826120a5565b5f5f6040838503121561214c575f5ffd5b82356121578161204e565b91506020830135801515811461216b575f5ffd5b809150509250929050565b5f5f60408385031215612187575f5ffd5b82356121928161204e565b9150602083013561216b8161204e565b5f5f83601f8401126121b2575f5ffd5b5081356001600160401b038111156121c8575f5ffd5b602083019150836020828501011115610ddf575f5ffd5b5f5f5f604084860312156121f1575f5ffd5b83356121fc8161204e565b925060208401356001600160401b03811115612216575f5ffd5b612222868287016121a2565b9497909650939450505050565b803563ffffffff811681146120bb575f5ffd5b5f5f5f60608486031215612254575f5ffd5b61225d846120a5565b9250602084013561226d8161204e565b915061227b6040850161222f565b90509250925092565b5f5f60408385031215612295575f5ffd5b612192836120a5565b5f5f604083850312156122af575f5ffd5b6122b8836120a5565b91506122c6602084016120a5565b90509250929050565b5f602082840312156122df575f5ffd5b5035919050565b5f602082840312156122f6575f5ffd5b81356108f58161204e565b6001600160e01b031981168114612062575f5ffd5b5f5f60408385031215612327575f5ffd5b82356123328161204e565b9150602083013561216b81612301565b5f5f5f60408486031215612354575f5ffd5b6121fc846120a5565b5f5f6040838503121561236e575f5ffd5b612377836120a5565b91506122c66020840161222f565b5f5f5f5f60608587031215612398575f5ffd5b84356123a38161204e565b935060208501356123b38161204e565b925060408501356001600160401b038111156123cd575f5ffd5b6123d9878288016121a2565b95989497509550505050565b5f5f602083850312156123f6575f5ffd5b82356001600160401b0381111561240b575f5ffd5b61241785828601612065565b90969095509350505050565b5f602082016020835280845180835260408501915060408160051b8601019250602086015f5b8281101561249b57603f19878603018452815180518087528060208301602089015e5f602082890101526020601f19601f83011688010196505050602082019150602084019350600181019050612449565b50929695505050505050565b5f5f5f606084860312156124b9575f5ffd5b83356124c48161204e565b925060208401356124d48161204e565b915060408401356124e481612301565b809150509250925092565b5f5f60408385031215612500575f5ffd5b82356123778161204e565b5f5f5f5f6060858703121561251e575f5ffd5b84356125298161204e565b935060208501356001600160401b03811115612543575f5ffd5b61254f878288016121a2565b909450925050604085013565ffffffffffff8116811461256d575f5ffd5b939692955090935050565b634e487b7160e01b5f52603260045260245ffd5b5f6020828403121561259c575f5ffd5b81356108f581612301565b81835281816020850137505f828201602090810191909152601f909101601f19169091010190565b602081525f6125e26020830184866125a7565b949350505050565b5f602082840312156125fa575f5ffd5b81516108f581612301565b6001600160a01b038581168252841660208201526060604082018190525f9061263190830184866125a7565b9695505050505050565b634e487b7160e01b5f52601160045260245ffd5b5f5f8585111561265d575f5ffd5b83861115612669575f5ffd5b5050820193919092039150565b634e487b7160e01b5f52604160045260245ffd5b5f5f8335601e1984360301811261269f575f5ffd5b8301803591506001600160401b038211156126b8575f5ffd5b602001915036819003821315610ddf575f5ffd5b828482375f8382015f815283518060208601835e5f910190815295945050505050565b65ffffffffffff81811683821601908111156107525761075261263b565b65ffffffffffff861681526001600160a01b038581166020830152841660408201526080606082018190525f9061274790830184866125a7565b979650505050505050565b80356001600160e01b03198116906004841015611a06576001600160e01b031960049490940360031b84901b1690921692915050565b63ffffffff82811682821603908111156107525761075261263b56fea264697066735822122060e0ebb1399afaee0084d5c4fe440fac74d536214d8b1fb3279afcec922b6e2d64736f6c634300081b0033", - "linkReferences": {}, - "deployedLinkReferences": {} -} diff --git a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/ERC1967Proxy.json b/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/ERC1967Proxy.json deleted file mode 100644 index 1c7e383..0000000 --- a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/ERC1967Proxy.json +++ /dev/null @@ -1,76 +0,0 @@ -{ - "_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": "0x608060405260405161039738038061039783398101604081905261002291610219565b61002c8282610033565b50506102e8565b61003c82610091565b6040516001600160a01b038316907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b905f90a280511561008557610080828261010c565b505050565b61008d6101ad565b5050565b806001600160a01b03163b5f036100cb57604051634c9c8ce360e01b81526001600160a01b03821660048201526024015b60405180910390fd5b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc80546001600160a01b0319166001600160a01b0392909216919091179055565b60605f61011984846101ce565b905080801561013a57505f3d118061013a57505f846001600160a01b03163b115b1561014f576101476101e1565b9150506101a7565b801561017957604051639996b31560e01b81526001600160a01b03851660048201526024016100c2565b3d1561018c576101876101fa565b6101a5565b60405163d6bda27560e01b815260040160405180910390fd5b505b92915050565b34156101cc5760405163b398979f60e01b815260040160405180910390fd5b565b5f5f5f835160208501865af49392505050565b6040513d81523d5f602083013e3d602001810160405290565b6040513d5f823e3d81fd5b634e487b7160e01b5f52604160045260245ffd5b5f5f6040838503121561022a575f5ffd5b82516001600160a01b0381168114610240575f5ffd5b60208401519092506001600160401b0381111561025b575f5ffd5b8301601f8101851361026b575f5ffd5b80516001600160401b0381111561028457610284610205565b604051601f8201601f19908116603f011681016001600160401b03811182821017156102b2576102b2610205565b6040528181528282016020018710156102c9575f5ffd5b8160208401602083015e5f602083830101528093505050509250929050565b60a3806102f45f395ff3fe6080604052600a600c565b005b60186014601a565b6050565b565b5f604b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc546001600160a01b031690565b905090565b365f5f375f5f365f845af43d5f5f3e8080156069573d5ff35b3d5ffdfea26469706673582212208fbb08860046f0df561fc15db5674455fa68789235bb5051bafc932a24685dc464736f6c634300081b0033", - "deployedBytecode": "0x6080604052600a600c565b005b60186014601a565b6050565b565b5f604b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc546001600160a01b031690565b905090565b365f5f375f5f365f845af43d5f5f3e8080156069573d5ff35b3d5ffdfea26469706673582212208fbb08860046f0df561fc15db5674455fa68789235bb5051bafc932a24685dc464736f6c634300081b0033", - "linkReferences": {}, - "deployedLinkReferences": {} -} diff --git a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/ERC2771Forwarder.json b/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/ERC2771Forwarder.json deleted file mode 100644 index 88c806d..0000000 --- a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/ERC2771Forwarder.json +++ /dev/null @@ -1,388 +0,0 @@ -{ - "_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": "0x610160604052348015610010575f5ffd5b5060405161131738038061131783398101604081905261002f91610189565b6040805180820190915260018152603160f81b60208201528190610053825f6100fd565b610120526100628160016100fd565b61014052815160208084019190912060e052815190820120610100524660a0526100ee60e05161010051604080517f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f60208201529081019290925260608201524660808201523060a08201525f9060c00160405160208183030381529060405280519060200120905090565b60805250503060c052506103cf565b5f602083511015610118576101118361012f565b9050610129565b8161012384826102bd565b5060ff90505b92915050565b5f5f829050601f81511115610162578260405163305a27a960e01b81526004016101599190610377565b60405180910390fd5b805161016d826103ac565b179392505050565b634e487b7160e01b5f52604160045260245ffd5b5f60208284031215610199575f5ffd5b81516001600160401b038111156101ae575f5ffd5b8201601f810184136101be575f5ffd5b80516001600160401b038111156101d7576101d7610175565b604051601f8201601f19908116603f011681016001600160401b038111828210171561020557610205610175565b60405281815282820160200186101561021c575f5ffd5b8160208401602083015e5f91810160200191909152949350505050565b600181811c9082168061024d57607f821691505b60208210810361026b57634e487b7160e01b5f52602260045260245ffd5b50919050565b601f8211156102b857805f5260205f20601f840160051c810160208510156102965750805b601f840160051c820191505b818110156102b5575f81556001016102a2565b50505b505050565b81516001600160401b038111156102d6576102d6610175565b6102ea816102e48454610239565b84610271565b6020601f82116001811461031c575f83156103055750848201515b5f19600385901b1c1916600184901b1784556102b5565b5f84815260208120601f198516915b8281101561034b578785015182556020948501946001909201910161032b565b508482101561036857868401515f19600387901b60f8161c191681555b50505050600190811b01905550565b602081525f82518060208401528060208501604085015e5f604082850101526040601f19601f83011684010191505092915050565b8051602080830151919081101561026b575f1960209190910360031b1b16919050565b60805160a05160c05160e051610100516101205161014051610ef76104205f395f61039e01525f61036d01525f610a6f01525f610a4701525f6109a201525f6109cc01525f6109f60152610ef75ff3fe608060405260043610610049575f3560e01c806319d8d38c1461004d5780637ecebe001461008157806384b0196e146100c3578063ccf96b4a146100ea578063df905caf146100ff575b5f5ffd5b348015610058575f5ffd5b5061006c610067366004610bae565b610112565b60405190151581526020015b60405180910390f35b34801561008c575f5ffd5b506100b561009b366004610c00565b6001600160a01b03165f9081526002602052604090205490565b604051908152602001610078565b3480156100ce575f5ffd5b506100d7610142565b6040516100789796959493929190610c49565b6100fd6100f8366004610cdf565b610184565b005b6100fd61010d366004610bae565b610289565b5f5f5f5f61011f856102e4565b509250925092508280156101305750815b80156101395750805b95945050505050565b5f6060805f5f5f6060610153610366565b61015b610397565b604080515f80825260208201909252600f60f81b9b939a50919850469750309650945092509050565b6001600160a01b038116155f80805b85811015610242578686828181106101ad576101ad610d61565b90506020028101906101bf9190610d75565b6101cd906040013584610d93565b92505f6101fd8888848181106101e5576101e5610d61565b90506020028101906101f79190610d75565b866103c4565b9050806102395787878381811061021657610216610d61565b90506020028101906102289190610d75565b610236906040013584610d93565b92505b50600101610193565b50348214610271576040516370647f7960e01b8152600481018390523460248201526044015b60405180910390fd5b801561028157610281848261059f565b505050505050565b806040013534146102b957604080516370647f7960e01b8152908201356004820152346024820152604401610268565b6102c48160016103c4565b6102e15760405163d6bda27560e01b815260040160405180910390fd5b50565b5f5f5f5f5f5f6102f387610616565b909250905061031061030b6040890160208a01610c00565b610788565b4261032160a08a0160808b01610db2565b65ffffffffffff161015838015610355575061034060208a018a610c00565b6001600160a01b0316836001600160a01b0316145b919750955093509150509193509193565b60606103927f00000000000000000000000000000000000000000000000000000000000000005f610801565b905090565b60606103927f00000000000000000000000000000000000000000000000000000000000000006001610801565b5f5f5f5f5f6103d2876102e4565b935093509350935085156104985783610420576103f56040880160208901610c00565b60405163d2650cd160e01b81526001600160a01b039091166004820152306024820152604401610268565b826104595761043560a0880160808901610db2565b604051634a777ac560e11b815265ffffffffffff9091166004820152602401610268565b81610498578061046c6020890189610c00565b604051636422d02b60e11b81526001600160a01b03928316600482015291166024820152604401610268565b8380156104a25750815b80156104ab5750825b15610595576001600160a01b0381165f908152600260205260408120805460018101909155905060608801355f6104e860408b0160208c01610c00565b905060408a01355f6104fd60a08d018d610dd7565b61050a60208f018f610c00565b60405160200161051c93929190610e21565b60405160208183030381529060405290505f5f5f83516020850186888af19a505a9050610549818e6108ac565b604080518781528c151560208201526001600160a01b038916917f842fb24a83793558587a3dab2be7674da4a51d09c5542d6dd354e5d0ea70813c910160405180910390a25050505050505b5050505092915050565b804710156105c95760405163cf47918160e01b815247600482015260248101829052604401610268565b6105e2828260405180602001604052805f8152506108c4565b156105eb575050565b3d156105fd576105f96108d9565b5050565b60405163d6bda27560e01b815260040160405180910390fd5b5f80808061076361062a60c0870187610dd7565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284375f9201919091525061075d92507f7f96328b83274ebc7c1cf4f7a3abda602b51a78b7fa1d86a2ce353d75e587cac9150610691905060208a018a610c00565b6106a160408b0160208c01610c00565b60408b013560608c01356106bb61009b60208f018f610c00565b8d60800160208101906106ce9190610db2565b8e8060a001906106de9190610dd7565b6040516106ec929190610e47565b6040805191829003822060208301999099526001600160a01b0397881690820152959094166060860152608085019290925260a084015260c083015265ffffffffffff1660e082015261010081019190915261012001604051602081830303815290604052805190602001206108e4565b90610910565b5090925090505f81600381111561077c5761077c610e56565b14959194509092505050565b6040513060248201525f90819060440160408051601f19818403018152919052602080820180516001600160e01b031663572b6c0560e01b17815282519293505f928392839290918391895afa92503d91505f5190508280156107ec575060208210155b80156107f757505f81115b9695505050505050565b606060ff831461081b5761081483610959565b90506108a6565b81805461082790610e6a565b80601f016020809104026020016040519081016040528092919081815260200182805461085390610e6a565b801561089e5780601f106108755761010080835404028352916020019161089e565b820191905f5260205f20905b81548152906001019060200180831161088157829003601f168201915b505050505090505b92915050565b6108bb603f6060830135610ea2565b8210156105f957fe5b5f5f5f83516020850186885af1949350505050565b6040513d5f823e3d81fd5b5f6108a66108f0610996565b8360405161190160f01b8152600281019290925260228201526042902090565b5f5f5f8351604103610947576020840151604085015160608601515f1a61093988828585610abf565b955095509550505050610952565b505081515f91506002905b9250925092565b60605f61096583610b87565b6040805160208082528183019092529192505f91906020820181803683375050509182525060208101929092525090565b5f306001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161480156109ee57507f000000000000000000000000000000000000000000000000000000000000000046145b15610a1857507f000000000000000000000000000000000000000000000000000000000000000090565b610392604080517f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f60208201527f0000000000000000000000000000000000000000000000000000000000000000918101919091527f000000000000000000000000000000000000000000000000000000000000000060608201524660808201523060a08201525f9060c00160405160208183030381529060405280519060200120905090565b5f80807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0841115610af857505f91506003905082610b7d565b604080515f808252602082018084528a905260ff891692820192909252606081018790526080810186905260019060a0016020604051602081039080840390855afa158015610b49573d5f5f3e3d5ffd5b5050604051601f1901519150506001600160a01b038116610b7457505f925060019150829050610b7d565b92505f91508190505b9450945094915050565b5f60ff8216601f8111156108a657604051632cd44ac360e21b815260040160405180910390fd5b5f60208284031215610bbe575f5ffd5b813567ffffffffffffffff811115610bd4575f5ffd5b820160e08185031215610be5575f5ffd5b9392505050565b6001600160a01b03811681146102e1575f5ffd5b5f60208284031215610c10575f5ffd5b8135610be581610bec565b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b60ff60f81b8816815260e060208201525f610c6760e0830189610c1b565b8281036040840152610c798189610c1b565b606084018890526001600160a01b038716608085015260a0840186905283810360c0850152845180825260208087019350909101905f5b81811015610cce578351835260209384019390920191600101610cb0565b50909b9a5050505050505050505050565b5f5f5f60408486031215610cf1575f5ffd5b833567ffffffffffffffff811115610d07575f5ffd5b8401601f81018613610d17575f5ffd5b803567ffffffffffffffff811115610d2d575f5ffd5b8660208260051b8401011115610d41575f5ffd5b602091820194509250840135610d5681610bec565b809150509250925092565b634e487b7160e01b5f52603260045260245ffd5b5f823560de19833603018112610d89575f5ffd5b9190910192915050565b808201808211156108a657634e487b7160e01b5f52601160045260245ffd5b5f60208284031215610dc2575f5ffd5b813565ffffffffffff81168114610be5575f5ffd5b5f5f8335601e19843603018112610dec575f5ffd5b83018035915067ffffffffffffffff821115610e06575f5ffd5b602001915036819003821315610e1a575f5ffd5b9250929050565b8284823760609190911b6bffffffffffffffffffffffff19169101908152601401919050565b818382375f9101908152919050565b634e487b7160e01b5f52602160045260245ffd5b600181811c90821680610e7e57607f821691505b602082108103610e9c57634e487b7160e01b5f52602260045260245ffd5b50919050565b5f82610ebc57634e487b7160e01b5f52601260045260245ffd5b50049056fea2646970667358221220b3162e46cf5009cda0fd7b979fa7c841a7820646cb210d0a717d56e0d19f713c64736f6c634300081b0033", - "deployedBytecode": "0x608060405260043610610049575f3560e01c806319d8d38c1461004d5780637ecebe001461008157806384b0196e146100c3578063ccf96b4a146100ea578063df905caf146100ff575b5f5ffd5b348015610058575f5ffd5b5061006c610067366004610bae565b610112565b60405190151581526020015b60405180910390f35b34801561008c575f5ffd5b506100b561009b366004610c00565b6001600160a01b03165f9081526002602052604090205490565b604051908152602001610078565b3480156100ce575f5ffd5b506100d7610142565b6040516100789796959493929190610c49565b6100fd6100f8366004610cdf565b610184565b005b6100fd61010d366004610bae565b610289565b5f5f5f5f61011f856102e4565b509250925092508280156101305750815b80156101395750805b95945050505050565b5f6060805f5f5f6060610153610366565b61015b610397565b604080515f80825260208201909252600f60f81b9b939a50919850469750309650945092509050565b6001600160a01b038116155f80805b85811015610242578686828181106101ad576101ad610d61565b90506020028101906101bf9190610d75565b6101cd906040013584610d93565b92505f6101fd8888848181106101e5576101e5610d61565b90506020028101906101f79190610d75565b866103c4565b9050806102395787878381811061021657610216610d61565b90506020028101906102289190610d75565b610236906040013584610d93565b92505b50600101610193565b50348214610271576040516370647f7960e01b8152600481018390523460248201526044015b60405180910390fd5b801561028157610281848261059f565b505050505050565b806040013534146102b957604080516370647f7960e01b8152908201356004820152346024820152604401610268565b6102c48160016103c4565b6102e15760405163d6bda27560e01b815260040160405180910390fd5b50565b5f5f5f5f5f5f6102f387610616565b909250905061031061030b6040890160208a01610c00565b610788565b4261032160a08a0160808b01610db2565b65ffffffffffff161015838015610355575061034060208a018a610c00565b6001600160a01b0316836001600160a01b0316145b919750955093509150509193509193565b60606103927f00000000000000000000000000000000000000000000000000000000000000005f610801565b905090565b60606103927f00000000000000000000000000000000000000000000000000000000000000006001610801565b5f5f5f5f5f6103d2876102e4565b935093509350935085156104985783610420576103f56040880160208901610c00565b60405163d2650cd160e01b81526001600160a01b039091166004820152306024820152604401610268565b826104595761043560a0880160808901610db2565b604051634a777ac560e11b815265ffffffffffff9091166004820152602401610268565b81610498578061046c6020890189610c00565b604051636422d02b60e11b81526001600160a01b03928316600482015291166024820152604401610268565b8380156104a25750815b80156104ab5750825b15610595576001600160a01b0381165f908152600260205260408120805460018101909155905060608801355f6104e860408b0160208c01610c00565b905060408a01355f6104fd60a08d018d610dd7565b61050a60208f018f610c00565b60405160200161051c93929190610e21565b60405160208183030381529060405290505f5f5f83516020850186888af19a505a9050610549818e6108ac565b604080518781528c151560208201526001600160a01b038916917f842fb24a83793558587a3dab2be7674da4a51d09c5542d6dd354e5d0ea70813c910160405180910390a25050505050505b5050505092915050565b804710156105c95760405163cf47918160e01b815247600482015260248101829052604401610268565b6105e2828260405180602001604052805f8152506108c4565b156105eb575050565b3d156105fd576105f96108d9565b5050565b60405163d6bda27560e01b815260040160405180910390fd5b5f80808061076361062a60c0870187610dd7565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284375f9201919091525061075d92507f7f96328b83274ebc7c1cf4f7a3abda602b51a78b7fa1d86a2ce353d75e587cac9150610691905060208a018a610c00565b6106a160408b0160208c01610c00565b60408b013560608c01356106bb61009b60208f018f610c00565b8d60800160208101906106ce9190610db2565b8e8060a001906106de9190610dd7565b6040516106ec929190610e47565b6040805191829003822060208301999099526001600160a01b0397881690820152959094166060860152608085019290925260a084015260c083015265ffffffffffff1660e082015261010081019190915261012001604051602081830303815290604052805190602001206108e4565b90610910565b5090925090505f81600381111561077c5761077c610e56565b14959194509092505050565b6040513060248201525f90819060440160408051601f19818403018152919052602080820180516001600160e01b031663572b6c0560e01b17815282519293505f928392839290918391895afa92503d91505f5190508280156107ec575060208210155b80156107f757505f81115b9695505050505050565b606060ff831461081b5761081483610959565b90506108a6565b81805461082790610e6a565b80601f016020809104026020016040519081016040528092919081815260200182805461085390610e6a565b801561089e5780601f106108755761010080835404028352916020019161089e565b820191905f5260205f20905b81548152906001019060200180831161088157829003601f168201915b505050505090505b92915050565b6108bb603f6060830135610ea2565b8210156105f957fe5b5f5f5f83516020850186885af1949350505050565b6040513d5f823e3d81fd5b5f6108a66108f0610996565b8360405161190160f01b8152600281019290925260228201526042902090565b5f5f5f8351604103610947576020840151604085015160608601515f1a61093988828585610abf565b955095509550505050610952565b505081515f91506002905b9250925092565b60605f61096583610b87565b6040805160208082528183019092529192505f91906020820181803683375050509182525060208101929092525090565b5f306001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161480156109ee57507f000000000000000000000000000000000000000000000000000000000000000046145b15610a1857507f000000000000000000000000000000000000000000000000000000000000000090565b610392604080517f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f60208201527f0000000000000000000000000000000000000000000000000000000000000000918101919091527f000000000000000000000000000000000000000000000000000000000000000060608201524660808201523060a08201525f9060c00160405160208183030381529060405280519060200120905090565b5f80807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0841115610af857505f91506003905082610b7d565b604080515f808252602082018084528a905260ff891692820192909252606081018790526080810186905260019060a0016020604051602081039080840390855afa158015610b49573d5f5f3e3d5ffd5b5050604051601f1901519150506001600160a01b038116610b7457505f925060019150829050610b7d565b92505f91508190505b9450945094915050565b5f60ff8216601f8111156108a657604051632cd44ac360e21b815260040160405180910390fd5b5f60208284031215610bbe575f5ffd5b813567ffffffffffffffff811115610bd4575f5ffd5b820160e08185031215610be5575f5ffd5b9392505050565b6001600160a01b03811681146102e1575f5ffd5b5f60208284031215610c10575f5ffd5b8135610be581610bec565b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b60ff60f81b8816815260e060208201525f610c6760e0830189610c1b565b8281036040840152610c798189610c1b565b606084018890526001600160a01b038716608085015260a0840186905283810360c0850152845180825260208087019350909101905f5b81811015610cce578351835260209384019390920191600101610cb0565b50909b9a5050505050505050505050565b5f5f5f60408486031215610cf1575f5ffd5b833567ffffffffffffffff811115610d07575f5ffd5b8401601f81018613610d17575f5ffd5b803567ffffffffffffffff811115610d2d575f5ffd5b8660208260051b8401011115610d41575f5ffd5b602091820194509250840135610d5681610bec565b809150509250925092565b634e487b7160e01b5f52603260045260245ffd5b5f823560de19833603018112610d89575f5ffd5b9190910192915050565b808201808211156108a657634e487b7160e01b5f52601160045260245ffd5b5f60208284031215610dc2575f5ffd5b813565ffffffffffff81168114610be5575f5ffd5b5f5f8335601e19843603018112610dec575f5ffd5b83018035915067ffffffffffffffff821115610e06575f5ffd5b602001915036819003821315610e1a575f5ffd5b9250929050565b8284823760609190911b6bffffffffffffffffffffffff19169101908152601401919050565b818382375f9101908152919050565b634e487b7160e01b5f52602160045260245ffd5b600181811c90821680610e7e57607f821691505b602082108103610e9c57634e487b7160e01b5f52602260045260245ffd5b50919050565b5f82610ebc57634e487b7160e01b5f52601260045260245ffd5b50049056fea2646970667358221220b3162e46cf5009cda0fd7b979fa7c841a7820646cb210d0a717d56e0d19f713c64736f6c634300081b0033", - "linkReferences": {}, - "deployedLinkReferences": {} -} diff --git a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/ERC7913RSAVerifier.json b/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/ERC7913RSAVerifier.json deleted file mode 100644 index d8bc20e..0000000 --- a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/ERC7913RSAVerifier.json +++ /dev/null @@ -1,40 +0,0 @@ -{ - "_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": "0x6080604052348015600e575f5ffd5b506106c08061001c5f395ff3fe608060405234801561000f575f5ffd5b5060043610610029575f3560e01c8063024ad3181461002d575b5f5ffd5b61004061003b366004610491565b61005d565b6040516001600160e01b0319909116815260200160405180910390f35b5f808061006c878901896105a9565b915091506100cd8660405160200161008691815260200190565b60408051601f198184030181526020601f8901819004810284018101909252878352919088908890819084018382808284375f920191909152508792508691506100f39050565b6100df576001600160e01b03196100e7565b62495a6360e31b5b98975050505050505050565b5f61014d6002866040516101079190610625565b602060405180830381855afa158015610122573d5f5f3e3d5ffd5b5050506040513d601f19601f820116820180604052508101906101459190610630565b858585610158565b90505b949350505050565b80515f9061010081108061016d575084518114155b1561017b575f915050610150565b5f5b818110156101f2575f610193826020850361033c565b90505f6101a38883016020015190565b90505f6101b38784016020015190565b9050808210156101c5575050506101f2565b808211806101d557506020850383145b156101e7575f95505050505050610150565b50505060200161017d565b505f6101ff86868661034e565b90505f5f5f6102148460328703016020015190565b6001600160f81b031916603160f81b036102595750720181898068304b0432400b281820100828002160651b91506bffffffffffffffffffffffff19905060346102b3565b600f1985850101516001600160f81b031916602f60f81b036102a65750700181798058304b0432400b28182010082160751b91506dffffffffffffffffffffffffffff19905060326102b3565b5f95505050505050610150565b80850360025b818110156102f057602081870101516001600160f81b0319908116146102e8575f975050505050505050610150565b6001016102b9565b5060208501516001600160f01b031916600160f01b14801561031f57508261031b8683016020015190565b1684145b801561032d5750858501518b145b9b9a5050505050505050505050565b5f8282188284100282185b9392505050565b60605f5f61035d868686610379565b91509150816103705761037060126103f0565b95945050505050565b5f606061038583610401565b156103a0575050604080515f808252602082019092526103e8565b8251855185516040516103bf92919084908a908a908a90602001610647565b604051602081830303815290604052915060208201818184518360055afa828452910160405291505b935093915050565b634e487b715f52806020526024601cfd5b5f805b82518110156104435782818151811061041f5761041f610676565b01602001516001600160f81b0319161561043b57505f92915050565b600101610404565b50600192915050565b5f5f83601f84011261045c575f5ffd5b50813567ffffffffffffffff811115610473575f5ffd5b60208301915083602082850101111561048a575f5ffd5b9250929050565b5f5f5f5f5f606086880312156104a5575f5ffd5b853567ffffffffffffffff8111156104bb575f5ffd5b6104c78882890161044c565b90965094505060208601359250604086013567ffffffffffffffff8111156104ed575f5ffd5b6104f98882890161044c565b969995985093965092949392505050565b634e487b7160e01b5f52604160045260245ffd5b5f82601f83011261052d575f5ffd5b813567ffffffffffffffff8111156105475761054761050a565b604051601f8201601f19908116603f0116810167ffffffffffffffff811182821017156105765761057661050a565b60405281815283820160200185101561058d575f5ffd5b816020850160208301375f918101602001919091529392505050565b5f5f604083850312156105ba575f5ffd5b823567ffffffffffffffff8111156105d0575f5ffd5b6105dc8582860161051e565b925050602083013567ffffffffffffffff8111156105f8575f5ffd5b6106048582860161051e565b9150509250929050565b5f81518060208401855e5f93019283525090919050565b5f610347828461060e565b5f60208284031215610640575f5ffd5b5051919050565b8681528560208201528460408201525f6100e761067061066a606085018861060e565b8661060e565b8461060e565b634e487b7160e01b5f52603260045260245ffdfea26469706673582212209b8c728fc5ef03f8bd438b66599c318b0ee2590913f08d5a956be66d3474664164736f6c634300081b0033", - "deployedBytecode": "0x608060405234801561000f575f5ffd5b5060043610610029575f3560e01c8063024ad3181461002d575b5f5ffd5b61004061003b366004610491565b61005d565b6040516001600160e01b0319909116815260200160405180910390f35b5f808061006c878901896105a9565b915091506100cd8660405160200161008691815260200190565b60408051601f198184030181526020601f8901819004810284018101909252878352919088908890819084018382808284375f920191909152508792508691506100f39050565b6100df576001600160e01b03196100e7565b62495a6360e31b5b98975050505050505050565b5f61014d6002866040516101079190610625565b602060405180830381855afa158015610122573d5f5f3e3d5ffd5b5050506040513d601f19601f820116820180604052508101906101459190610630565b858585610158565b90505b949350505050565b80515f9061010081108061016d575084518114155b1561017b575f915050610150565b5f5b818110156101f2575f610193826020850361033c565b90505f6101a38883016020015190565b90505f6101b38784016020015190565b9050808210156101c5575050506101f2565b808211806101d557506020850383145b156101e7575f95505050505050610150565b50505060200161017d565b505f6101ff86868661034e565b90505f5f5f6102148460328703016020015190565b6001600160f81b031916603160f81b036102595750720181898068304b0432400b281820100828002160651b91506bffffffffffffffffffffffff19905060346102b3565b600f1985850101516001600160f81b031916602f60f81b036102a65750700181798058304b0432400b28182010082160751b91506dffffffffffffffffffffffffffff19905060326102b3565b5f95505050505050610150565b80850360025b818110156102f057602081870101516001600160f81b0319908116146102e8575f975050505050505050610150565b6001016102b9565b5060208501516001600160f01b031916600160f01b14801561031f57508261031b8683016020015190565b1684145b801561032d5750858501518b145b9b9a5050505050505050505050565b5f8282188284100282185b9392505050565b60605f5f61035d868686610379565b91509150816103705761037060126103f0565b95945050505050565b5f606061038583610401565b156103a0575050604080515f808252602082019092526103e8565b8251855185516040516103bf92919084908a908a908a90602001610647565b604051602081830303815290604052915060208201818184518360055afa828452910160405291505b935093915050565b634e487b715f52806020526024601cfd5b5f805b82518110156104435782818151811061041f5761041f610676565b01602001516001600160f81b0319161561043b57505f92915050565b600101610404565b50600192915050565b5f5f83601f84011261045c575f5ffd5b50813567ffffffffffffffff811115610473575f5ffd5b60208301915083602082850101111561048a575f5ffd5b9250929050565b5f5f5f5f5f606086880312156104a5575f5ffd5b853567ffffffffffffffff8111156104bb575f5ffd5b6104c78882890161044c565b90965094505060208601359250604086013567ffffffffffffffff8111156104ed575f5ffd5b6104f98882890161044c565b969995985093965092949392505050565b634e487b7160e01b5f52604160045260245ffd5b5f82601f83011261052d575f5ffd5b813567ffffffffffffffff8111156105475761054761050a565b604051601f8201601f19908116603f0116810167ffffffffffffffff811182821017156105765761057661050a565b60405281815283820160200185101561058d575f5ffd5b816020850160208301375f918101602001919091529392505050565b5f5f604083850312156105ba575f5ffd5b823567ffffffffffffffff8111156105d0575f5ffd5b6105dc8582860161051e565b925050602083013567ffffffffffffffff8111156105f8575f5ffd5b6106048582860161051e565b9150509250929050565b5f81518060208401855e5f93019283525090919050565b5f610347828461060e565b5f60208284031215610640575f5ffd5b5051919050565b8681528560208201528460408201525f6100e761067061066a606085018861060e565b8661060e565b8461060e565b634e487b7160e01b5f52603260045260245ffdfea26469706673582212209b8c728fc5ef03f8bd438b66599c318b0ee2590913f08d5a956be66d3474664164736f6c634300081b0033", - "linkReferences": {}, - "deployedLinkReferences": {} -} diff --git a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/ERC7913WebAuthnVerifier.json b/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/ERC7913WebAuthnVerifier.json deleted file mode 100644 index 3fb6475..0000000 --- a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/ERC7913WebAuthnVerifier.json +++ /dev/null @@ -1,40 +0,0 @@ -{ - "_format": "hh-sol-artifact-1", - "contractName": "ERC7913WebAuthnVerifier", - "sourceName": "contracts/utils/cryptography/verifiers/ERC7913WebAuthnVerifier.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": "0x6080604052348015600e575f5ffd5b506114088061001c5f395ff3fe608060405234801561000f575f5ffd5b5060043610610029575f3560e01c8063024ad3181461002d575b5f5ffd5b61004061003b36600461106f565b61005d565b6040516001600160e01b0319909116815260200160405180910390f35b5f5f3661006a858561010b565b9150915081801561007b5750604087145b80156100e357506100e38660405160200161009891815260200190565b604051602081830303815290604052826100b1906111b6565b6100be60205f8c8e61124c565b6100c791611273565b6100d5604060208d8f61124c565b6100de91611273565b610208565b6100f5576001600160e01b03196100fd565b62495a6360e31b5b925050505b95945050505050565b5f8260c083101561011e575f9150610201565b5f61012c846080818861124c565b61013591611273565b90505f6101458560a0818961124c565b61014e91611273565b90508161015c6020876112a4565b108061017157508061016f6020876112a4565b105b15610180575f93505050610201565b5f61018d8684818a61124c565b61019691611273565b90505f6101a58784818b61124c565b6101ae91611273565b90508160206101bd868a6112a4565b6101c791906112a4565b10806101e757508060206101db858a6112a4565b6101e591906112a4565b105b156101f8575f955050505050610201565b60019550505050505b9250929050565b5f6101028585858560015f602485608001515111801561026e575061026e8560a0015186606001518181016020015191516014909101106affffffffffffffffffffff199190911674113a3cb832911d113bb2b130baba34371733b2ba1160591b141690565b801561028857506102888560a0015186604001518861040d565b80156102ba57506102ba85608001516020815181106102a9576102a96112b7565b0160200151600160f81b9081161490565b80156102f457508115806102f457506102f485608001516020815181106102e3576102e36112b7565b0160200151600160fa1b9081161490565b801561032957506103298560800151602081518110610315576103156112b7565b01602001516001600160f81b03191661045d565b801561040357506104036002866080015160028860a0015160405161034e91906112e2565b602060405180830381855afa158015610369573d5f5f3e3d5ffd5b5050506040513d601f19601f8201168201806040525081019061038c91906112ed565b60405160200161039d929190611304565b60408051601f19818403018152908290526103b7916112e2565b602060405180830381855afa1580156103d2573d5f5f3e3d5ffd5b5050506040513d601f19601f820116820180604052508101906103f591906112ed565b86516020880151878761047c565b9695505050505050565b5f5f610418836104b2565b604051602001610428919061131c565b60405160208183030381529060405290505f610451868684518861044c919061134e565b6104bf565b90506104038183610540565b5f600160fb1b82811614806104765750600160fc1b8216155b92915050565b5f5f5f61048c8888888888610552565b91509150806104a7576104a2888888888861062d565b6100fd565b509695505050505050565b60606104768260016106dd565b60606104cc82855161085c565b91506104d8838361085c565b92505f6104e584846112a4565b67ffffffffffffffff8111156104fd576104fd6110e8565b6040519080825280601f01601f191660200182016040528015610527576020820181803683370190505b509050838303846020870101602083015e949350505050565b5f61054b838361086b565b9392505050565b5f5f61055e868661088f565b1580610571575061056f84846108e6565b155b1561058157505f90506001610623565b61058e878787878761094a565b1561059e57506001905080610623565b61060d7fbb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023600560017fa71af64de5126a4a4e02b7922d66ce9415ce88a4c9d25514d91082c8725ac9577f5d47723c8fbe580bb369fec9c2665d8e30a435b9932645482e7c9f11e872296b61094a565b1561061d57505f90506001610623565b505f9050805b9550959350505050565b5f610638858561088f565b158061064b575061064983836108e6565b155b1561065757505f610102565b5f610662848461098a565b90505f61067c865f5160206113b35f395f51905f52610b7d565b90505f5f5160206113b35f395f51905f52828a0990505f5f5160206113b35f395f51905f52838a0990505f6106b2858484610b8c565b509050896106cd5f5160206113b35f395f51905f5283611375565b149b9a5050505050505050505050565b606082515f036106fb575060408051602081019091525f8152610476565b5f8261072b57600384516002610711919061134e565b61071b9190611388565b61072690600461139b565b610750565b60038451600461073b919061139b565b61074690600261134e565b6107509190611388565b905060405191507f4142434445464748494a4b4c4d4e4f505152535455565758595a616263646566601f5261067083027f6768696a6b6c6d6e6f707172737475767778797a303132333435363738392b2f18603f526020820181810185865187016020810180515f82525b8284101561080e576003840193508351603f8160121c16518753600187019650603f81600c1c16518753600187019650603f8160061c16518753600187019650603f8116518753506001860195506107bb565b90525085905061084f5760038651066001811461083257600281146108455761084d565b603d6001840353603d600284035361084d565b603d60018403535b505b9183525060405292915050565b5f82821882841002821861054b565b5f8151835114801561054b5750508051602091820120825192909101919091201490565b5f82158015906108ab57505f5160206113b35f395f51905f5283105b80156108b657508115155b801561054b5750507f7fffffff800000007fffffffffffffffde737d56d38bcf4279dce5617e3192a81015919050565b5f600160601b63ffffffff60c01b031980838409817f5ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2604b8387856003600160601b0363ffffffff60c01b0319878b8c0908090894821191909310169190921416919050565b5f6040518681528560208201528460408201528360608201528260808201525f5f5260205f60a0836101005afa61097d57fe5b50505f5195945050505050565b610992610fea565b60405180606001604052805f81526020015f81526020015f815250815f601081106109bf576109bf6112b7565b602002018190525060405180606001604052808481526020018381526020016001815250816001601081106109f6576109f66112b7565b602002018190525060405180606001604052807f6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c29681526020017f4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f58152602001600181525081600460108110610a6d57610a6d6112b7565b6020020152610a838160015b6020020151610cb0565b6040820152610a93816004610a79565b6101008201526020810151610ab0908260025b6020020151610d0c565b6060820152610ac98160015b6020020151826004610aa6565b60a0820152610ad9816002610abc565b60c0820152610ae9816003610abc565b60e0820152610b028160015b6020020151826008610aa6565b610120820152610b13816002610af5565b610140820152610b24816003610af5565b610160820152610b35816004610af5565b610180820152610b4f8160015b602002015182600c610aa6565b6101a0820152610b60816002610b42565b6101c0820152610b71816003610b42565b6101e082015292915050565b5f61054b836002840384610d6a565b5f80808080805b6080811015610c94578115610bc757610bad848484610d8b565b91955093509150610bbf848484610d8b565b919550935091505b600c60fc89901c1660fe88901c17898160108110610be757610be76112b7565b60200201516040015115610c8057825f03610c5657898160108110610c0e57610c0e6112b7565b6020020151518a8260108110610c2657610c266112b7565b6020020151602001518b8360108110610c4157610c416112b7565b60200201516040015191965094509250610c80565b610c788a8260108110610c6b57610c6b6112b7565b6020020151868686610e0e565b919650945092505b50600297881b979690961b95600101610b93565b50610ca0838383610f3a565b945094505050505b935093915050565b610cd160405180606001604052805f81526020015f81526020015f81525090565b5f5f5f610cea855f015186602001518760400151610d8b565b6040805160608101825293845260208401929092529082015295945050505050565b610d2d60405180606001604052805f81526020015f81526020015f81525090565b5f5f5f610d4786865f015187602001518860400151610e0e565b604080516060810182529384526020840192909252908201529695505050505050565b5f5f5f610d78868686610f87565b9150915081610102576101026012610fd9565b5f5f5f600160601b63ffffffff60c01b031980868709818687098283848384096003600160601b0363ffffffff60c01b03190984858c8d096003090890508283838b09600409838482600209850385848509089650838485858609600809850385868a880385088509089550505050808186880960020991505093509350939050565b5f5f5f600160601b63ffffffff60c01b0319604088015181818209828388858a8b090960208c0151098381850385868686098c090884858a8b098d51098581870387868f0908935081158415168015610e6e5760018114610eb457610f29565b868586098788898386096002098903898a848a098b038b88890908089a5087888983890987098903898a8e8c038c8689090887090899505086878c880986099750610f29565b8c8c8c898283098a8283098b8c8d8384096003600160601b0363ffffffff60c01b0319098d8e8889096003090890508b8c83870960040994508b8c866002098d038d838409089e508b8c8384096008098c0391508b8f8d03860894508b828d878409089d505050898a8284096002099a505050505b505050505050509450945094915050565b5f5f825f03610f4d57505f905080610ca8565b600160601b63ffffffff60c01b03195f610f678583610b7d565b905081818209828189099450828383830988099350505050935093915050565b5f5f825f03610f9a57505f905080610ca8565b60405160208152602080820152602060408201528560608201528460808201528360a082015260205f60c08360055afa9250505f519050935093915050565b634e487b715f52806020526024601cfd5b6040518061020001604052806010905b61101b60405180606001604052805f81526020015f81526020015f81525090565b815260200190600190039081610ffa5790505090565b5f5f83601f840112611041575f5ffd5b50813567ffffffffffffffff811115611058575f5ffd5b602083019150836020828501011115610201575f5ffd5b5f5f5f5f5f60608688031215611083575f5ffd5b853567ffffffffffffffff811115611099575f5ffd5b6110a588828901611031565b90965094505060208601359250604086013567ffffffffffffffff8111156110cb575f5ffd5b6110d788828901611031565b969995985093965092949392505050565b634e487b7160e01b5f52604160045260245ffd5b60405160c0810167ffffffffffffffff8111828210171561111f5761111f6110e8565b60405290565b5f82601f830112611134575f5ffd5b8135602083015f5f67ffffffffffffffff841115611154576111546110e8565b50604051601f19601f85018116603f0116810181811067ffffffffffffffff82111715611183576111836110e8565b60405283815290508082840187101561119a575f5ffd5b838360208301375f602085830101528094505050505092915050565b5f60c082360312156111c6575f5ffd5b6111ce6110fc565b82358152602080840135908201526040808401359082015260608084013590820152608083013567ffffffffffffffff811115611209575f5ffd5b61121536828601611125565b60808301525060a083013567ffffffffffffffff811115611234575f5ffd5b61124036828601611125565b60a08301525092915050565b5f5f8585111561125a575f5ffd5b83861115611266575f5ffd5b5050820193919092039150565b80356020831015610476575f19602084900360031b1b1692915050565b634e487b7160e01b5f52601160045260245ffd5b8181038181111561047657610476611290565b634e487b7160e01b5f52603260045260245ffd5b5f81518060208401855e5f93019283525090919050565b5f61054b82846112cb565b5f602082840312156112fd575f5ffd5b5051919050565b5f61130f82856112cb565b9283525050602001919050565b6c1131b430b63632b733b2911d1160991b81525f61133d600d8301846112cb565b601160f91b81526001019392505050565b8082018082111561047657610476611290565b634e487b7160e01b5f52601260045260245ffd5b5f8261138357611383611361565b500690565b5f8261139657611396611361565b500490565b80820281158282048414176104765761047661129056feffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551a2646970667358221220b33516316052982abc6f4187cfd0b1fe6f5ee6419c820a465dad2b752db337fa64736f6c634300081b0033", - "deployedBytecode": "0x608060405234801561000f575f5ffd5b5060043610610029575f3560e01c8063024ad3181461002d575b5f5ffd5b61004061003b36600461106f565b61005d565b6040516001600160e01b0319909116815260200160405180910390f35b5f5f3661006a858561010b565b9150915081801561007b5750604087145b80156100e357506100e38660405160200161009891815260200190565b604051602081830303815290604052826100b1906111b6565b6100be60205f8c8e61124c565b6100c791611273565b6100d5604060208d8f61124c565b6100de91611273565b610208565b6100f5576001600160e01b03196100fd565b62495a6360e31b5b925050505b95945050505050565b5f8260c083101561011e575f9150610201565b5f61012c846080818861124c565b61013591611273565b90505f6101458560a0818961124c565b61014e91611273565b90508161015c6020876112a4565b108061017157508061016f6020876112a4565b105b15610180575f93505050610201565b5f61018d8684818a61124c565b61019691611273565b90505f6101a58784818b61124c565b6101ae91611273565b90508160206101bd868a6112a4565b6101c791906112a4565b10806101e757508060206101db858a6112a4565b6101e591906112a4565b105b156101f8575f955050505050610201565b60019550505050505b9250929050565b5f6101028585858560015f602485608001515111801561026e575061026e8560a0015186606001518181016020015191516014909101106affffffffffffffffffffff199190911674113a3cb832911d113bb2b130baba34371733b2ba1160591b141690565b801561028857506102888560a0015186604001518861040d565b80156102ba57506102ba85608001516020815181106102a9576102a96112b7565b0160200151600160f81b9081161490565b80156102f457508115806102f457506102f485608001516020815181106102e3576102e36112b7565b0160200151600160fa1b9081161490565b801561032957506103298560800151602081518110610315576103156112b7565b01602001516001600160f81b03191661045d565b801561040357506104036002866080015160028860a0015160405161034e91906112e2565b602060405180830381855afa158015610369573d5f5f3e3d5ffd5b5050506040513d601f19601f8201168201806040525081019061038c91906112ed565b60405160200161039d929190611304565b60408051601f19818403018152908290526103b7916112e2565b602060405180830381855afa1580156103d2573d5f5f3e3d5ffd5b5050506040513d601f19601f820116820180604052508101906103f591906112ed565b86516020880151878761047c565b9695505050505050565b5f5f610418836104b2565b604051602001610428919061131c565b60405160208183030381529060405290505f610451868684518861044c919061134e565b6104bf565b90506104038183610540565b5f600160fb1b82811614806104765750600160fc1b8216155b92915050565b5f5f5f61048c8888888888610552565b91509150806104a7576104a2888888888861062d565b6100fd565b509695505050505050565b60606104768260016106dd565b60606104cc82855161085c565b91506104d8838361085c565b92505f6104e584846112a4565b67ffffffffffffffff8111156104fd576104fd6110e8565b6040519080825280601f01601f191660200182016040528015610527576020820181803683370190505b509050838303846020870101602083015e949350505050565b5f61054b838361086b565b9392505050565b5f5f61055e868661088f565b1580610571575061056f84846108e6565b155b1561058157505f90506001610623565b61058e878787878761094a565b1561059e57506001905080610623565b61060d7fbb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023600560017fa71af64de5126a4a4e02b7922d66ce9415ce88a4c9d25514d91082c8725ac9577f5d47723c8fbe580bb369fec9c2665d8e30a435b9932645482e7c9f11e872296b61094a565b1561061d57505f90506001610623565b505f9050805b9550959350505050565b5f610638858561088f565b158061064b575061064983836108e6565b155b1561065757505f610102565b5f610662848461098a565b90505f61067c865f5160206113b35f395f51905f52610b7d565b90505f5f5160206113b35f395f51905f52828a0990505f5f5160206113b35f395f51905f52838a0990505f6106b2858484610b8c565b509050896106cd5f5160206113b35f395f51905f5283611375565b149b9a5050505050505050505050565b606082515f036106fb575060408051602081019091525f8152610476565b5f8261072b57600384516002610711919061134e565b61071b9190611388565b61072690600461139b565b610750565b60038451600461073b919061139b565b61074690600261134e565b6107509190611388565b905060405191507f4142434445464748494a4b4c4d4e4f505152535455565758595a616263646566601f5261067083027f6768696a6b6c6d6e6f707172737475767778797a303132333435363738392b2f18603f526020820181810185865187016020810180515f82525b8284101561080e576003840193508351603f8160121c16518753600187019650603f81600c1c16518753600187019650603f8160061c16518753600187019650603f8116518753506001860195506107bb565b90525085905061084f5760038651066001811461083257600281146108455761084d565b603d6001840353603d600284035361084d565b603d60018403535b505b9183525060405292915050565b5f82821882841002821861054b565b5f8151835114801561054b5750508051602091820120825192909101919091201490565b5f82158015906108ab57505f5160206113b35f395f51905f5283105b80156108b657508115155b801561054b5750507f7fffffff800000007fffffffffffffffde737d56d38bcf4279dce5617e3192a81015919050565b5f600160601b63ffffffff60c01b031980838409817f5ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2604b8387856003600160601b0363ffffffff60c01b0319878b8c0908090894821191909310169190921416919050565b5f6040518681528560208201528460408201528360608201528260808201525f5f5260205f60a0836101005afa61097d57fe5b50505f5195945050505050565b610992610fea565b60405180606001604052805f81526020015f81526020015f815250815f601081106109bf576109bf6112b7565b602002018190525060405180606001604052808481526020018381526020016001815250816001601081106109f6576109f66112b7565b602002018190525060405180606001604052807f6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c29681526020017f4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f58152602001600181525081600460108110610a6d57610a6d6112b7565b6020020152610a838160015b6020020151610cb0565b6040820152610a93816004610a79565b6101008201526020810151610ab0908260025b6020020151610d0c565b6060820152610ac98160015b6020020151826004610aa6565b60a0820152610ad9816002610abc565b60c0820152610ae9816003610abc565b60e0820152610b028160015b6020020151826008610aa6565b610120820152610b13816002610af5565b610140820152610b24816003610af5565b610160820152610b35816004610af5565b610180820152610b4f8160015b602002015182600c610aa6565b6101a0820152610b60816002610b42565b6101c0820152610b71816003610b42565b6101e082015292915050565b5f61054b836002840384610d6a565b5f80808080805b6080811015610c94578115610bc757610bad848484610d8b565b91955093509150610bbf848484610d8b565b919550935091505b600c60fc89901c1660fe88901c17898160108110610be757610be76112b7565b60200201516040015115610c8057825f03610c5657898160108110610c0e57610c0e6112b7565b6020020151518a8260108110610c2657610c266112b7565b6020020151602001518b8360108110610c4157610c416112b7565b60200201516040015191965094509250610c80565b610c788a8260108110610c6b57610c6b6112b7565b6020020151868686610e0e565b919650945092505b50600297881b979690961b95600101610b93565b50610ca0838383610f3a565b945094505050505b935093915050565b610cd160405180606001604052805f81526020015f81526020015f81525090565b5f5f5f610cea855f015186602001518760400151610d8b565b6040805160608101825293845260208401929092529082015295945050505050565b610d2d60405180606001604052805f81526020015f81526020015f81525090565b5f5f5f610d4786865f015187602001518860400151610e0e565b604080516060810182529384526020840192909252908201529695505050505050565b5f5f5f610d78868686610f87565b9150915081610102576101026012610fd9565b5f5f5f600160601b63ffffffff60c01b031980868709818687098283848384096003600160601b0363ffffffff60c01b03190984858c8d096003090890508283838b09600409838482600209850385848509089650838485858609600809850385868a880385088509089550505050808186880960020991505093509350939050565b5f5f5f600160601b63ffffffff60c01b0319604088015181818209828388858a8b090960208c0151098381850385868686098c090884858a8b098d51098581870387868f0908935081158415168015610e6e5760018114610eb457610f29565b868586098788898386096002098903898a848a098b038b88890908089a5087888983890987098903898a8e8c038c8689090887090899505086878c880986099750610f29565b8c8c8c898283098a8283098b8c8d8384096003600160601b0363ffffffff60c01b0319098d8e8889096003090890508b8c83870960040994508b8c866002098d038d838409089e508b8c8384096008098c0391508b8f8d03860894508b828d878409089d505050898a8284096002099a505050505b505050505050509450945094915050565b5f5f825f03610f4d57505f905080610ca8565b600160601b63ffffffff60c01b03195f610f678583610b7d565b905081818209828189099450828383830988099350505050935093915050565b5f5f825f03610f9a57505f905080610ca8565b60405160208152602080820152602060408201528560608201528460808201528360a082015260205f60c08360055afa9250505f519050935093915050565b634e487b715f52806020526024601cfd5b6040518061020001604052806010905b61101b60405180606001604052805f81526020015f81526020015f81525090565b815260200190600190039081610ffa5790505090565b5f5f83601f840112611041575f5ffd5b50813567ffffffffffffffff811115611058575f5ffd5b602083019150836020828501011115610201575f5ffd5b5f5f5f5f5f60608688031215611083575f5ffd5b853567ffffffffffffffff811115611099575f5ffd5b6110a588828901611031565b90965094505060208601359250604086013567ffffffffffffffff8111156110cb575f5ffd5b6110d788828901611031565b969995985093965092949392505050565b634e487b7160e01b5f52604160045260245ffd5b60405160c0810167ffffffffffffffff8111828210171561111f5761111f6110e8565b60405290565b5f82601f830112611134575f5ffd5b8135602083015f5f67ffffffffffffffff841115611154576111546110e8565b50604051601f19601f85018116603f0116810181811067ffffffffffffffff82111715611183576111836110e8565b60405283815290508082840187101561119a575f5ffd5b838360208301375f602085830101528094505050505092915050565b5f60c082360312156111c6575f5ffd5b6111ce6110fc565b82358152602080840135908201526040808401359082015260608084013590820152608083013567ffffffffffffffff811115611209575f5ffd5b61121536828601611125565b60808301525060a083013567ffffffffffffffff811115611234575f5ffd5b61124036828601611125565b60a08301525092915050565b5f5f8585111561125a575f5ffd5b83861115611266575f5ffd5b5050820193919092039150565b80356020831015610476575f19602084900360031b1b1692915050565b634e487b7160e01b5f52601160045260245ffd5b8181038181111561047657610476611290565b634e487b7160e01b5f52603260045260245ffd5b5f81518060208401855e5f93019283525090919050565b5f61054b82846112cb565b5f602082840312156112fd575f5ffd5b5051919050565b5f61130f82856112cb565b9283525050602001919050565b6c1131b430b63632b733b2911d1160991b81525f61133d600d8301846112cb565b601160f91b81526001019392505050565b8082018082111561047657610476611290565b634e487b7160e01b5f52601260045260245ffd5b5f8261138357611383611361565b500690565b5f8261139657611396611361565b500490565b80820281158282048414176104765761047661129056feffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551a2646970667358221220b33516316052982abc6f4187cfd0b1fe6f5ee6419c820a465dad2b752db337fa64736f6c634300081b0033", - "linkReferences": {}, - "deployedLinkReferences": {} -} diff --git a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/TransparentUpgradeableProxy.json b/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/TransparentUpgradeableProxy.json deleted file mode 100644 index c99b2c7..0000000 --- a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/TransparentUpgradeableProxy.json +++ /dev/null @@ -1,116 +0,0 @@ -{ - "_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": "0x60a0604052604051610d58380380610d5883398101604081905261002291610347565b828161002e828261008c565b50508160405161003d9061030b565b6001600160a01b039091168152602001604051809103905ff080158015610066573d5f5f3e3d5ffd5b506001600160a01b031660805261008461007f60805190565b6100ea565b505050610418565b61009582610157565b6040516001600160a01b038316907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b905f90a28051156100de576100d982826101d5565b505050565b6100e6610276565b5050565b7f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f6101295f516020610d385f395f51905f52546001600160a01b031690565b604080516001600160a01b03928316815291841660208301520160405180910390a161015481610297565b50565b806001600160a01b03163b5f0361019157604051634c9c8ce360e01b81526001600160a01b03821660048201526024015b60405180910390fd5b807f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5b80546001600160a01b0319166001600160a01b039290921691909117905550565b60605f6101e284846102d4565b905080801561020357505f3d118061020357505f846001600160a01b03163b115b15610218576102106102e7565b915050610270565b801561024257604051639996b31560e01b81526001600160a01b0385166004820152602401610188565b3d1561025557610250610300565b61026e565b60405163d6bda27560e01b815260040160405180910390fd5b505b92915050565b34156102955760405163b398979f60e01b815260040160405180910390fd5b565b6001600160a01b0381166102c057604051633173bdd160e11b81525f6004820152602401610188565b805f516020610d385f395f51905f526101b4565b5f5f5f835160208501865af49392505050565b6040513d81523d5f602083013e3d602001810160405290565b6040513d5f823e3d81fd5b6104e68061085283390190565b80516001600160a01b038116811461032e575f5ffd5b919050565b634e487b7160e01b5f52604160045260245ffd5b5f5f5f60608486031215610359575f5ffd5b61036284610318565b925061037060208501610318565b60408501519092506001600160401b0381111561038b575f5ffd5b8401601f8101861361039b575f5ffd5b80516001600160401b038111156103b4576103b4610333565b604051601f8201601f19908116603f011681016001600160401b03811182821017156103e2576103e2610333565b6040528181528282016020018810156103f9575f5ffd5b8160208401602083015e5f602083830101528093505050509250925092565b60805161042361042f5f395f601001526104235ff3fe608060405261000c61000e565b005b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316330361007a575f356001600160e01b03191663278f794360e11b14610070576040516334ad5dbb60e21b815260040160405180910390fd5b610078610082565b565b6100786100b0565b5f8061009136600481846102e1565b81019061009e919061031c565b915091506100ac82826100c0565b5050565b6100786100bb61011a565b610151565b6100c98261016f565b6040516001600160a01b038316907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b905f90a28051156101125761010d82826101ea565b505050565b6100ac61028b565b5f61014c7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc546001600160a01b031690565b905090565b365f5f375f5f365f845af43d5f5f3e80801561016b573d5ff35b3d5ffd5b806001600160a01b03163b5f036101a957604051634c9c8ce360e01b81526001600160a01b03821660048201526024015b60405180910390fd5b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc80546001600160a01b0319166001600160a01b0392909216919091179055565b60605f6101f784846102aa565b905080801561021857505f3d118061021857505f846001600160a01b03163b115b1561022d576102256102bd565b915050610285565b801561025757604051639996b31560e01b81526001600160a01b03851660048201526024016101a0565b3d1561026a576102656102d6565b610283565b60405163d6bda27560e01b815260040160405180910390fd5b505b92915050565b34156100785760405163b398979f60e01b815260040160405180910390fd5b5f5f5f835160208501865af49392505050565b6040513d81523d5f602083013e3d602001810160405290565b6040513d5f823e3d81fd5b5f5f858511156102ef575f5ffd5b838611156102fb575f5ffd5b5050820193919092039150565b634e487b7160e01b5f52604160045260245ffd5b5f5f6040838503121561032d575f5ffd5b82356001600160a01b0381168114610343575f5ffd5b9150602083013567ffffffffffffffff81111561035e575f5ffd5b8301601f8101851361036e575f5ffd5b803567ffffffffffffffff81111561038857610388610308565b604051601f8201601f19908116603f0116810167ffffffffffffffff811182821017156103b7576103b7610308565b6040528181528282016020018710156103ce575f5ffd5b816020840160208301375f60208383010152809350505050925092905056fea264697066735822122071033efde0725f3deac6ed328bb745e0faab923dcaa856dd35110b0b720cc81864736f6c634300081b00336080604052348015600e575f5ffd5b506040516104e63803806104e6833981016040819052602b9160b4565b806001600160a01b038116605857604051631e4fbdf760e01b81525f600482015260240160405180910390fd5b605f816065565b505060df565b5f80546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b5f6020828403121560c3575f5ffd5b81516001600160a01b038116811460d8575f5ffd5b9392505050565b6103fa806100ec5f395ff3fe608060405260043610610049575f3560e01c8063715018a61461004d5780638da5cb5b146100635780639623609d1461008e578063ad3cb1cc146100a1578063f2fde38b146100de575b5f5ffd5b348015610058575f5ffd5b506100616100fd565b005b34801561006e575f5ffd5b505f546040516001600160a01b0390911681526020015b60405180910390f35b61006161009c366004610260565b610110565b3480156100ac575f5ffd5b506100d1604051806040016040528060058152602001640352e302e360dc1b81525081565b6040516100859190610365565b3480156100e9575f5ffd5b506100616100f836600461037e565b61017b565b6101056101bd565b61010e5f6101e9565b565b6101186101bd565b60405163278f794360e11b81526001600160a01b03841690634f1ef2869034906101489086908690600401610399565b5f604051808303818588803b15801561015f575f5ffd5b505af1158015610171573d5f5f3e3d5ffd5b5050505050505050565b6101836101bd565b6001600160a01b0381166101b157604051631e4fbdf760e01b81525f60048201526024015b60405180910390fd5b6101ba816101e9565b50565b5f546001600160a01b0316331461010e5760405163118cdaa760e01b81523360048201526024016101a8565b5f80546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6001600160a01b03811681146101ba575f5ffd5b634e487b7160e01b5f52604160045260245ffd5b5f5f5f60608486031215610272575f5ffd5b833561027d81610238565b9250602084013561028d81610238565b9150604084013567ffffffffffffffff8111156102a8575f5ffd5b8401601f810186136102b8575f5ffd5b803567ffffffffffffffff8111156102d2576102d261024c565b604051601f8201601f19908116603f0116810167ffffffffffffffff811182821017156103015761030161024c565b604052818152828201602001881015610318575f5ffd5b816020840160208301375f602083830101528093505050509250925092565b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b602081525f6103776020830184610337565b9392505050565b5f6020828403121561038e575f5ffd5b813561037781610238565b6001600160a01b03831681526040602082018190525f906103bc90830184610337565b94935050505056fea264697066735822122006969be45262ce7a7d55a8ed09d4fc3284f19ccf33907228dd20e0d30f8ba79f64736f6c634300081b0033b53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103", - "deployedBytecode": "0x608060405261000c61000e565b005b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316330361007a575f356001600160e01b03191663278f794360e11b14610070576040516334ad5dbb60e21b815260040160405180910390fd5b610078610082565b565b6100786100b0565b5f8061009136600481846102e1565b81019061009e919061031c565b915091506100ac82826100c0565b5050565b6100786100bb61011a565b610151565b6100c98261016f565b6040516001600160a01b038316907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b905f90a28051156101125761010d82826101ea565b505050565b6100ac61028b565b5f61014c7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc546001600160a01b031690565b905090565b365f5f375f5f365f845af43d5f5f3e80801561016b573d5ff35b3d5ffd5b806001600160a01b03163b5f036101a957604051634c9c8ce360e01b81526001600160a01b03821660048201526024015b60405180910390fd5b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc80546001600160a01b0319166001600160a01b0392909216919091179055565b60605f6101f784846102aa565b905080801561021857505f3d118061021857505f846001600160a01b03163b115b1561022d576102256102bd565b915050610285565b801561025757604051639996b31560e01b81526001600160a01b03851660048201526024016101a0565b3d1561026a576102656102d6565b610283565b60405163d6bda27560e01b815260040160405180910390fd5b505b92915050565b34156100785760405163b398979f60e01b815260040160405180910390fd5b5f5f5f835160208501865af49392505050565b6040513d81523d5f602083013e3d602001810160405290565b6040513d5f823e3d81fd5b5f5f858511156102ef575f5ffd5b838611156102fb575f5ffd5b5050820193919092039150565b634e487b7160e01b5f52604160045260245ffd5b5f5f6040838503121561032d575f5ffd5b82356001600160a01b0381168114610343575f5ffd5b9150602083013567ffffffffffffffff81111561035e575f5ffd5b8301601f8101851361036e575f5ffd5b803567ffffffffffffffff81111561038857610388610308565b604051601f8201601f19908116603f0116810167ffffffffffffffff811182821017156103b7576103b7610308565b6040528181528282016020018710156103ce575f5ffd5b816020840160208301375f60208383010152809350505050925092905056fea264697066735822122071033efde0725f3deac6ed328bb745e0faab923dcaa856dd35110b0b720cc81864736f6c634300081b0033", - "linkReferences": {}, - "deployedLinkReferences": {} -} diff --git a/dependencies/@openzeppelin-contracts-5.5.0/utils/cryptography/MessageHashUtils.sol b/dependencies/@openzeppelin-contracts-5.5.0/utils/cryptography/MessageHashUtils.sol deleted file mode 100644 index cef8af2..0000000 --- a/dependencies/@openzeppelin-contracts-5.5.0/utils/cryptography/MessageHashUtils.sol +++ /dev/null @@ -1,99 +0,0 @@ -// SPDX-License-Identifier: MIT -// OpenZeppelin Contracts (last updated v5.5.0) (utils/cryptography/MessageHashUtils.sol) - -pragma solidity ^0.8.24; - -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.5.0/utils/structs/DoubleEndedQueue.sol b/dependencies/@openzeppelin-contracts-5.5.0/utils/structs/DoubleEndedQueue.sol deleted file mode 100644 index f243243..0000000 --- a/dependencies/@openzeppelin-contracts-5.5.0/utils/structs/DoubleEndedQueue.sol +++ /dev/null @@ -1,156 +0,0 @@ -// 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.5.0/README.md b/dependencies/@openzeppelin-contracts-5.7.0/README.md similarity index 85% rename from dependencies/@openzeppelin-contracts-5.5.0/README.md rename to dependencies/@openzeppelin-contracts-5.7.0/README.md index 4d64709..6a01f56 100644 --- a/dependencies/@openzeppelin-contracts-5.5.0/README.md +++ b/dependencies/@openzeppelin-contracts-5.7.0/README.md @@ -20,6 +20,16 @@ ## Overview +### Release tags + +We use NPM tags to clearly distinguish between audited and non-audited versions of our package: + +| Tag | Purpose | Description | +| :--------- | :----------------------- | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| **latest** | ✅ Audited releases | Stable, audited versions of the package. This is the **default** version installed when users run `npm install @openzeppelin/contracts`. | +| **dev** | 🧪 Final but not audited | Versions that are finalized and feature-complete but have **not yet been audited**. This version is fully tested, can be used in production and is covered by the bug bounty. | +| **next** | 🚧 Release candidates | Pre-release versions that are **not final**. Used for testing and validation before the version becomes a final `dev` or `latest` release. | + ### Installation #### Hardhat (npm) @@ -27,6 +37,12 @@ ``` $ npm install @openzeppelin/contracts ``` +→ Installs the latest audited release (`latest`). + +``` +$ npm install @openzeppelin/contracts@dev +``` +→ Installs the latest unaudited release (`dev`). #### Foundry (git) diff --git a/dependencies/@openzeppelin-contracts-5.5.0/access/AccessControl.sol b/dependencies/@openzeppelin-contracts-5.7.0/access/AccessControl.sol similarity index 96% rename from dependencies/@openzeppelin-contracts-5.5.0/access/AccessControl.sol rename to dependencies/@openzeppelin-contracts-5.7.0/access/AccessControl.sol index 0c7ec60..f20fc01 100644 --- a/dependencies/@openzeppelin-contracts-5.5.0/access/AccessControl.sol +++ b/dependencies/@openzeppelin-contracts-5.7.0/access/AccessControl.sol @@ -1,11 +1,11 @@ // SPDX-License-Identifier: MIT -// OpenZeppelin Contracts (last updated v5.4.0) (access/AccessControl.sol) +// OpenZeppelin Contracts (last updated v5.7.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"; +import {ERC165} from "../utils/introspection/ERC165.sol"; /** * @dev Contract module that allows children to implement role-based access @@ -65,7 +65,7 @@ abstract contract AccessControl is Context, IAccessControl, ERC165 { _; } - /// @inheritdoc IERC165 + /// @inheritdoc ERC165 function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { return interfaceId == type(IAccessControl).interfaceId || super.supportsInterface(interfaceId); } @@ -143,8 +143,7 @@ abstract contract AccessControl is Context, IAccessControl, ERC165 { * 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. + * Emits a {RoleRevoked} event if the calling account had `role` and this call successfully revoked it. * * Requirements: * diff --git a/dependencies/@openzeppelin-contracts-5.5.0/access/IAccessControl.sol b/dependencies/@openzeppelin-contracts-5.7.0/access/IAccessControl.sol similarity index 100% rename from dependencies/@openzeppelin-contracts-5.5.0/access/IAccessControl.sol rename to dependencies/@openzeppelin-contracts-5.7.0/access/IAccessControl.sol diff --git a/dependencies/@openzeppelin-contracts-5.5.0/access/Ownable.sol b/dependencies/@openzeppelin-contracts-5.7.0/access/Ownable.sol similarity index 100% rename from dependencies/@openzeppelin-contracts-5.5.0/access/Ownable.sol rename to dependencies/@openzeppelin-contracts-5.7.0/access/Ownable.sol diff --git a/dependencies/@openzeppelin-contracts-5.5.0/access/Ownable2Step.sol b/dependencies/@openzeppelin-contracts-5.7.0/access/Ownable2Step.sol similarity index 100% rename from dependencies/@openzeppelin-contracts-5.5.0/access/Ownable2Step.sol rename to dependencies/@openzeppelin-contracts-5.7.0/access/Ownable2Step.sol diff --git a/dependencies/@openzeppelin-contracts-5.5.0/access/extensions/AccessControlDefaultAdminRules.sol b/dependencies/@openzeppelin-contracts-5.7.0/access/extensions/AccessControlDefaultAdminRules.sol similarity index 98% rename from dependencies/@openzeppelin-contracts-5.5.0/access/extensions/AccessControlDefaultAdminRules.sol rename to dependencies/@openzeppelin-contracts-5.7.0/access/extensions/AccessControlDefaultAdminRules.sol index 0be96d9..8d2c723 100644 --- a/dependencies/@openzeppelin-contracts-5.5.0/access/extensions/AccessControlDefaultAdminRules.sol +++ b/dependencies/@openzeppelin-contracts-5.7.0/access/extensions/AccessControlDefaultAdminRules.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -// OpenZeppelin Contracts (last updated v5.5.0) (access/extensions/AccessControlDefaultAdminRules.sol) +// OpenZeppelin Contracts (last updated v5.6.0) (access/extensions/AccessControlDefaultAdminRules.sol) pragma solidity ^0.8.20; @@ -315,7 +315,7 @@ abstract contract AccessControlDefaultAdminRules is IAccessControlDefaultAdminRu /** * @dev Setter of the tuple for pending admin and its schedule. * - * May emit a DefaultAdminTransferCanceled event. + * May emit a {DefaultAdminTransferCanceled} event. */ function _setPendingDefaultAdmin(address newAdmin, uint48 newSchedule) private { (, uint48 oldSchedule) = pendingDefaultAdmin(); @@ -333,7 +333,7 @@ abstract contract AccessControlDefaultAdminRules is IAccessControlDefaultAdminRu /** * @dev Setter of the tuple for pending delay and its schedule. * - * May emit a DefaultAdminDelayChangeCanceled event. + * May emit a {DefaultAdminDelayChangeCanceled} event. */ function _setPendingDelay(uint48 newDelay, uint48 newSchedule) private { uint48 oldSchedule = _pendingDelaySchedule; diff --git a/dependencies/@openzeppelin-contracts-5.5.0/access/extensions/AccessControlEnumerable.sol b/dependencies/@openzeppelin-contracts-5.7.0/access/extensions/AccessControlEnumerable.sol similarity index 96% rename from dependencies/@openzeppelin-contracts-5.5.0/access/extensions/AccessControlEnumerable.sol rename to dependencies/@openzeppelin-contracts-5.7.0/access/extensions/AccessControlEnumerable.sol index 26a1594..1e49385 100644 --- a/dependencies/@openzeppelin-contracts-5.5.0/access/extensions/AccessControlEnumerable.sol +++ b/dependencies/@openzeppelin-contracts-5.7.0/access/extensions/AccessControlEnumerable.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -// OpenZeppelin Contracts (last updated v5.5.0) (access/extensions/AccessControlEnumerable.sol) +// OpenZeppelin Contracts (last updated v5.7.0) (access/extensions/AccessControlEnumerable.sol) pragma solidity ^0.8.24; @@ -34,7 +34,7 @@ abstract contract AccessControlEnumerable is IAccessControlEnumerable, AccessCon * for more information. */ function getRoleMember(bytes32 role, uint256 index) public view virtual returns (address) { - return _roleMembers[role].at(index); + return _roleMembers[role].pos(index); } /** diff --git a/dependencies/@openzeppelin-contracts-5.5.0/access/extensions/IAccessControlDefaultAdminRules.sol b/dependencies/@openzeppelin-contracts-5.7.0/access/extensions/IAccessControlDefaultAdminRules.sol similarity index 95% rename from dependencies/@openzeppelin-contracts-5.5.0/access/extensions/IAccessControlDefaultAdminRules.sol rename to dependencies/@openzeppelin-contracts-5.7.0/access/extensions/IAccessControlDefaultAdminRules.sol index 1d91399..62f8e1b 100644 --- a/dependencies/@openzeppelin-contracts-5.5.0/access/extensions/IAccessControlDefaultAdminRules.sol +++ b/dependencies/@openzeppelin-contracts-5.7.0/access/extensions/IAccessControlDefaultAdminRules.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -// OpenZeppelin Contracts (last updated v5.5.0) (access/extensions/IAccessControlDefaultAdminRules.sol) +// OpenZeppelin Contracts (last updated v5.6.0) (access/extensions/IAccessControlDefaultAdminRules.sol) pragma solidity >=0.8.4; @@ -103,7 +103,7 @@ interface IAccessControlDefaultAdminRules is IAccessControl { * * - Only can be called by the current {defaultAdmin}. * - * Emits a DefaultAdminRoleChangeStarted event. + * Emits a {DefaultAdminTransferScheduled} event. */ function beginDefaultAdminTransfer(address newAdmin) external; @@ -116,7 +116,7 @@ interface IAccessControlDefaultAdminRules is IAccessControl { * * - Only can be called by the current {defaultAdmin}. * - * May emit a DefaultAdminTransferCanceled event. + * May emit a {DefaultAdminTransferCanceled} event. */ function cancelDefaultAdminTransfer() external; @@ -160,7 +160,7 @@ interface IAccessControlDefaultAdminRules is IAccessControl { * * - Only can be called by the current {defaultAdmin}. * - * Emits a DefaultAdminDelayChangeScheduled event and may emit a DefaultAdminDelayChangeCanceled event. + * Emits a {DefaultAdminDelayChangeScheduled} event and may emit a {DefaultAdminDelayChangeCanceled} event. */ function changeDefaultAdminDelay(uint48 newDelay) external; @@ -171,7 +171,7 @@ interface IAccessControlDefaultAdminRules is IAccessControl { * * - Only can be called by the current {defaultAdmin}. * - * May emit a DefaultAdminDelayChangeCanceled event. + * May emit a {DefaultAdminDelayChangeCanceled} event. */ function rollbackDefaultAdminDelay() external; diff --git a/dependencies/@openzeppelin-contracts-5.5.0/access/extensions/IAccessControlEnumerable.sol b/dependencies/@openzeppelin-contracts-5.7.0/access/extensions/IAccessControlEnumerable.sol similarity index 100% rename from dependencies/@openzeppelin-contracts-5.5.0/access/extensions/IAccessControlEnumerable.sol rename to dependencies/@openzeppelin-contracts-5.7.0/access/extensions/IAccessControlEnumerable.sol diff --git a/dependencies/@openzeppelin-contracts-5.5.0/access/manager/AccessManaged.sol b/dependencies/@openzeppelin-contracts-5.7.0/access/manager/AccessManaged.sol similarity index 100% rename from dependencies/@openzeppelin-contracts-5.5.0/access/manager/AccessManaged.sol rename to dependencies/@openzeppelin-contracts-5.7.0/access/manager/AccessManaged.sol diff --git a/dependencies/@openzeppelin-contracts-5.5.0/access/manager/AccessManager.sol b/dependencies/@openzeppelin-contracts-5.7.0/access/manager/AccessManager.sol similarity index 92% rename from dependencies/@openzeppelin-contracts-5.5.0/access/manager/AccessManager.sol rename to dependencies/@openzeppelin-contracts-5.7.0/access/manager/AccessManager.sol index 12a734d..d4afbac 100644 --- a/dependencies/@openzeppelin-contracts-5.5.0/access/manager/AccessManager.sol +++ b/dependencies/@openzeppelin-contracts-5.7.0/access/manager/AccessManager.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -// OpenZeppelin Contracts (last updated v5.5.0) (access/manager/AccessManager.sol) +// OpenZeppelin Contracts (last updated v5.7.0) (access/manager/AccessManager.sol) pragma solidity ^0.8.20; @@ -148,6 +148,11 @@ contract AccessManager is Context, Multicall, IAccessManager { // 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 if (selector == IAccessManaged.setAuthority.selector) { + (bool isAdmin, uint32 executionDelay) = hasRole(ADMIN_ROLE, caller); + uint32 adminDelay = getTargetAdminDelay(target); + uint32 setAuthorityDelay = uint32(Math.max(executionDelay, adminDelay)); + return isAdmin ? (setAuthorityDelay == 0, setAuthorityDelay) : (false, 0); } else { uint64 roleId = getTargetFunctionRole(target, selector); (bool isMember, uint32 currentDelay) = hasRole(roleId, caller); @@ -324,7 +329,7 @@ contract AccessManager is Context, Multicall, IAccessManager { * 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. + * anyone to grant or revoke such role. */ function _setRoleAdmin(uint64 roleId, uint64 admin) internal virtual { if (roleId == ADMIN_ROLE || roleId == PUBLIC_ROLE) { @@ -388,6 +393,11 @@ contract AccessManager is Context, Multicall, IAccessManager { * Emits a {TargetFunctionRoleUpdated} event. */ function _setTargetFunctionRole(address target, bytes4 selector, uint64 roleId) internal virtual { + if (selector == IAccessManaged.setAuthority.selector) { + // Prevent updating authority using an execute call, instead only allow it through updateAuthority to + // ensure the proper delay and admin restrictions are applied. + revert AccessManagerLockedFunction(selector); + } _targets[target].allowedRoles[selector] = roleId; emit TargetFunctionRoleUpdated(target, selector, roleId); } @@ -531,13 +541,8 @@ contract AccessManager is Context, Multicall, IAccessManager { 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); - } + } else if (!_canCancel(caller, target, data)) { + revert AccessManagerUnauthorizedCancel(msgsender, caller, target, selector); } delete _schedules[operationId].timepoint; // reset the timepoint, keep the nonce @@ -711,6 +716,37 @@ contract AccessManager is Context, Multicall, IAccessManager { return (delay == 0, delay); } + /** + * @dev Returns true if a scheduled operation can be canceled by the caller. + */ + function _canCancel(address caller, address target, bytes calldata data) internal view virtual returns (bool) { + address msgsender = _msgSender(); + + // caller can cancel if they are the msg.sender of the scheduled operation + if (caller == msgsender) { + return true; + } + + // admins can cancel any operation, and guardians of the target function's role can cancel it + (bool isAdmin, ) = hasRole(ADMIN_ROLE, msgsender); + (bool isGuardian, ) = hasRole(getRoleGuardian(getTargetFunctionRole(target, _checkSelector(data))), msgsender); + if (isAdmin || isGuardian) { + return true; + } + + // if the target is this AccessManager and the call matches an admin-restricted function, allow members + // of the admin role returned by _getAdminRestrictions to cancel. ADMIN_ROLE was already checked above. + if (target == address(this)) { + (bool adminRestricted, uint64 roleId, ) = _getAdminRestrictions(data); + if (adminRestricted && roleId != ADMIN_ROLE) { + (bool inRole, ) = hasRole(roleId, msgsender); + return inRole; + } + } + + return false; + } + /** * @dev Returns true if a call with `target` and `selector` is being executed via {executed}. */ diff --git a/dependencies/@openzeppelin-contracts-5.5.0/access/manager/AuthorityUtils.sol b/dependencies/@openzeppelin-contracts-5.7.0/access/manager/AuthorityUtils.sol similarity index 100% rename from dependencies/@openzeppelin-contracts-5.5.0/access/manager/AuthorityUtils.sol rename to dependencies/@openzeppelin-contracts-5.7.0/access/manager/AuthorityUtils.sol diff --git a/dependencies/@openzeppelin-contracts-5.5.0/access/manager/IAccessManaged.sol b/dependencies/@openzeppelin-contracts-5.7.0/access/manager/IAccessManaged.sol similarity index 100% rename from dependencies/@openzeppelin-contracts-5.5.0/access/manager/IAccessManaged.sol rename to dependencies/@openzeppelin-contracts-5.7.0/access/manager/IAccessManaged.sol diff --git a/dependencies/@openzeppelin-contracts-5.5.0/access/manager/IAccessManager.sol b/dependencies/@openzeppelin-contracts-5.7.0/access/manager/IAccessManager.sol similarity index 94% rename from dependencies/@openzeppelin-contracts-5.5.0/access/manager/IAccessManager.sol rename to dependencies/@openzeppelin-contracts-5.7.0/access/manager/IAccessManager.sol index 749fe26..f1edfbc 100644 --- a/dependencies/@openzeppelin-contracts-5.5.0/access/manager/IAccessManager.sol +++ b/dependencies/@openzeppelin-contracts-5.7.0/access/manager/IAccessManager.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -// OpenZeppelin Contracts (last updated v5.5.0) (access/manager/IAccessManager.sol) +// OpenZeppelin Contracts (last updated v5.7.0) (access/manager/IAccessManager.sol) pragma solidity >=0.8.4; @@ -36,7 +36,7 @@ interface IAccessManager { * * 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. + * otherwise it indicates the timestamp when the execution delay update takes effect for this account and roleId. */ event RoleGranted(uint64 indexed roleId, address indexed account, uint32 delay, uint48 since, bool newMember); @@ -80,6 +80,7 @@ interface IAccessManager { error AccessManagerNotReady(bytes32 operationId); error AccessManagerExpired(bytes32 operationId); error AccessManagerLockedRole(uint64 roleId); + error AccessManagerLockedFunction(bytes4 selector); error AccessManagerBadConfirmation(); error AccessManagerUnauthorizedAccount(address msgsender, uint64 roleId); error AccessManagerUnauthorizedCall(address caller, address target, bytes4 selector); @@ -106,6 +107,11 @@ interface IAccessManager { * * NOTE: This function does not report the permissions of the admin functions in the manager itself. These are defined by the * {AccessManager} documentation. + * + * NOTE: The `setAuthority(address)` selector is reserved on all targets (whether or not they are {AccessManaged}): + * it is gated to `ADMIN_ROLE` with a possible delay, and it cannot be reconfigured via {setTargetFunctionRole}. + * Any target function whose selector collides with `setAuthority(address)` inherits this restriction when routed + * through the manager. */ function canCall( address caller, @@ -196,6 +202,7 @@ interface IAccessManager { * Requirements: * * - the caller must be a global admin + * - `roleId` must not be the `ADMIN_ROLE` or `PUBLIC_ROLE` * * Emits a {RoleLabel} event. */ @@ -254,6 +261,7 @@ interface IAccessManager { * Requirements: * * - the caller must be a global admin + * - `roleId` must not be the `ADMIN_ROLE` or `PUBLIC_ROLE` * * Emits a {RoleAdminChanged} event */ @@ -265,6 +273,7 @@ interface IAccessManager { * Requirements: * * - the caller must be a global admin + * - `roleId` must not be the `ADMIN_ROLE` or `PUBLIC_ROLE` * * Emits a {RoleGuardianChanged} event */ @@ -276,6 +285,7 @@ interface IAccessManager { * Requirements: * * - the caller must be a global admin + * - `roleId` must not be the `PUBLIC_ROLE` * * Emits a {RoleGrantDelayChanged} event. */ @@ -287,6 +297,7 @@ interface IAccessManager { * Requirements: * * - the caller must be a global admin + * - `selectors` must not contain the `setAuthority(address)` selector, which is reserved. See {canCall}. * * Emits a {TargetFunctionRoleUpdated} event per selector. */ diff --git a/dependencies/@openzeppelin-contracts-5.5.0/access/manager/IAuthority.sol b/dependencies/@openzeppelin-contracts-5.7.0/access/manager/IAuthority.sol similarity index 100% rename from dependencies/@openzeppelin-contracts-5.5.0/access/manager/IAuthority.sol rename to dependencies/@openzeppelin-contracts-5.7.0/access/manager/IAuthority.sol diff --git a/dependencies/@openzeppelin-contracts-5.5.0/account/Account.sol b/dependencies/@openzeppelin-contracts-5.7.0/account/Account.sol similarity index 93% rename from dependencies/@openzeppelin-contracts-5.5.0/account/Account.sol rename to dependencies/@openzeppelin-contracts-5.7.0/account/Account.sol index 0b33538..cfec3d6 100644 --- a/dependencies/@openzeppelin-contracts-5.5.0/account/Account.sol +++ b/dependencies/@openzeppelin-contracts-5.7.0/account/Account.sol @@ -1,10 +1,10 @@ // SPDX-License-Identifier: MIT -// OpenZeppelin Contracts (last updated v5.5.0) (account/Account.sol) +// OpenZeppelin Contracts (last updated v5.7.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 {PackedUserOperation, IAccount, IEntryPoint} from "../interfaces/IERC4337.sol"; +import {ERC4337Utils} from "./utils/ERC4337Utils.sol"; import {AbstractSigner} from "../utils/cryptography/signers/AbstractSigner.sol"; import {LowLevelCall} from "../utils/LowLevelCall.sol"; @@ -15,7 +15,7 @@ import {LowLevelCall} from "../utils/LowLevelCall.sol"; * 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. + * feature that all Accounts 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 @@ -50,7 +50,7 @@ abstract contract Account is AbstractSigner, IAccount { * @dev Canonical entry point for the account that forwards and validates user operations. */ function entryPoint() public view virtual returns (IEntryPoint) { - return ERC4337Utils.ENTRYPOINT_V08; + return ERC4337Utils.ENTRYPOINT_V09; } /** @@ -104,7 +104,7 @@ abstract contract Account is AbstractSigner, IAccount { } /** - * @dev Virtual function that returns the signable hash for a user operations. Since v0.8.0 of the entrypoint, + * @dev Virtual function that returns the signable hash for a user operation. Since v0.8.0 of the entrypoint, * `userOpHash` is an EIP-712 hash that can be signed directly. */ function _signableUserOpHash( diff --git a/dependencies/@openzeppelin-contracts-5.5.0/account/extensions/draft-AccountERC7579.sol b/dependencies/@openzeppelin-contracts-5.7.0/account/extensions/draft-AccountERC7579.sol similarity index 96% rename from dependencies/@openzeppelin-contracts-5.5.0/account/extensions/draft-AccountERC7579.sol rename to dependencies/@openzeppelin-contracts-5.7.0/account/extensions/draft-AccountERC7579.sol index 2302d83..6bf37e0 100644 --- a/dependencies/@openzeppelin-contracts-5.5.0/account/extensions/draft-AccountERC7579.sol +++ b/dependencies/@openzeppelin-contracts-5.7.0/account/extensions/draft-AccountERC7579.sol @@ -1,9 +1,9 @@ // SPDX-License-Identifier: MIT -// OpenZeppelin Contracts (last updated v5.5.0) (account/extensions/draft-AccountERC7579.sol) +// OpenZeppelin Contracts (last updated v5.7.0) (account/extensions/draft-AccountERC7579.sol) pragma solidity ^0.8.26; -import {PackedUserOperation} from "../../interfaces/draft-IERC4337.sol"; +import {PackedUserOperation} from "../../interfaces/IERC4337.sol"; import {IERC1271} from "../../interfaces/IERC1271.sol"; import { IERC7579Module, @@ -85,7 +85,7 @@ abstract contract AccountERC7579 is Account, IERC1271, IERC7579Execution, IERC75 /// @inheritdoc IERC7579AccountConfig function accountId() public view virtual returns (string memory) { // vendorname.accountname.semver - return "@openzeppelin/community-contracts.AccountERC7579.v0.0.0"; + return "@openzeppelin/contracts.AccountERC7579.v1.0.0"; } /** @@ -284,6 +284,12 @@ abstract contract AccountERC7579 is Account, IERC1271, IERC7579Execution, IERC75 * Requirements: * * * Module must be already installed. Reverts with {ERC7579Utils-ERC7579UninstalledModule} otherwise. + * * The module's own {IERC7579Module-onUninstall} function must succeed. + * + * NOTE: The module's {IERC7579Module-onUninstall} callback is invoked without catching reverts, so a buggy or + * malicious module can block its own uninstallation by reverting. A forced uninstallation that bypasses this + * callback can still be performed through a delegate call (`CALLTYPE_DELEGATECALL`) via {execute}, running logic + * in the account's context that clears the module from storage directly. */ function _uninstallModule(uint256 moduleTypeId, address module, bytes memory deInitData) internal virtual { require(supportsModule(moduleTypeId), ERC7579Utils.ERC7579UnsupportedModuleType(moduleTypeId)); @@ -400,7 +406,7 @@ abstract contract AccountERC7579 is Account, IERC1271, IERC7579Execution, IERC75 * 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. + * clones/proxy/EIP-7702 delegates and therefore rely on initializers anyway. */ function _decodeFallbackData( bytes memory data diff --git a/dependencies/@openzeppelin-contracts-5.5.0/account/extensions/draft-AccountERC7579Hooked.sol b/dependencies/@openzeppelin-contracts-5.7.0/account/extensions/draft-AccountERC7579Hooked.sol similarity index 88% rename from dependencies/@openzeppelin-contracts-5.5.0/account/extensions/draft-AccountERC7579Hooked.sol rename to dependencies/@openzeppelin-contracts-5.7.0/account/extensions/draft-AccountERC7579Hooked.sol index c83f38f..5655136 100644 --- a/dependencies/@openzeppelin-contracts-5.5.0/account/extensions/draft-AccountERC7579Hooked.sol +++ b/dependencies/@openzeppelin-contracts-5.7.0/account/extensions/draft-AccountERC7579Hooked.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -// OpenZeppelin Contracts (last updated v5.4.0) (account/extensions/draft-AccountERC7579Hooked.sol) +// OpenZeppelin Contracts (last updated v5.7.0) (account/extensions/draft-AccountERC7579Hooked.sol) pragma solidity ^0.8.26; @@ -42,7 +42,7 @@ abstract contract AccountERC7579Hooked is AccountERC7579 { /// @inheritdoc AccountERC7579 function accountId() public view virtual override returns (string memory) { // vendorname.accountname.semver - return "@openzeppelin/community-contracts.AccountERC7579Hooked.v0.0.0"; + return "@openzeppelin/contracts.AccountERC7579Hooked.v1.0.0"; } /// @dev Returns the hook module address if installed, or `address(0)` otherwise. @@ -79,7 +79,13 @@ abstract contract AccountERC7579Hooked is AccountERC7579 { super._installModule(moduleTypeId, module, initData); } - /// @dev Uninstalls a module with support for hook modules. See {AccountERC7579-_uninstallModule} + /** + * @dev Uninstalls a module with support for hook modules. See {AccountERC7579-_uninstallModule}. + * + * NOTE: Uninstalling the hook runs through its own `withHook` `preCheck`/`postCheck`, so a hook that reverts + * there blocks its removal. Since `_execute` is `withHook`-gated too, the delegatecall escape hatch does not + * apply, and such a hook may be impossible to uninstall. + */ function _uninstallModule( uint256 moduleTypeId, address module, diff --git a/dependencies/@openzeppelin-contracts-5.5.0/account/extensions/draft-ERC7821.sol b/dependencies/@openzeppelin-contracts-5.7.0/account/extensions/draft-ERC7821.sol similarity index 100% rename from dependencies/@openzeppelin-contracts-5.5.0/account/extensions/draft-ERC7821.sol rename to dependencies/@openzeppelin-contracts-5.7.0/account/extensions/draft-ERC7821.sol diff --git a/dependencies/@openzeppelin-contracts-5.7.0/account/paymaster/Paymaster.sol b/dependencies/@openzeppelin-contracts-5.7.0/account/paymaster/Paymaster.sol new file mode 100644 index 0000000..343d928 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.7.0/account/paymaster/Paymaster.sol @@ -0,0 +1,170 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v5.7.0) (account/paymaster/Paymaster.sol) + +pragma solidity ^0.8.20; + +import {ERC4337Utils} from "../utils/ERC4337Utils.sol"; +import {IEntryPoint, IPaymaster, PackedUserOperation} from "../../interfaces/IERC4337.sol"; + +/** + * @dev A simple ERC4337 paymaster implementation. This base implementation only includes the minimal logic to validate + * and pay for user operations. + * + * Developers must implement the {Paymaster-_validatePaymasterUserOp} function to define the paymaster's validation + * and payment logic, and {Paymaster-_postOp} function to define the post-operation logic. The `context` parameter + * is used to pass data between the validation and post execution phases. + * + * The paymaster includes support to call the {IEntryPointStake} interface to manage the paymaster's deposits and stakes + * through the internal functions {_deposit}, {_withdraw}, {_addStake}, {_unlockStake} and {_withdrawStake}. + * + * * Deposits are used to pay for user operations. + * * Stakes are used to guarantee the paymaster's reputation and obtain more flexibility in accessing storage. + * + * [IMPORTANT] + * ==== + * The deposit and stake functions are `internal` so that developers can expose them under the public interface and + * authorization mechanism of their choice. Public versions of {_withdraw}, {_unlockStake} and {_withdrawStake} MUST + * be exposed and properly authorized, otherwise the deposit and stake will be permanently locked. + * + * Example implementation exposing the deposit and stake functions using {AccessControl}: + * + * ```solidity + * contract MyPaymaster is Paymaster, AccessControl { + * bytes32 private constant WITHDRAWER_ROLE = keccak256("WITHDRAWER_ROLE"); + * bytes32 private constant UNSTAKER_ROLE = keccak256("UNSTAKER_ROLE"); + * + * constructor() { + * _grantRole(DEFAULT_ADMIN_ROLE, msg.sender); + * } + * + * function deposit() public payable virtual { + * _deposit(msg.value); + * } + * + * function withdraw(address payable to, uint256 value) public virtual onlyRole(WITHDRAWER_ROLE) { + * _withdraw(to, value); + * } + * + * function addStake(uint32 unstakeDelaySec) public payable virtual { + * _addStake(msg.value, unstakeDelaySec); + * } + * + * function unlockStake() public virtual onlyRole(UNSTAKER_ROLE) { + * _unlockStake(); + * } + * + * function withdrawStake(address payable to) public virtual onlyRole(UNSTAKER_ROLE) { + * _withdrawStake(to); + * } + * + * function _validatePaymasterUserOp( + * PackedUserOperation calldata userOp, + * bytes32 userOpHash, + * uint256 requiredPreFund + * ) internal virtual override returns (bytes memory context, uint256 validationData) { + * // validation logic + * } + * } + * ``` + * ==== + * + * NOTE: See [Paymaster's unstaked reputation rules](https://eips.ethereum.org/EIPS/eip-7562#unstaked-paymasters-reputation-rules) + * for more details on the paymaster's storage access limitations. + */ +abstract contract Paymaster is IPaymaster { + /// @dev Unauthorized call to the paymaster. + error PaymasterUnauthorized(address sender); + + /// @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_V09; + } + + /// @inheritdoc IPaymaster + function validatePaymasterUserOp( + PackedUserOperation calldata userOp, + bytes32 userOpHash, + uint256 maxCost + ) public virtual onlyEntryPoint returns (bytes memory context, uint256 validationData) { + return _validatePaymasterUserOp(userOp, userOpHash, maxCost); + } + + /// @inheritdoc IPaymaster + function postOp( + PostOpMode mode, + bytes calldata context, + uint256 actualGasCost, + uint256 actualUserOpFeePerGas + ) public virtual onlyEntryPoint { + _postOp(mode, context, actualGasCost, actualUserOpFeePerGas); + } + + /** + * @dev Internal validation of whether the paymaster is willing to pay for the user operation. + * Returns the context to be passed to postOp and the validation data. + * + * The `requiredPreFund` is the amount the paymaster has to pay (in native tokens). It's calculated + * as `requiredGas * userOp.maxFeePerGas`, where `required` gas can be calculated from the user operation + * as `verificationGasLimit + callGasLimit + paymasterVerificationGasLimit + paymasterPostOpGasLimit + preVerificationGas` + */ + function _validatePaymasterUserOp( + PackedUserOperation calldata userOp, + bytes32 userOpHash, + uint256 requiredPreFund + ) internal virtual returns (bytes memory context, uint256 validationData); + + /** + * @dev Handles post user operation execution logic. The caller must be the entry point. + * + * It receives the `context` returned by `_validatePaymasterUserOp`. Function is not called if no context + * is returned by {validatePaymasterUserOp}. + * + * NOTE: The `actualUserOpFeePerGas` is not `tx.gasprice`. A user operation can be bundled with other transactions + * making the gas price of the user operation to differ. + */ + function _postOp( + PostOpMode /* mode */, + bytes calldata /* context */, + uint256 /* actualGasCost */, + uint256 /* actualUserOpFeePerGas */ + ) internal virtual {} + + /// @dev Ensures the caller is the {entrypoint}. + function _checkEntryPoint() internal view virtual { + address sender = msg.sender; + if (sender != address(entryPoint())) { + revert PaymasterUnauthorized(sender); + } + } + + /// @dev Calls {IEntryPointStake-depositTo}. + function _deposit(uint256 value) internal virtual { + entryPoint().depositTo{value: value}(address(this)); + } + + /// @dev Calls {IEntryPointStake-withdrawTo}. + function _withdraw(address payable to, uint256 value) internal virtual { + entryPoint().withdrawTo(to, value); + } + + /// @dev Calls {IEntryPointStake-addStake}. + function _addStake(uint256 value, uint32 unstakeDelaySec) internal virtual { + entryPoint().addStake{value: value}(unstakeDelaySec); + } + + /// @dev Calls {IEntryPointStake-unlockStake}. + function _unlockStake() internal virtual { + entryPoint().unlockStake(); + } + + /// @dev Calls {IEntryPointStake-withdrawStake}. + function _withdrawStake(address payable to) internal virtual { + entryPoint().withdrawStake(to); + } +} diff --git a/dependencies/@openzeppelin-contracts-5.7.0/account/paymaster/extensions/PaymasterERC20.sol b/dependencies/@openzeppelin-contracts-5.7.0/account/paymaster/extensions/PaymasterERC20.sol new file mode 100644 index 0000000..04e5e92 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.7.0/account/paymaster/extensions/PaymasterERC20.sol @@ -0,0 +1,363 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v5.7.0) (account/paymaster/extensions/PaymasterERC20.sol) + +pragma solidity ^0.8.20; + +import {ERC4337Utils, PackedUserOperation} from "../../utils/ERC4337Utils.sol"; +import {IERC20, SafeERC20} from "../../../token/ERC20/utils/SafeERC20.sol"; +import {Math} from "../../../utils/math/Math.sol"; +import {SafeCast} from "../../../utils/math/SafeCast.sol"; +import {Paymaster} from "../Paymaster.sol"; + +/** + * @dev Extension of {Paymaster} that enables users to pay gas with ERC-20 tokens. + * + * To enable this feature, developers must implement the {_fetchDetails} function: + * + * ```solidity + * function _fetchDetails( + * PackedUserOperation calldata userOp, + * bytes32 userOpHash + * ) internal view override returns (uint256 validationData, IERC20 token, uint256 tokenPerNative) { + * // Implement logic to fetch the token, and token price from the userOp + * } + * ``` + * + * The contract follows a pre-charge and refund model: + * 1. During validation, it pre-charges the maximum possible gas cost + * 2. After execution, it refunds any unused gas back to the user + * + * NOTE: {_prefund} performs a `transferFrom` during the validation phase, writing to the token contract's storage. + * ERC-7562 restricts unstaked paymasters from such accesses, and public mempool bundlers will reject these operations. + * Stake the paymaster (see {Paymaster-_addStake}) when deploying against a public mempool. + * + * [IMPORTANT] + * ==== + * The {_withdrawTokens} function is `internal` so that developers can expose it under the public interface and + * authorization mechanism of their choice. Public versions of {_withdrawTokens} MUST be exposed and properly authorized, + * otherwise the tokens will be permanently stuck in the paymaster. + * + * Example implementation exposing the {_withdrawTokens} function using {AccessControl}: + * + * ```solidity + * contract MyPaymaster is Paymaster, AccessControl { + * bytes32 private constant WITHDRAWER_ROLE = keccak256("WITHDRAWER_ROLE"); + * + * constructor() { + * _grantRole(DEFAULT_ADMIN_ROLE, msg.sender); + * } + * + * function withdrawTokens(IERC20 token, address recipient, uint256 amount) public virtual onlyRole(WITHDRAWER_ROLE) { + * _withdrawTokens(token, recipient, amount); + * } + * + * ... + * } + * ``` + * ==== + */ +abstract contract PaymasterERC20 is Paymaster { + using ERC4337Utils for *; + using Math for *; + using SafeCast for *; + using SafeERC20 for IERC20; + + /** + * @dev Emitted when a user operation identified by `userOpHash` is sponsored by this paymaster + * using the specified ERC-20 `token`. The `tokenAmount` is the amount charged for the operation, + * and `tokenPerNative` is the valuation of the token in units of token per native currency (e.g., ETH). + */ + event UserOperationSponsored( + bytes32 indexed userOpHash, + address indexed token, + uint256 tokenAmount, + uint256 tokenPerNative + ); + + /** + * @dev Thrown when the paymaster fails to refund the difference between the `prefundAmount` + * and the `actualAmount` of `token`. + */ + error PaymasterERC20FailedRefund(IERC20 token, uint256 prefundAmount, uint256 actualAmount, bytes prefundContext); + + /** + * @dev See {Paymaster-_validatePaymasterUserOp}. + * + * Attempts to retrieve the `token` and `tokenPerNative` from the user operation (see {_fetchDetails}) + * and prefund the user operation using these values and the `maxCost` argument (see {_prefund}). + * + * Returns `abi.encodePacked(userOpHash, token, tokenPerNative, prefundAmount, prefunder, penaltyGas, prefundContext)` + * in `context` if the prefund is successful. Otherwise, it returns empty bytes. + */ + function _validatePaymasterUserOp( + PackedUserOperation calldata userOp, + bytes32 userOpHash, + uint256 maxCost + ) internal virtual override returns (bytes memory context, uint256 validationData) { + IERC20 token; + uint256 tokenPerNative; + address userOpSender = userOp.sender; + (validationData, token, tokenPerNative) = _fetchDetails(userOp, userOpHash); + + if (uint160(validationData) == ERC4337Utils.SIG_VALIDATION_FAILED || tokenPerNative < _minTokensPerNative()) + return (bytes(""), ERC4337Utils.SIG_VALIDATION_FAILED); + + // Worst-case unused-gas penalty that the EntryPoint may debit from the paymaster's deposit for the + // user-controlled `paymasterPostOpGasLimit` (see {_postOpGasPenalty}). The EntryPoint computes this penalty + // only after `postOp` returns, so it is absent from the `actualGasCost` reported to {_postOp}. We price it + // into the charge here and retain it in {_postOp}, so a user cannot inflate `paymasterPostOpGasLimit` to + // drain the paymaster's deposit. + uint256 penaltyGas = _postOpGasPenalty(userOp.paymasterPostOpGasLimit()); + + // If the _erc20Cost math fails, the returned value will be type(uint256).max, which we will never be able + // to charge as a prefund. The `trySafeTransferFrom` in the `_prefund` will fail, causing success to be false. + // Saturating arithmetic keeps an overflow in the native cost from wrapping: it saturates to + // `type(uint256).max`, which `_erc20Cost` also returns, and fails the prefund instead of undercharging. + // + // native cost is computed as: maxCost + ((_postOpCost() + penaltyGas) * userOp.maxFeePerGas()) + uint256 maxTokenCost = _erc20Cost( + _postOpCost().saturatingAdd(penaltyGas).saturatingMul(userOp.maxFeePerGas()).saturatingAdd(maxCost), + tokenPerNative + ); + (bool success, address prefunder, uint256 prefundAmount, bytes memory prefundContext) = _prefund( + userOp, + userOpHash, + token, + tokenPerNative, + userOpSender, + maxTokenCost + ); + + return + success + ? ( + abi.encodePacked( + userOpHash, + token, + tokenPerNative, + prefundAmount, + prefunder, + penaltyGas, + prefundContext + ), + validationData + ) + : (bytes(""), ERC4337Utils.SIG_VALIDATION_FAILED); + } + + /** + * @dev Charges `prefundAmount` of `token` from `prefunder_` and returns the effective prefund actually pulled. + * + * The base implementation pulls exactly the requested `prefundAmount`. Extensions may inflate the amount + * (e.g. a guarantor adds the cost of the extra postOp work it performs) and must return the effective value. + * + * Returns `(success, prefunder, effectivePrefundAmount, prefundContext)`. `prefundContext` is forwarded to + * {_postOp} through its `context` argument and may be used by overrides to carry data into {_refund}. + * + * NOTE: Consider not reverting if the prefund fails when overriding this function. This is to avoid reverting + * during the validation phase of the user operation, which may penalize the paymaster's reputation according + * to ERC-7562 validation rules. + */ + function _prefund( + PackedUserOperation calldata /* userOp */, + bytes32 /* userOpHash */, + IERC20 token, + uint256 /* tokenPerNative */, + address prefunder_, + uint256 prefundAmount_ + ) internal virtual returns (bool success, address prefunder, uint256 prefundAmount, bytes memory prefundContext) { + return (token.trySafeTransferFrom(prefunder_, address(this), prefundAmount_), prefunder_, prefundAmount_, ""); + } + + /** + * @dev Attempts to refund the user operation after execution. See {_refund}. + * + * Reverts with {PaymasterERC20FailedRefund} if the refund fails. + * + * IMPORTANT: This function may revert after the user operation has been executed without + * reverting the user operation itself. Consider implementing a mechanism to handle + * this case gracefully. + */ + function _postOp( + PostOpMode /* mode */, + bytes calldata context, + uint256 actualGasCost, + uint256 actualUserOpFeePerGas + ) internal virtual override { + bytes32 userOpHash = bytes32(context[0x00:0x20]); + IERC20 token = IERC20(address(bytes20(context[0x20:0x34]))); + uint256 tokenPerNative = uint256(bytes32(context[0x34:0x54])); + uint256 prefundAmount = uint256(bytes32(context[0x54:0x74])); + address prefunder = address(bytes20(context[0x74:0x88])); + uint256 penaltyGas = uint256(bytes32(context[0x88:0xA8])); + bytes calldata prefundContext = context[0xA8:]; + + // If the _erc20Cost math fails, the returned value will be type(uint256).max, which we will never be able + // to charge as a refund. The `trySafeTransfer` in the `_refund` will fail, causing success to be false. + // `penaltyGas` covers the EntryPoint's unused-gas penalty on `paymasterPostOpGasLimit`, which is excluded + // from `actualGasCost` (the EntryPoint computes it only after `postOp` returns). See {_postOpGasPenalty}. + // + // native cost is computed as: actualGasCost + ((_postOpCost() + penaltyGas) * actualUserOpFeePerGas) + uint256 actualTokenCost = _erc20Cost( + _postOpCost().saturatingAdd(penaltyGas).saturatingMul(actualUserOpFeePerGas).saturatingAdd(actualGasCost), + tokenPerNative + ); + (bool success, uint256 actualAmount) = _refund( + token, + tokenPerNative, + actualTokenCost, + actualUserOpFeePerGas, + prefunder, + prefundAmount, + prefundContext + ); + if (!success) revert PaymasterERC20FailedRefund(token, prefundAmount, actualAmount, prefundContext); + + emit UserOperationSponsored(userOpHash, address(token), actualAmount, tokenPerNative); + } + + /** + * @dev Refunds `prefundAmount - actualAmount` of `token` back to `prefunder` and returns the + * `actualAmount` actually charged. + * + * `actualAmount` is pre-computed by {_postOp} via {_erc20Cost}. Extensions may change it (e.g. a + * guarantor adds its extra postOp cost or zeroes it out after pulling from the user) and must + * return the value that was effectively charged. + * + * Requirements: + * + * - `actualAmount <= prefundAmount`. + */ + function _refund( + IERC20 token, + uint256 /* tokenPerNative */, + uint256 actualAmount_, + uint256 /* actualUserOpFeePerGas */, + address prefunder, + uint256 prefundAmount, + bytes calldata /* prefundContext */ + ) internal virtual returns (bool success, uint256 actualAmount) { + // Under ERC-4337 EntryPoint, `actualGasCost <= maxCost` and `actualUserOpFeePerGas <= maxFeePerGas`, + // so `actualAmount_ <= prefundAmount` holds. + return (token.trySafeTransfer(prefunder, prefundAmount - actualAmount_), actualAmount_); + } + + /** + * @dev Retrieves payment details for a user operation. + * + * The values returned by this internal function are: + * + * * `validationData`: ERC-4337 validation data, indicating success/failure and optional time validity (`validAfter`, `validUntil`). + * * `token`: Address of the ERC-20 token used for payment to the paymaster. + * * `tokenPerNative`: Token units charged per unit of native currency. This is scaled by `_tokenPerNativeDenominator()` + * which defaults to 1e18 (wei per eth), making it effectively a number of token units per eth, and not per wei. + * + * ==== Calculating the token price + * + * `tokenPerNative` is the multiplier {_erc20Cost} applies to a native-currency gas cost to produce a token amount: + * `tokenAmount = (nativeCost * tokenPerNative) / _tokenPerNativeDenominator()`. Each elements is denominated as follows: + * + * * `tokenAmount`: token units. + * * `nativeCost`: wei. + * * `tokenPerNative`: token units per eth. + * * `_tokenPerNativeDenominator()`: wei per native coin (1e18 on EVM chains). + * + * For a token priced from USD oracles, derive `tokenPerNative` from the inverse exchange rate: + * + * `tokenPerNative = ( / 1e18) / ( / 10**) * _tokenPerNativeDenominator()` + * + * For example, suppose the token is USDC ($1 with 6 decimals) and the native currency is ETH ($2524.86 with 18 decimals). + * Then 1 wei of gas costs `(2524.86 / 1e18) / (1 / 1e6) = 2.52486e-9` USDC units, so with + * `_tokenPerNativeDenominator() = 1e18` we have `tokenPerNative = 2_524_860_000` (i.e. `2.52486e-9 * 1e18`). Charging + * `actualGasCost` wei yields `actualGasCost * 2_524_860_000 / 1e18` USDC units. + */ + function _fetchDetails( + PackedUserOperation calldata userOp, + bytes32 userOpHash + ) internal view virtual returns (uint256 validationData, IERC20 token, uint256 tokenPerNative); + + /** + * @dev Over-estimates the cost of the post-operation logic, which the EntryPoint charges to the paymaster but + * excludes from the `actualGasCost` reported to {_postOp}. + * + * NOTE: The default assumes a standard ERC-20. Override with a higher value for gas-heavier tokens; a persistent + * underestimate drains the paymaster's deposit. + */ + function _postOpCost() internal view virtual returns (uint256) { + return 30_000; + } + + /** + * @dev Worst-case unused-gas penalty (in gas units) that the EntryPoint charges the paymaster's deposit for an + * over-provisioned, user-controlled `paymasterPostOpGasLimit`. This penalty is excluded from the `actualGasCost` + * reported to {_postOp} (the EntryPoint computes it only after `postOp` returns), so it is priced into the charge + * during validation and retained in {_postOp}. Without it, a user could inflate `paymasterPostOpGasLimit` and + * have the paymaster absorb the resulting penalty on every operation, draining its deposit. + * + * The default mirrors the EntryPoint (v0.7-v0.9): a 10% penalty on unused postOp gas, applied only once the + * unused amount reaches 40_000 gas. The worst case is a `postOp` that consumes ~0 gas (e.g. it reverts and the + * maximum penalty is charged), leaving the whole limit unused. + * + * NOTE: Override to return 0 when targeting an EntryPoint that has no unused-gas penalty. + */ + function _postOpGasPenalty(uint256 postOpGasLimit) internal view virtual returns (uint256) { + return Math.ternary(postOpGasLimit > 40_000, postOpGasLimit / 10, 0); + } + + /// @dev Denominator used for interpreting the `tokenPerNative` returned by {_fetchDetails} as "fixed point" in {_erc20Cost}. + function _tokenPerNativeDenominator() internal view virtual returns (uint256) { + return 1e18; + } + + /** + * @dev Lower bound on `tokenPerNative` (see {_fetchDetails} for units). Operations whose `tokenPerNative` + * is strictly below this value are rejected with `SIG_VALIDATION_FAILED` before {_prefund} runs. + * + * To pick a value, decide: + * + * * `minCharge`: smallest token amount you want to bill per op (e.g. `0.01 USDC = 10_000` units). + * * `minGasCost`: smallest `actualGasCost + _postOpCost() * actualUserOpFeePerGas` you expect, in wei + * (= `minGas * minFeePerGas`; `minFeePerGas` can be as low as 1 wei on some L2s). + * + * Then set `_minTokensPerNative() >= minCharge * _tokenPerNativeDenominator() / minGasCost`. + * + * Example: a USDC (6 decimals) paymaster on a chain with `minFeePerGas = 1 gwei`, sponsoring + * ops of at least 100_000 gas and charging at least 0.01 USDC per op: + * + * ```solidity + * function _minTokensPerNative() internal view override returns (uint256) { + * return 100e6; // = 1e4 (0.01 USDC) * 1e18 / 1e14 (100_000 gas * 1 gwei) = 100 USDC/ETH + * } + * ``` + * + * WARNING: Setting `_minTokensPerNative()` below `minCharge * _tokenPerNativeDenominator() / minGasCost` + * lets {_erc20Cost} round to zero or to dust for the cheapest ops the paymaster accepts, + * sponsoring them at a low (or zero) price. + */ + function _minTokensPerNative() internal view virtual returns (uint256) { + return 0; + } + + /** + * @dev Calculates native currency cost to ERC-20 token cost. + * + * Returns `type(uint256).max` if computation overflows. + */ + function _erc20Cost(uint256 nativeCost, uint256 tokenPerNative) internal view virtual returns (uint256) { + uint256 denominator = _tokenPerNativeDenominator(); + (uint256 high, ) = nativeCost.mul512(tokenPerNative); + // Round up using a saturating add to avoid possible overflow of the rounding. + return + high < denominator + ? nativeCost.mulDiv(tokenPerNative, denominator).saturatingAdd( + (mulmod(nativeCost, tokenPerNative, denominator) > 0).toUint() + ) + : type(uint256).max; + } + + /// @dev Internal function that allows the withdrawer to extract ERC-20 tokens resulting from gas payments. + function _withdrawTokens(IERC20 token, address recipient, uint256 amount) internal virtual { + if (amount == type(uint256).max) amount = token.balanceOf(address(this)); + token.safeTransfer(recipient, amount); + } +} diff --git a/dependencies/@openzeppelin-contracts-5.7.0/account/paymaster/extensions/PaymasterERC20Guarantor.sol b/dependencies/@openzeppelin-contracts-5.7.0/account/paymaster/extensions/PaymasterERC20Guarantor.sol new file mode 100644 index 0000000..3d975d6 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.7.0/account/paymaster/extensions/PaymasterERC20Guarantor.sol @@ -0,0 +1,160 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v5.7.0) (account/paymaster/extensions/PaymasterERC20Guarantor.sol) + +pragma solidity ^0.8.20; + +import {ERC4337Utils, PackedUserOperation} from "../../utils/ERC4337Utils.sol"; +import {IERC20, SafeERC20} from "../../../token/ERC20/utils/SafeERC20.sol"; +import {Math} from "../../../utils/math/Math.sol"; +import {PaymasterERC20} from "./PaymasterERC20.sol"; + +/** + * @dev Extension of {PaymasterERC20} that enables third parties to guarantee user operations. + * + * This contract allows a guarantor to pre-fund user operations on behalf of users. The guarantor + * pays the maximum possible gas cost upfront, and after execution: + * 1. If the user repays the guarantor, the guarantor gets their funds back + * 2. If the user fails to repay, the guarantor absorbs the cost + * + * A common use case is for guarantors to pay for the operations of users claiming airdrops. In this scenario: + * + * * The guarantor pays the gas fees upfront + * * The user claims their airdrop tokens + * * The user repays the guarantor from the claimed tokens + * * If the user fails to repay, the guarantor absorbs the cost + * + * The guarantor is identified through the {_fetchGuarantor} function, which must be implemented + * by developers to determine who can guarantee operations. This allows for flexible guarantor selection + * logic based on the specific requirements of the application. + */ +abstract contract PaymasterERC20Guarantor is PaymasterERC20 { + using ERC4337Utils for *; + using Math for *; + using SafeERC20 for IERC20; + + /// @dev Emitted when a user operation identified by `userOpHash` is guaranteed by a `guarantor` for `prefundAmount`. + event UserOperationGuaranteed(bytes32 indexed userOpHash, address indexed guarantor, uint256 prefundAmount); + + /** + * @dev Prefunds the user operation using either the guarantor or the default prefunder, and + * appends `userOp.sender` to the tail of `prefundContext` so the refund process can identify + * the user operation sender. + * + * For guaranteed ops, `prefundAmount` is inflated by {_guaranteedPostOpCost} worth of tokens + * so the prefund pulled from the guarantor covers the extra postOp work done in {_refund} + * ({SafeERC20-trySafeTransferFrom} from the user + {SafeERC20-trySafeTransfer} to the guarantor). + */ + function _prefund( + PackedUserOperation calldata userOp, + bytes32 userOpHash, + IERC20 token, + uint256 tokenPrice, + address prefunder_, + uint256 prefundAmount_ + ) + internal + virtual + override + returns (bool success, address prefunder, uint256 prefundAmount, bytes memory prefundContext) + { + address guarantor = _fetchGuarantor(userOp); + bool isGuaranteed = guarantor != address(0); + + // If there is a guarantor, add more funds to cover the extra postOp cost + // and set the guarantor as the prefunder. + if (isGuaranteed) { + // `_erc20Cost` may return `type(uint256).max` as an overflow sentinel. `saturatingAdd` preserves it + // so the bad value reaches `trySafeTransferFrom` and fails there, instead of reverting here. + uint256 guaranteedPostOpCost = _erc20Cost(_guaranteedPostOpCost() * userOp.maxFeePerGas(), tokenPrice); + prefundAmount_ = prefundAmount_.saturatingAdd(guaranteedPostOpCost); + prefunder_ = guarantor; + } + (success, prefunder, prefundAmount, prefundContext) = super._prefund( + userOp, + userOpHash, + token, + tokenPrice, + prefunder_, + prefundAmount_ + ); + if (prefunder == guarantor) { + emit UserOperationGuaranteed(userOpHash, prefunder, prefundAmount); + } + return (success, prefunder, prefundAmount_, abi.encodePacked(prefundContext, userOp.sender)); + } + + /** + * @dev Handles the refund process for guaranteed operations. + * + * * **Non-guaranteed** (`prefunder == userOp.sender`): pass the base `actualAmount` through to + * {PaymasterERC20-_refund}. + * * **Guaranteed**: augment `actualAmount` by {_guaranteedPostOpCost} * `actualUserOpFeePerGas` + * (priced in tokens), pull it from `userOp.sender`, and call {PaymasterERC20-_refund} with + * `actualAmount = 0` so the guarantor gets the full `prefundAmount` back. If the user fails to pay, + * the guarantor absorbs the GUARANTEED cost (not the base cost). + */ + function _refund( + IERC20 token, + uint256 tokenPrice, + uint256 actualAmount, + uint256 actualUserOpFeePerGas, + address prefunder, + uint256 prefundAmount, + bytes calldata prefundContext + ) internal virtual override returns (bool refunded, uint256 effectiveAmount) { + address userOpSender = address(bytes20(prefundContext[prefundContext.length - 20:])); + + // If the prefunder is not the userOp sender, it means the operation is guaranteed + // In that case we: + // 1. update the actualAmount to include the extra postOp cost. + // 2. register that updated amount as the effective cost of the operation (for event logs). + // 3. try to pull the actualAmount from the userOp sender. + // 4. on success, zero out the actualAmount so super refunds the guarantor in full; + // on failure, leave it so super deducts it and the guarantor absorbs the cost. + if (prefunder != userOpSender) { + // If the values used here are able to cause that _erc20Cost math to fail (and return type(uint256).max), + // then the same failure must have already happened in the _prefund phase, causing the whole userOp to + // fail before even reaching this point. + uint256 guaranteedPostOpAmount = _erc20Cost(_guaranteedPostOpCost() * actualUserOpFeePerGas, tokenPrice); + actualAmount += guaranteedPostOpAmount; + effectiveAmount = actualAmount; + + // The paymaster gets the funds first, so in case of a failure, the guarantor absorbs the cost. + if (token.trySafeTransferFrom(userOpSender, address(this), actualAmount)) { + actualAmount = 0; + } + } else { + effectiveAmount = actualAmount; + } + + (refunded, ) = super._refund( + token, + tokenPrice, + actualAmount, + actualUserOpFeePerGas, + prefunder, + prefundAmount, + prefundContext[:prefundContext.length - 20] + ); + + return (refunded, effectiveAmount); + } + + /** + * @dev Fetches the guarantor address and validation data from the user operation. + * + * NOTE: Return `address(0)` to disable the guarantor feature. If supported, ensure + * explicit consent (e.g., signature verification) to prevent unauthorized use. + */ + function _fetchGuarantor(PackedUserOperation calldata userOp) internal view virtual returns (address guarantor); + + /** + * @dev Over-estimates the cost of the post-operation logic. Added on top of {PaymasterERC20-_postOpCost} for + * guaranteed userOps. + * + * NOTE: Like {PaymasterERC20-_postOpCost}, override with a higher value for gas-heavier tokens. + */ + function _guaranteedPostOpCost() internal view virtual returns (uint256) { + return 15_000; + } +} diff --git a/dependencies/@openzeppelin-contracts-5.7.0/account/paymaster/extensions/PaymasterERC721Owner.sol b/dependencies/@openzeppelin-contracts-5.7.0/account/paymaster/extensions/PaymasterERC721Owner.sol new file mode 100644 index 0000000..16b0723 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.7.0/account/paymaster/extensions/PaymasterERC721Owner.sol @@ -0,0 +1,54 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v5.7.0) (account/paymaster/extensions/PaymasterERC721Owner.sol) + +pragma solidity ^0.8.20; + +import {IERC721} from "../../../interfaces/IERC721.sol"; +import {ERC4337Utils, PackedUserOperation} from "../../utils/ERC4337Utils.sol"; +import {Paymaster} from "../Paymaster.sol"; + +/** + * @dev Extension of {Paymaster} that supports account based on ownership of an ERC-721 token. + * + * This paymaster will sponsor user operations if the user has at least 1 token of the token specified + * during construction. + * + * NOTE: {_validatePaymasterUserOp} reads `token.balanceOf` during the validation phase, accessing storage in + * an external contract. ERC-7562 restricts unstaked paymasters from such accesses, and public mempool bundlers + * will reject these operations when the token contract is proxied or upgradeable. Stake the paymaster + * (see {Paymaster-_addStake}) when deploying against a public mempool. + */ +abstract contract PaymasterERC721Owner is Paymaster { + IERC721 private immutable _token; + + constructor(IERC721 token_) { + _token = token_; + } + + /// @dev ERC-721 token used to validate the user operation. + function token() public virtual returns (IERC721) { + return _token; + } + + /** + * @dev Internal validation of whether the paymaster is willing to pay for the user operation. + * Returns the context to be passed to postOp and the validation data. + * + * NOTE: The default `context` is `bytes(0)`. Developers that add a context when overriding this function MUST + * also override {_postOp} to process the context passed along. + */ + function _validatePaymasterUserOp( + PackedUserOperation calldata userOp, + bytes32 /* userOpHash */, + uint256 /* maxCost */ + ) internal virtual override returns (bytes memory context, uint256 validationData) { + return ( + bytes(""), + // balanceOf reverts if the `userOp.sender` is the address(0), so this becomes unreachable with address(0) + // assuming a compliant entrypoint (`_validatePaymasterUserOp` is called after `validateUserOp`), + token().balanceOf(userOp.sender) == 0 + ? ERC4337Utils.SIG_VALIDATION_FAILED + : ERC4337Utils.SIG_VALIDATION_SUCCESS + ); + } +} diff --git a/dependencies/@openzeppelin-contracts-5.7.0/account/paymaster/extensions/PaymasterSigner.sol b/dependencies/@openzeppelin-contracts-5.7.0/account/paymaster/extensions/PaymasterSigner.sol new file mode 100644 index 0000000..ff7bec2 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.7.0/account/paymaster/extensions/PaymasterSigner.sol @@ -0,0 +1,98 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v5.7.0) (account/paymaster/extensions/PaymasterSigner.sol) + +pragma solidity ^0.8.24; + +import {ERC4337Utils, PackedUserOperation} from "../../utils/ERC4337Utils.sol"; +import {AbstractSigner} from "../../../utils/cryptography/signers/AbstractSigner.sol"; +import {EIP712} from "../../../utils/cryptography/EIP712.sol"; +import {Paymaster} from "../Paymaster.sol"; +import {Calldata} from "../../../utils/Calldata.sol"; + +/** + * @dev Extension of {Paymaster} that adds signature validation. See {SignerECDSA}, {SignerP256} or {SignerRSA}. + * + * Example of usage: + * + * ```solidity + * contract MyPaymasterECDSASigner is PaymasterSigner, SignerECDSA { + * constructor(address signerAddr) EIP712("MyPaymasterECDSASigner", "1") SignerECDSA(signerAddr) {} + * } + * ``` + */ +abstract contract PaymasterSigner is AbstractSigner, EIP712, Paymaster { + using ERC4337Utils for *; + + bytes32 private constant USER_OPERATION_REQUEST_TYPEHASH = + keccak256( + "UserOperationRequest(address sender,uint256 nonce,bytes initCode,bytes callData,bytes32 accountGasLimits,uint256 preVerificationGas,bytes32 gasFees,uint256 paymasterVerificationGasLimit,uint256 paymasterPostOpGasLimit,uint48 validAfter,uint48 validUntil)" + ); + + /** + * @dev Virtual function that returns the signable hash for a user operations. Given the `userOpHash` + * contains the `paymasterAndData` itself, it's not possible to sign that value directly. Instead, + * this function must be used to provide a custom mechanism to authorize an user operation. + */ + function _signableUserOpHash( + PackedUserOperation calldata userOp, + uint48 validAfter, + uint48 validUntil + ) internal view virtual returns (bytes32) { + return + _hashTypedDataV4( + keccak256( + abi.encode( + USER_OPERATION_REQUEST_TYPEHASH, + userOp.sender, + userOp.nonce, + keccak256(userOp.initCode), + keccak256(userOp.callData), + userOp.accountGasLimits, + userOp.preVerificationGas, + userOp.gasFees, + userOp.paymasterVerificationGasLimit(), + userOp.paymasterPostOpGasLimit(), + validAfter, + validUntil + ) + ) + ); + } + + /** + * @dev Internal validation of whether the paymaster is willing to pay for the user operation. + * Returns the context to be passed to postOp and the validation data. + * + * NOTE: The `context` returned is `bytes(0)`. Developers overriding this function MUST + * override {_postOp} to process the context passed along. + */ + function _validatePaymasterUserOp( + PackedUserOperation calldata userOp, + bytes32 /* userOpHash */, + uint256 /* maxCost */ + ) internal virtual override returns (bytes memory context, uint256 validationData) { + (uint48 validAfter, uint48 validUntil, bytes calldata signature) = _decodePaymasterUserOp(userOp); + + // Mixed `BLOCK_RANGE_FLAG` bits between `validAfter` and `validUntil` are rejected + bool rangeFlagsCompatible = (validAfter ^ validUntil) & ERC4337Utils.BLOCK_RANGE_FLAG == 0; + + return ( + bytes(""), + rangeFlagsCompatible + ? _rawSignatureValidation(_signableUserOpHash(userOp, validAfter, validUntil), signature) + .packValidationData(validAfter, validUntil) + : ERC4337Utils.SIG_VALIDATION_FAILED + ); + } + + /// @dev Decodes the user operation's data from `paymasterAndData`. + function _decodePaymasterUserOp( + PackedUserOperation calldata userOp + ) internal pure virtual returns (uint48 validAfter, uint48 validUntil, bytes calldata signature) { + bytes calldata paymasterData = userOp.paymasterData(); + return + paymasterData.length < 12 + ? (uint48(0), uint48(0), Calldata.emptyBytes()) + : (uint48(bytes6(paymasterData[0:6])), uint48(bytes6(paymasterData[6:12])), paymasterData[12:]); + } +} diff --git a/dependencies/@openzeppelin-contracts-5.5.0/account/utils/EIP7702Utils.sol b/dependencies/@openzeppelin-contracts-5.7.0/account/utils/EIP7702Utils.sol similarity index 83% rename from dependencies/@openzeppelin-contracts-5.5.0/account/utils/EIP7702Utils.sol rename to dependencies/@openzeppelin-contracts-5.7.0/account/utils/EIP7702Utils.sol index df9ca8a..5de0f6b 100644 --- a/dependencies/@openzeppelin-contracts-5.5.0/account/utils/EIP7702Utils.sol +++ b/dependencies/@openzeppelin-contracts-5.7.0/account/utils/EIP7702Utils.sol @@ -1,12 +1,12 @@ // SPDX-License-Identifier: MIT -// OpenZeppelin Contracts (last updated v5.5.0) (account/utils/EIP7702Utils.sol) +// OpenZeppelin Contracts (last updated v5.6.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]. + * See https://eips.ethereum.org/EIPS/eip-7702[EIP-7702]. */ library EIP7702Utils { bytes3 internal constant EIP7702_PREFIX = 0xef0100; diff --git a/dependencies/@openzeppelin-contracts-5.5.0/account/utils/draft-ERC4337Utils.sol b/dependencies/@openzeppelin-contracts-5.7.0/account/utils/ERC4337Utils.sol similarity index 53% rename from dependencies/@openzeppelin-contracts-5.5.0/account/utils/draft-ERC4337Utils.sol rename to dependencies/@openzeppelin-contracts-5.7.0/account/utils/ERC4337Utils.sol index 6d2c8cc..438098f 100644 --- a/dependencies/@openzeppelin-contracts-5.5.0/account/utils/draft-ERC4337Utils.sol +++ b/dependencies/@openzeppelin-contracts-5.7.0/account/utils/ERC4337Utils.sol @@ -1,9 +1,9 @@ // SPDX-License-Identifier: MIT -// OpenZeppelin Contracts (last updated v5.3.0) (account/utils/draft-ERC4337Utils.sol) +// OpenZeppelin Contracts (last updated v5.7.0) (account/utils/ERC4337Utils.sol) pragma solidity ^0.8.20; -import {IEntryPoint, PackedUserOperation} from "../../interfaces/draft-IERC4337.sol"; +import {IEntryPoint, PackedUserOperation} from "../../interfaces/IERC4337.sol"; import {Math} from "../../utils/math/Math.sol"; import {Calldata} from "../../utils/Calldata.sol"; import {Packing} from "../../utils/Packing.sol"; @@ -27,20 +27,46 @@ library ERC4337Utils { /// @dev Address of the entrypoint v0.8.0 IEntryPoint internal constant ENTRYPOINT_V08 = IEntryPoint(0x4337084D9E255Ff0702461CF8895CE9E3b5Ff108); + /// @dev Address of the entrypoint v0.9.0 + IEntryPoint internal constant ENTRYPOINT_V09 = IEntryPoint(0x433709009B8330FDa32311DF1C2AFA402eD8D009); + /// @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}. + /// @dev Magic value used in EntryPoint v0.9+ to detect the presence of a paymaster signature in `paymasterAndData`. + bytes8 internal constant PAYMASTER_SIG_MAGIC = 0x22e325a297439656; // keccak256("PaymasterSignature")[:8] + + /// @dev Highest bit set to 1 in a 6-bytes field. + uint48 internal constant BLOCK_RANGE_FLAG = 0x800000000000; + + /// @dev Mask for the lower 47 bits of a 6-bytes field (equivalent to uint48(~BLOCK_RANGE_FLAG)). + uint48 internal constant BLOCK_RANGE_MASK = 0x7fffffffffff; + + /// @dev Validity range of the validation data. + enum ValidationRange { + TIMESTAMP, + BLOCK + } + + /** + * @dev Parses the validation data into its components and the validity range. See {packValidationData}. + * Strips away the highest bit flag from the `validAfter` and `validUntil` fields. + */ function parseValidationData( uint256 validationData - ) internal pure returns (address aggregator, uint48 validAfter, uint48 validUntil) { + ) internal pure returns (address aggregator, uint48 validAfter, uint48 validUntil, ValidationRange range) { 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; + range = ((validAfter & validUntil & BLOCK_RANGE_FLAG) == 0) ? ValidationRange.TIMESTAMP : ValidationRange.BLOCK; + + validAfter &= BLOCK_RANGE_MASK; + validUntil &= BLOCK_RANGE_MASK; + + if (validUntil == 0) validUntil = BLOCK_RANGE_MASK; } /// @dev Packs the validation data into a single uint256. See {parseValidationData}. @@ -49,10 +75,36 @@ library ERC4337Utils { uint48 validAfter, uint48 validUntil ) internal pure returns (uint256) { + return + packValidationData( + aggregator, + validAfter, + validUntil, + (validAfter & validUntil & BLOCK_RANGE_FLAG) == 0 ? ValidationRange.TIMESTAMP : ValidationRange.BLOCK + ); + } + + /** + * @dev Variant of {packValidationData} that forces which validity range to use. This overwrites the presence of + * flags in `validAfter` and `validUntil`). + */ + function packValidationData( + address aggregator, + uint48 validAfter, + uint48 validUntil, + ValidationRange range + ) internal pure returns (uint256) { + if (range == ValidationRange.TIMESTAMP) { + validAfter &= BLOCK_RANGE_MASK; + validUntil &= BLOCK_RANGE_MASK; + } else if (range == ValidationRange.BLOCK) { + validAfter |= BLOCK_RANGE_FLAG; + validUntil |= BLOCK_RANGE_FLAG; + } 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. + /// @dev Variant of {packValidationData} that uses a boolean success flag instead of an aggregator address. function packValidationData(bool sigSuccess, uint48 validAfter, uint48 validUntil) internal pure returns (uint256) { return packValidationData( @@ -62,27 +114,59 @@ library ERC4337Utils { ); } + /** + * @dev Variant of {packValidationData} that uses a boolean success flag instead of an aggregator address and that + * forces which validity range to use. This overwrites the presence of flags in `validAfter` and `validUntil`). + */ + function packValidationData( + bool sigSuccess, + uint48 validAfter, + uint48 validUntil, + ValidationRange range + ) internal pure returns (uint256) { + return + packValidationData( + address(uint160(Math.ternary(sigSuccess, SIG_VALIDATION_SUCCESS, SIG_VALIDATION_FAILED))), + validAfter, + validUntil, + range + ); + } + /** * @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. + * + * NOTE: Returns `SIG_VALIDATION_FAILED` if the validation ranges differ. */ 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); + (address aggregator1, uint48 validAfter1, uint48 validUntil1, ValidationRange range1) = parseValidationData( + validationData1 + ); + (address aggregator2, uint48 validAfter2, uint48 validUntil2, ValidationRange range2) = 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); + if (range1 == range2) { + 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, range1); + } else { + return SIG_VALIDATION_FAILED; + } } /// @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); + (address aggregator_, uint48 validAfter, uint48 validUntil, ValidationRange range) = parseValidationData( + validationData + ); + uint256 current = Math.ternary(range == ValidationRange.TIMESTAMP, block.timestamp, block.number); + return (aggregator_, current <= validAfter || validUntil < current); } /// @dev Get the hash of a user operation for a given entrypoint @@ -91,7 +175,7 @@ library ERC4337Utils { // // 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 + // to recompute. Domain separator could be fetched 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); @@ -152,8 +236,44 @@ library ERC4337Utils { return self.paymasterAndData.length < 52 ? 0 : uint128(bytes16(self.paymasterAndData[36:52])); } - /// @dev Returns the fourth section of `paymasterAndData` from the {PackedUserOperation}. + /** + * @dev Returns the fourth section of `paymasterAndData` from the {PackedUserOperation}. + * If a paymaster signature is present, it is excluded from the returned data. + */ function paymasterData(PackedUserOperation calldata self) internal pure returns (bytes calldata) { - return self.paymasterAndData.length < 52 ? Calldata.emptyBytes() : self.paymasterAndData[52:]; + bool hasSignature = self.paymasterAndData.length > 9 && + bytes8(self.paymasterAndData[self.paymasterAndData.length - 8:]) == PAYMASTER_SIG_MAGIC; + uint256 suffixLength = hasSignature ? _paymasterSignatureSize(self) + 10 : 0; + return + self.paymasterAndData.length < 52 + suffixLength + ? Calldata.emptyBytes() + : self.paymasterAndData[52:self.paymasterAndData.length - suffixLength]; + } + + /** + * @dev Returns the paymaster signature from `paymasterAndData` (EntryPoint v0.9+). + * Returns empty bytes if no paymaster signature is present. + */ + function paymasterSignature(PackedUserOperation calldata self) internal pure returns (bytes calldata) { + if ( + self.paymasterAndData.length < 10 || + bytes8(self.paymasterAndData[self.paymasterAndData.length - 8:]) != PAYMASTER_SIG_MAGIC + ) return Calldata.emptyBytes(); + + uint256 sigSize = _paymasterSignatureSize(self); + uint256 sigEnd = self.paymasterAndData.length - 10; + return + self.paymasterAndData.length < 62 + sigSize + ? Calldata.emptyBytes() + : self.paymasterAndData[sigEnd - sigSize:sigEnd]; + } + + /** + * @dev Returns the size of the paymaster signature in `paymasterAndData` (EntryPoint v0.9+). + * Does not check minimum length of `paymasterAndData`. + */ + function _paymasterSignatureSize(PackedUserOperation calldata self) private pure returns (uint256) { + return + uint16(bytes2(self.paymasterAndData[self.paymasterAndData.length - 10:self.paymasterAndData.length - 8])); } } diff --git a/dependencies/@openzeppelin-contracts-5.5.0/account/utils/draft-ERC7579Utils.sol b/dependencies/@openzeppelin-contracts-5.7.0/account/utils/draft-ERC7579Utils.sol similarity index 96% rename from dependencies/@openzeppelin-contracts-5.5.0/account/utils/draft-ERC7579Utils.sol rename to dependencies/@openzeppelin-contracts-5.7.0/account/utils/draft-ERC7579Utils.sol index 07bd924..3880911 100644 --- a/dependencies/@openzeppelin-contracts-5.5.0/account/utils/draft-ERC7579Utils.sol +++ b/dependencies/@openzeppelin-contracts-5.7.0/account/utils/draft-ERC7579Utils.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -// OpenZeppelin Contracts (last updated v5.5.0) (account/utils/draft-ERC7579Utils.sol) +// OpenZeppelin Contracts (last updated v5.6.0) (account/utils/draft-ERC7579Utils.sol) pragma solidity ^0.8.20; @@ -146,9 +146,9 @@ library ERC7579Utils { function decodeSingle( bytes calldata executionCalldata ) internal pure returns (address target, uint256 value, bytes calldata callData) { - target = address(bytes20(executionCalldata[0x00:0x14])); - value = uint256(bytes32(executionCalldata[0x14:0x34])); - callData = executionCalldata[0x34:]; + target = address(bytes20(executionCalldata)); + value = uint256(bytes32(executionCalldata[20:52])); + callData = executionCalldata[52:]; } /// @dev Encodes a delegate call execution. See {decodeDelegate}. @@ -163,8 +163,8 @@ library ERC7579Utils { function decodeDelegate( bytes calldata executionCalldata ) internal pure returns (address target, bytes calldata callData) { - target = address(bytes20(executionCalldata[0:0x14])); - callData = executionCalldata[0x14:]; + target = address(bytes20(executionCalldata)); + callData = executionCalldata[20:]; } /// @dev Encodes a batch of executions. See {decodeBatch}. diff --git a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/AbstractSigner.json b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/AbstractSigner.json similarity index 100% rename from dependencies/@openzeppelin-contracts-5.5.0/build/contracts/AbstractSigner.json rename to dependencies/@openzeppelin-contracts-5.7.0/build/contracts/AbstractSigner.json diff --git a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/AccessControl.json b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/AccessControl.json similarity index 100% rename from dependencies/@openzeppelin-contracts-5.5.0/build/contracts/AccessControl.json rename to dependencies/@openzeppelin-contracts-5.7.0/build/contracts/AccessControl.json diff --git a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/AccessControlDefaultAdminRules.json b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/AccessControlDefaultAdminRules.json similarity index 100% rename from dependencies/@openzeppelin-contracts-5.5.0/build/contracts/AccessControlDefaultAdminRules.json rename to dependencies/@openzeppelin-contracts-5.7.0/build/contracts/AccessControlDefaultAdminRules.json diff --git a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/AccessControlEnumerable.json b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/AccessControlEnumerable.json similarity index 100% rename from dependencies/@openzeppelin-contracts-5.5.0/build/contracts/AccessControlEnumerable.json rename to dependencies/@openzeppelin-contracts-5.7.0/build/contracts/AccessControlEnumerable.json diff --git a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/AccessManaged.json b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/AccessManaged.json similarity index 100% rename from dependencies/@openzeppelin-contracts-5.5.0/build/contracts/AccessManaged.json rename to dependencies/@openzeppelin-contracts-5.7.0/build/contracts/AccessManaged.json diff --git a/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/AccessManager.json b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/AccessManager.json new file mode 100644 index 0000000..a2f7e93 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/AccessManager.json @@ -0,0 +1,1186 @@ +{ + "_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": "bytes4", + "name": "selector", + "type": "bytes4" + } + ], + "name": "AccessManagerLockedFunction", + "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": "0x608060405234801561000f575f5ffd5b50604051612dcc380380612dcc83398101604081905261002e91610441565b6001600160a01b03811661005c57604051630409d6d160e11b81525f60048201526024015b60405180910390fd5b6100685f82818061006f565b50506104bc565b5f6002600160401b03196001600160401b038616016100ac5760405163061c6a4360e21b81526001600160401b0386166004820152602401610053565b6001600160401b0385165f9081526001602090815260408083206001600160a01b038816845290915281205465ffffffffffff16159081156101a15763ffffffff85166100f76102b5565b6101019190610482565b905060405180604001604052808265ffffffffffff1681526020016101318663ffffffff166102c460201b60201c565b6001600160701b039081169091526001600160401b0389165f9081526001602090815260408083206001600160a01b038c16845282529091208351815494909201519092166601000000000000026001600160a01b031990931665ffffffffffff90911617919091179055610247565b6001600160401b0387165f9081526001602090815260408083206001600160a01b038a1684529091528120546101ed9166010000000000009091046001600160701b03169086906102cd565b6001600160401b0389165f9081526001602090815260408083206001600160a01b038c168452909152902080546001600160701b03909316660100000000000002600160301b600160a01b03199093169290921790915590505b6040805163ffffffff8616815265ffffffffffff831660208201528315158183015290516001600160a01b038816916001600160401b038a16917ff98448b987f1428e0e230e1f3c6e2ce15b5693eaf31827fbd0b1ec4b424ae7cf9181900360600190a35095945050505050565b5f6102bf42610373565b905090565b63ffffffff1690565b5f80806102e26001600160701b0387166103a9565b90505f61031d8563ffffffff168763ffffffff168463ffffffff1611610308575f610312565b61031288856104a0565b63ffffffff166103c7565b905063ffffffff811661032e6102b5565b6103389190610482565b925063ffffffff8616602083901b67ffffffff0000000016604085901b6dffffffffffff000000000000000016171793505050935093915050565b5f65ffffffffffff8211156103a5576040516306dfcc6560e41b81526030600482015260248101839052604401610053565b5090565b5f806103bd6001600160701b0384166103d7565b5090949350505050565b8082118183180281185b92915050565b5f80806103eb846103e66102b5565b6103f8565b9250925092509193909250565b6001600160501b03602083901c166001600160701b03831665ffffffffffff604085901c811690841681111561043057828282610434565b815f5f5b9250925092509250925092565b5f60208284031215610451575f5ffd5b81516001600160a01b0381168114610467575f5ffd5b9392505050565b634e487b7160e01b5f52601160045260245ffd5b65ffffffffffff81811683821601908111156103d1576103d161046e565b63ffffffff82811682821603908111156103d1576103d161046e565b612903806104c95f395ff3fe6080604052600436106101db575f3560e01c80636d5115bd116100fd578063b700961311610092578063d22b598911610062578063d22b598914610636578063d6bb62c614610655578063f801a69814610674578063fe0776f5146106ad575f5ffd5b8063b7009613146105a8578063b7d2b162146105e3578063cc1b6c8114610602578063d1f856ee14610617575f5ffd5b8063a166aa89116100cd578063a166aa8914610501578063a64d95ce14610530578063abd9bd2a1461054f578063ac9650d81461057c575f5ffd5b80636d5115bd1461049157806375b238fc146104b0578063853551b8146104c357806394c7d7ee146104e2575f5ffd5b806330cae187116101735780634665096d116101435780634665096d146104035780634c1da1e2146104185780635296295214610437578063530dd45614610456575f5ffd5b806330cae1871461035c5780633adc277a1461037b5780633ca7c02a146103b15780634136a33c146103cb575f5ffd5b806318ff183c116101ae57806318ff183c146102b25780631cff79cd146102d157806325c471a0146102e45780633078f11414610303575f5ffd5b806308d6122d146101df5780630b0a93ba1461020057806312be87271461025f578063167bd39514610293575b5f5ffd5b3480156101ea575f5ffd5b506101fe6101f93660046121f1565b6106cc565b005b34801561020b575f5ffd5b5061024261021a366004612253565b6001600160401b039081165f9081526001602081905260409091200154600160401b90041690565b6040516001600160401b0390911681526020015b60405180910390f35b34801561026a575f5ffd5b5061027e610279366004612253565b61071e565b60405163ffffffff9091168152602001610256565b34801561029e575f5ffd5b506101fe6102ad36600461226c565b610758565b3480156102bd575f5ffd5b506101fe6102cc3660046122a7565b61076e565b61027e6102df366004612310565b6107d0565b3480156102ef575f5ffd5b506101fe6102fe366004612373565b6108fc565b34801561030e575f5ffd5b5061032261031d3660046123b5565b61091e565b604051610256949392919065ffffffffffff948516815263ffffffff93841660208201529190921660408201529116606082015260800190565b348015610367575f5ffd5b506101fe6103763660046123cf565b610982565b348015610386575f5ffd5b5061039a610395366004612400565b610994565b60405165ffffffffffff9091168152602001610256565b3480156103bc575f5ffd5b506102426001600160401b0381565b3480156103d6575f5ffd5b5061027e6103e5366004612400565b5f90815260026020526040902054600160301b900463ffffffff1690565b34801561040e575f5ffd5b5062093a8061027e565b348015610423575f5ffd5b5061027e610432366004612417565b6109c5565b348015610442575f5ffd5b506101fe6104513660046123cf565b6109f2565b348015610461575f5ffd5b50610242610470366004612253565b6001600160401b039081165f90815260016020819052604090912001541690565b34801561049c575f5ffd5b506102426104ab366004612447565b610a04565b3480156104bb575f5ffd5b506102425f81565b3480156104ce575f5ffd5b506101fe6104dd366004612473565b610a3e565b3480156104ed575f5ffd5b506101fe6104fc366004612310565b610ad5565b34801561050c575f5ffd5b5061052061051b366004612417565b610b7f565b6040519015158152602001610256565b34801561053b575f5ffd5b506101fe61054a36600461248e565b610ba6565b34801561055a575f5ffd5b5061056e6105693660046124b6565b610bb8565b604051908152602001610256565b348015610587575f5ffd5b5061059b610596366004612516565b610bf1565b6040516102569190612554565b3480156105b3575f5ffd5b506105c76105c23660046125d8565b610cd6565b60408051921515835263ffffffff909116602083015201610256565b3480156105ee575f5ffd5b506101fe6105fd3660046123b5565b610dc7565b34801561060d575f5ffd5b506206978061027e565b348015610622575f5ffd5b506105c76106313660046123b5565b610dde565b348015610641575f5ffd5b506101fe610650366004612620565b610e57565b348015610660575f5ffd5b5061027e61066f3660046124b6565b610e69565b34801561067f575f5ffd5b5061069361068e36600461263c565b610f77565b6040805192835263ffffffff909116602083015201610256565b3480156106b8575f5ffd5b506101fe6106c73660046123b5565b6110b8565b6106d46110e1565b5f5b828110156107175761070f858585848181106106f4576106f46126a9565b905060200201602081019061070991906126bd565b84611158565b6001016106d6565b5050505050565b6001600160401b0381165f9081526001602081905260408220015461075290600160801b90046001600160701b0316611216565b92915050565b6107606110e1565b61076a8282611234565b5050565b6107766110e1565b604051637a9e5e4b60e01b81526001600160a01b038281166004830152831690637a9e5e4b906024015f604051808303815f87803b1580156107b6575f5ffd5b505af11580156107c8573d5f5f3e3d5ffd5b505050505050565b5f3381806107e0838888886112a5565b91509150811580156107f6575063ffffffff8116155b1561084957828761080788886112f6565b6040516381c6f24b60e01b81526001600160a01b0393841660048201529290911660248301526001600160e01b03191660448201526064015b60405180910390fd5b5f61085684898989610bb8565b90505f63ffffffff831615158061087c575061087182610994565b65ffffffffffff1615155b1561088d5761088a8261130d565b90505b6003546108a38a61089e8b8b6112f6565b61140b565b6003819055506108ea8a8a8a8080601f0160208091040260200160405190810160405280939291908181526020018383808284375f92019190915250349250611430915050565b506003559450505050505b9392505050565b6109046110e1565b61091883836109128661071e565b846114fc565b50505050565b6001600160401b0382165f9081526001602090815260408083206001600160a01b03851684529091528120805465ffffffffffff81169291829182919061097490600160301b90046001600160701b0316611742565b969991985096509350505050565b61098a6110e1565b61076a8282611763565b5f8181526002602052604081205465ffffffffffff166109b381611806565b6109bd57806108f5565b5f9392505050565b6001600160a01b0381165f90815260208190526040812060010154610752906001600160701b0316611216565b6109fa6110e1565b61076a8282611834565b6001600160a01b0382165f908152602081815260408083206001600160e01b0319851684529091529020546001600160401b031692915050565b610a466110e1565b6001600160401b0383161580610a6457506001600160401b03838116145b15610a8d5760405163061c6a4360e21b81526001600160401b0384166004820152602401610840565b826001600160401b03167f1256f5b5ecb89caec12db449738f2fbcd1ba5806cf38f35413f4e5c15bf6a4508383604051610ac8929190612700565b60405180910390a2505050565b60408051638fb3603760e01b80825291513392918391638fb36037916004808201926020929091908290030181865afa158015610b14573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610b389190612713565b6001600160e01b03191614610b6b57604051630641fee960e31b81526001600160a01b0382166004820152602401610840565b610717610b7a85838686610bb8565b61130d565b6001600160a01b03165f90815260208190526040902060010154600160701b900460ff1690565b610bae6110e1565b61076a82826118e5565b5f84848484604051602001610bd0949392919061272e565b6040516020818303038152906040528051906020012090505b949350505050565b604080515f815260208101909152606090826001600160401b03811115610c1a57610c1a61279f565b604051908082528060200260200182016040528015610c4d57816020015b6060815260200190600190039081610c385790505b5091505f5b83811015610cce57610ca930868684818110610c7057610c706126a9565b9050602002810190610c8291906127b3565b85604051602001610c95939291906127f5565b6040516020818303038152906040526119f4565b838281518110610cbb57610cbb6126a9565b6020908102919091010152600101610c52565b505092915050565b5f5f610ce184610b7f565b15610cf057505f905080610dbf565b306001600160a01b03861603610d1457610d0a8484611a76565b5f91509150610dbf565b638561a1b560e01b6001600160e01b0319841601610d84575f5f610d385f88610dde565b915091505f610d46876109c5565b90505f610d5f8363ffffffff168363ffffffff16611a8c565b905083610d6d575f5f610d77565b63ffffffff811615815b9550955050505050610dbf565b5f610d8f8585610a04565b90505f5f610d9d8389610dde565b9150915081610dad575f5f610db7565b63ffffffff811615815b945094505050505b935093915050565b610dcf6110e1565b610dd98282611a9b565b505050565b5f8067fffffffffffffffe196001600160401b03851601610e045750600190505f610e50565b5f5f610e10868661091e565b5050915091508165ffffffffffff165f14158015610e455750610e31611b84565b65ffffffffffff168265ffffffffffff1611155b93509150610e509050565b9250929050565b610e5f6110e1565b61076a8282611b93565b5f3381610e7685856112f6565b90505f610e8588888888610bb8565b5f8181526002602052604081205491925065ffffffffffff9091169003610ec25760405163060a299b60e41b815260048101829052602401610840565b610ece88888888611c4e565b610f1657604051630ff89d4760e21b81526001600160a01b038085166004830152808a166024830152881660448201526001600160e01b031983166064820152608401610840565b5f81815260026020526040808220805465ffffffffffff1916908190559051600160301b90910463ffffffff1691829184917fbd9ac67a6e2f6463b80927326310338bcbb4bdb7936ce1365ea3e01067e7b9f791a398975050505050505050565b5f803381610f87828989896112a5565b9150505f8163ffffffff16610f9a611b84565b610fa49190612818565b905063ffffffff82161580610fda57505f8665ffffffffffff16118015610fda57508065ffffffffffff168665ffffffffffff16105b15610feb5782896108078a8a6112f6565b6110058665ffffffffffff168265ffffffffffff16611a8c565b9550611013838a8a8a610bb8565b945061101e85611d16565b5f8581526002602052604090819020805465ffffffffffff891669ffffffffffffffffffff19821617600160301b9182900463ffffffff90811660010190811692830291909117909255915190955086907f82a2da5dee54ea8021c6545b4444620291e07ee83be6dd57edb175062715f3b4906110a4908a9088908f908f908f90612836565b60405180910390a350505094509492505050565b6001600160a01b0381163314610dcf57604051635f159e6360e01b815260040160405180910390fd5b335f806110ef838236611d62565b9150915081610dd9578063ffffffff165f03611149575f6111108136611e25565b5060405163f07e038f60e01b81526001600160a01b03871660048201526001600160401b03821660248201529092506044019050610840565b610918610b7a84305f36610bb8565b638561a1b560e01b6001600160e01b031983160161119557604051637a3a272560e11b81526001600160e01b031983166004820152602401610840565b6001600160a01b0383165f818152602081815260408083206001600160e01b0319871680855290835292819020805467ffffffffffffffff19166001600160401b038716908117909155905192835292917f9ea6790c7dadfd01c9f8b9762b3682607af2c7e79e05a9f9fdf5580dde949151910160405180910390a3505050565b5f5f61122a836001600160701b0316611742565b5090949350505050565b6001600160a01b0382165f81815260208190526040908190206001018054841515600160701b0260ff60701b19909116179055517f90d4e7bb7e5d933792b3562e1741306f8be94837e1348dacef9b6f1df56eb1389061129990841515815260200190565b60405180910390a25050565b5f80306001600160a01b038616036112cb576112c2868585611d62565b915091506112ed565b600483106112e7576112e286866105c287876112f6565b6112c2565b505f9050805b94509492505050565b5f6113046004828486612778565b6108f59161287b565b5f8181526002602052604081205465ffffffffffff811690600160301b900463ffffffff168183036113555760405163060a299b60e41b815260048101859052602401610840565b61135d611b84565b65ffffffffffff168265ffffffffffff16111561139057604051630c65b5bd60e11b815260048101859052602401610840565b61139982611806565b156113ba57604051631e2975b960e21b815260048101859052602401610840565b5f84815260026020526040808220805465ffffffffffff191690555163ffffffff83169186917f76a2a46953689d4861a5d3f6ed883ad7e6af674a21f8e162707159fc9dde614d9190a39392505050565b6001600160a01b0382165f9081526001600160e01b03198216602052604081206108f5565b60608147101561145c5760405163cf47918160e01b815247600482015260248101839052604401610840565b5f61146885848661200b565b905080801561148957505f3d118061148957505f856001600160a01b03163b115b1561149e57611496612020565b9150506108f5565b80156114c857604051639996b31560e01b81526001600160a01b0386166004820152602401610840565b3d156114db576114d6612039565b6114f4565b60405163d6bda27560e01b815260040160405180910390fd5b509392505050565b5f67fffffffffffffffe196001600160401b0386160161153a5760405163061c6a4360e21b81526001600160401b0386166004820152602401610840565b6001600160401b0385165f9081526001602090815260408083206001600160a01b038816845290915281205465ffffffffffff161590811561162a578463ffffffff16611585611b84565b61158f9190612818565b905060405180604001604052808265ffffffffffff1681526020016115bd8663ffffffff1663ffffffff1690565b6001600160701b039081169091526001600160401b0389165f9081526001602090815260408083206001600160a01b038c1684528252909120835181549490920151909216600160301b026001600160a01b031990931665ffffffffffff909116179190911790556116d4565b6001600160401b0387165f9081526001602090815260408083206001600160a01b038a16845290915281205461167391600160301b9091046001600160701b0316908690612044565b6001600160401b0389165f9081526001602090815260408083206001600160a01b038c168452909152902080546001600160701b03909316600160301b0273ffffffffffffffffffffffffffff000000000000199093169290921790915590505b6040805163ffffffff8616815265ffffffffffff831660208201528315158183015290516001600160a01b038816916001600160401b038a16917ff98448b987f1428e0e230e1f3c6e2ce15b5693eaf31827fbd0b1ec4b424ae7cf9181900360600190a35095945050505050565b5f5f5f61175684611751611b84565b6120ea565b9250925092509193909250565b6001600160401b038216158061178157506001600160401b03828116145b156117aa5760405163061c6a4360e21b81526001600160401b0383166004820152602401610840565b6001600160401b038281165f818152600160208190526040808320909101805467ffffffffffffffff19169486169485179055517f1fd6dd7631312dfac2205b52913f99de03b4d7e381d5d27d3dbfe0713e6e63409190a35050565b5f61180f611b84565b65ffffffffffff1661182462093a8084612818565b65ffffffffffff16111592915050565b6001600160401b038216158061185257506001600160401b03828116145b1561187b5760405163061c6a4360e21b81526001600160401b0383166004820152602401610840565b6001600160401b038281165f81815260016020819052604080832090910180546fffffffffffffffff00000000000000001916600160401b958716958602179055517f7a8059630b897b5de4c08ade69f8b90c3ead1f8596d62d10b6c4d14a0afb4ae29190a35050565b67fffffffffffffffe196001600160401b038316016119225760405163061c6a4360e21b81526001600160401b0383166004820152602401610840565b6001600160401b0382165f9081526001602081905260408220015461195b90600160801b90046001600160701b03168362069780612044565b6001600160401b0385165f818152600160208190526040918290200180546001600160701b03909516600160801b026dffffffffffffffffffffffffffff60801b199095169490941790935591519092507ffeb69018ee8b8fd50ea86348f1267d07673379f72cffdeccec63853ee8ce8b4890610ac8908590859063ffffffff92909216825265ffffffffffff16602082015260400190565b60605f611a018484612136565b9050808015611a2257505f3d1180611a2257505f846001600160a01b03163b115b15611a3757611a2f612020565b915050610752565b8015611a6157604051639996b31560e01b81526001600160a01b0385166004820152602401610840565b3d156114db57611a6f612039565b5092915050565b5f611a81838361140b565b600354149392505050565b5f8282188284110282186108f5565b5f67fffffffffffffffe196001600160401b03841601611ad95760405163061c6a4360e21b81526001600160401b0384166004820152602401610840565b6001600160401b0383165f9081526001602090815260408083206001600160a01b038616845290915281205465ffffffffffff169003611b1a57505f610752565b6001600160401b0383165f8181526001602090815260408083206001600160a01b038716808552925280832080546001600160a01b0319169055519092917ff229baa593af28c41b1d16b748cd7688f0c83aaf92d4be41c44005defe84c16691a350600192915050565b5f611b8e42612149565b905090565b6001600160a01b0382165f90815260208190526040812060010154611bc5906001600160701b03168362069780612044565b6001600160a01b0385165f818152602081815260409182902060010180546dffffffffffffffffffffffffffff19166001600160701b039690961695909517909455805163ffffffff8716815265ffffffffffff841694810194909452919350917fa56b76017453f399ec2327ba00375dbfb1fd070ff854341ad6191e6a2e2de19c9101610ac8565b5f336001600160a01b038616819003611c6b576001915050610be9565b5f611c765f83610dde565b5090505f611c94611c8e61021a896104ab8a8a6112f6565b84610dde565b5090508180611ca05750805b15611cb15760019350505050610be9565b306001600160a01b03881603611d09575f5f611ccd8888611e25565b5091509150818015611ce757506001600160401b03811615155b15611d06575f611cf78287610dde565b509650610be995505050505050565b50505b505f979650505050505050565b5f8181526002602052604090205465ffffffffffff168015801590611d415750611d3f81611806565b155b1561076a5760405163813e945960e01b815260048101839052602401610840565b5f806004831015611d7757505f905080610dbf565b306001600160a01b03861603611d9a57610d0a30611d9586866112f6565b611a76565b5f5f5f611da78787611e25565b92509250925082158015611dbf5750611dbf30610b7f565b15611dd2575f5f94509450505050610dbf565b5f5f611dde848b610dde565b9150915081611df7575f5f965096505050505050610dbf565b611e0d8363ffffffff168263ffffffff16611a8c565b63ffffffff8116159b909a5098505050505050505050565b5f80806004841015611e3e57505f915081905080612004565b5f611e4986866112f6565b90506001600160e01b031981166310a6aa3760e31b1480611e7a57506001600160e01b031981166330cae18760e01b145b80611e9557506001600160e01b0319811663294b14a960e11b145b80611eb057506001600160e01b03198116635326cae760e11b145b80611ecb57506001600160e01b0319811663d22b598960e01b145b15611ee05760015f5f93509350935050612004565b6001600160e01b0319811663063fc60f60e21b1480611f0f57506001600160e01b0319811663167bd39560e01b145b80611f2a57506001600160e01b031981166308d6122d60e01b145b15611f69575f611f3e60246004888a612778565b810190611f4b9190612417565b90505f611f57826109c5565b600196505f9550935061200492505050565b6001600160e01b0319811663012e238d60e51b1480611f9857506001600160e01b03198116635be958b160e11b145b15611ff0575f611fac60246004888a612778565b810190611fb99190612253565b90506001611fe2826001600160401b039081165f90815260016020819052604090912001541690565b5f9450945094505050612004565b5f611ffb3083610a04565b5f935093509350505b9250925092565b5f5f5f83516020850186885af1949350505050565b6040513d81523d5f602083013e3d602001810160405290565b6040513d5f823e3d81fd5b5f5f5f612059866001600160701b0316611216565b90505f6120948563ffffffff168763ffffffff168463ffffffff161161207f575f612089565b61208988856128b1565b63ffffffff16611a8c565b90508063ffffffff166120a5611b84565b6120af9190612818565b925063ffffffff8616602083901b67ffffffff0000000016604085901b6dffffffffffff000000000000000016171793505050935093915050565b69ffffffffffffffffffff602083901c166001600160701b03831665ffffffffffff604085901c811690841681111561212557828282612129565b815f5f5b9250925092509250925092565b5f5f5f835160208501865af49392505050565b5f65ffffffffffff82111561217b576040516306dfcc6560e41b81526030600482015260248101839052604401610840565b5090565b6001600160a01b0381168114612193575f5ffd5b50565b5f5f83601f8401126121a6575f5ffd5b5081356001600160401b038111156121bc575f5ffd5b6020830191508360208260051b8501011115610e50575f5ffd5b80356001600160401b03811681146121ec575f5ffd5b919050565b5f5f5f5f60608587031215612204575f5ffd5b843561220f8161217f565b935060208501356001600160401b03811115612229575f5ffd5b61223587828801612196565b90945092506122489050604086016121d6565b905092959194509250565b5f60208284031215612263575f5ffd5b6108f5826121d6565b5f5f6040838503121561227d575f5ffd5b82356122888161217f565b91506020830135801515811461229c575f5ffd5b809150509250929050565b5f5f604083850312156122b8575f5ffd5b82356122c38161217f565b9150602083013561229c8161217f565b5f5f83601f8401126122e3575f5ffd5b5081356001600160401b038111156122f9575f5ffd5b602083019150836020828501011115610e50575f5ffd5b5f5f5f60408486031215612322575f5ffd5b833561232d8161217f565b925060208401356001600160401b03811115612347575f5ffd5b612353868287016122d3565b9497909650939450505050565b803563ffffffff811681146121ec575f5ffd5b5f5f5f60608486031215612385575f5ffd5b61238e846121d6565b9250602084013561239e8161217f565b91506123ac60408501612360565b90509250925092565b5f5f604083850312156123c6575f5ffd5b6122c3836121d6565b5f5f604083850312156123e0575f5ffd5b6123e9836121d6565b91506123f7602084016121d6565b90509250929050565b5f60208284031215612410575f5ffd5b5035919050565b5f60208284031215612427575f5ffd5b81356108f58161217f565b6001600160e01b031981168114612193575f5ffd5b5f5f60408385031215612458575f5ffd5b82356124638161217f565b9150602083013561229c81612432565b5f5f5f60408486031215612485575f5ffd5b61232d846121d6565b5f5f6040838503121561249f575f5ffd5b6124a8836121d6565b91506123f760208401612360565b5f5f5f5f606085870312156124c9575f5ffd5b84356124d48161217f565b935060208501356124e48161217f565b925060408501356001600160401b038111156124fe575f5ffd5b61250a878288016122d3565b95989497509550505050565b5f5f60208385031215612527575f5ffd5b82356001600160401b0381111561253c575f5ffd5b61254885828601612196565b90969095509350505050565b5f602082016020835280845180835260408501915060408160051b8601019250602086015f5b828110156125cc57603f19878603018452815180518087528060208301602089015e5f602082890101526020601f19601f8301168801019650505060208201915060208401935060018101905061257a565b50929695505050505050565b5f5f5f606084860312156125ea575f5ffd5b83356125f58161217f565b925060208401356126058161217f565b9150604084013561261581612432565b809150509250925092565b5f5f60408385031215612631575f5ffd5b82356124a88161217f565b5f5f5f5f6060858703121561264f575f5ffd5b843561265a8161217f565b935060208501356001600160401b03811115612674575f5ffd5b612680878288016122d3565b909450925050604085013565ffffffffffff8116811461269e575f5ffd5b939692955090935050565b634e487b7160e01b5f52603260045260245ffd5b5f602082840312156126cd575f5ffd5b81356108f581612432565b81835281816020850137505f828201602090810191909152601f909101601f19169091010190565b602081525f610be96020830184866126d8565b5f60208284031215612723575f5ffd5b81516108f581612432565b6001600160a01b038581168252841660208201526060604082018190525f9061275a90830184866126d8565b9695505050505050565b634e487b7160e01b5f52601160045260245ffd5b5f5f85851115612786575f5ffd5b83861115612792575f5ffd5b5050820193919092039150565b634e487b7160e01b5f52604160045260245ffd5b5f5f8335601e198436030181126127c8575f5ffd5b8301803591506001600160401b038211156127e1575f5ffd5b602001915036819003821315610e50575f5ffd5b828482375f8382015f815283518060208601835e5f910190815295945050505050565b65ffffffffffff818116838216019081111561075257610752612764565b65ffffffffffff861681526001600160a01b038581166020830152841660408201526080606082018190525f9061287090830184866126d8565b979650505050505050565b80356001600160e01b03198116906004841015611a6f576001600160e01b031960049490940360031b84901b1690921692915050565b63ffffffff82811682821603908111156107525761075261276456fea2646970667358221220a5f2a31bcab50ad1bf1dd7265dea5d3d16300eeb1d8024eaa29875390032ca7764736f6c63430008230033", + "deployedBytecode": "0x6080604052600436106101db575f3560e01c80636d5115bd116100fd578063b700961311610092578063d22b598911610062578063d22b598914610636578063d6bb62c614610655578063f801a69814610674578063fe0776f5146106ad575f5ffd5b8063b7009613146105a8578063b7d2b162146105e3578063cc1b6c8114610602578063d1f856ee14610617575f5ffd5b8063a166aa89116100cd578063a166aa8914610501578063a64d95ce14610530578063abd9bd2a1461054f578063ac9650d81461057c575f5ffd5b80636d5115bd1461049157806375b238fc146104b0578063853551b8146104c357806394c7d7ee146104e2575f5ffd5b806330cae187116101735780634665096d116101435780634665096d146104035780634c1da1e2146104185780635296295214610437578063530dd45614610456575f5ffd5b806330cae1871461035c5780633adc277a1461037b5780633ca7c02a146103b15780634136a33c146103cb575f5ffd5b806318ff183c116101ae57806318ff183c146102b25780631cff79cd146102d157806325c471a0146102e45780633078f11414610303575f5ffd5b806308d6122d146101df5780630b0a93ba1461020057806312be87271461025f578063167bd39514610293575b5f5ffd5b3480156101ea575f5ffd5b506101fe6101f93660046121f1565b6106cc565b005b34801561020b575f5ffd5b5061024261021a366004612253565b6001600160401b039081165f9081526001602081905260409091200154600160401b90041690565b6040516001600160401b0390911681526020015b60405180910390f35b34801561026a575f5ffd5b5061027e610279366004612253565b61071e565b60405163ffffffff9091168152602001610256565b34801561029e575f5ffd5b506101fe6102ad36600461226c565b610758565b3480156102bd575f5ffd5b506101fe6102cc3660046122a7565b61076e565b61027e6102df366004612310565b6107d0565b3480156102ef575f5ffd5b506101fe6102fe366004612373565b6108fc565b34801561030e575f5ffd5b5061032261031d3660046123b5565b61091e565b604051610256949392919065ffffffffffff948516815263ffffffff93841660208201529190921660408201529116606082015260800190565b348015610367575f5ffd5b506101fe6103763660046123cf565b610982565b348015610386575f5ffd5b5061039a610395366004612400565b610994565b60405165ffffffffffff9091168152602001610256565b3480156103bc575f5ffd5b506102426001600160401b0381565b3480156103d6575f5ffd5b5061027e6103e5366004612400565b5f90815260026020526040902054600160301b900463ffffffff1690565b34801561040e575f5ffd5b5062093a8061027e565b348015610423575f5ffd5b5061027e610432366004612417565b6109c5565b348015610442575f5ffd5b506101fe6104513660046123cf565b6109f2565b348015610461575f5ffd5b50610242610470366004612253565b6001600160401b039081165f90815260016020819052604090912001541690565b34801561049c575f5ffd5b506102426104ab366004612447565b610a04565b3480156104bb575f5ffd5b506102425f81565b3480156104ce575f5ffd5b506101fe6104dd366004612473565b610a3e565b3480156104ed575f5ffd5b506101fe6104fc366004612310565b610ad5565b34801561050c575f5ffd5b5061052061051b366004612417565b610b7f565b6040519015158152602001610256565b34801561053b575f5ffd5b506101fe61054a36600461248e565b610ba6565b34801561055a575f5ffd5b5061056e6105693660046124b6565b610bb8565b604051908152602001610256565b348015610587575f5ffd5b5061059b610596366004612516565b610bf1565b6040516102569190612554565b3480156105b3575f5ffd5b506105c76105c23660046125d8565b610cd6565b60408051921515835263ffffffff909116602083015201610256565b3480156105ee575f5ffd5b506101fe6105fd3660046123b5565b610dc7565b34801561060d575f5ffd5b506206978061027e565b348015610622575f5ffd5b506105c76106313660046123b5565b610dde565b348015610641575f5ffd5b506101fe610650366004612620565b610e57565b348015610660575f5ffd5b5061027e61066f3660046124b6565b610e69565b34801561067f575f5ffd5b5061069361068e36600461263c565b610f77565b6040805192835263ffffffff909116602083015201610256565b3480156106b8575f5ffd5b506101fe6106c73660046123b5565b6110b8565b6106d46110e1565b5f5b828110156107175761070f858585848181106106f4576106f46126a9565b905060200201602081019061070991906126bd565b84611158565b6001016106d6565b5050505050565b6001600160401b0381165f9081526001602081905260408220015461075290600160801b90046001600160701b0316611216565b92915050565b6107606110e1565b61076a8282611234565b5050565b6107766110e1565b604051637a9e5e4b60e01b81526001600160a01b038281166004830152831690637a9e5e4b906024015f604051808303815f87803b1580156107b6575f5ffd5b505af11580156107c8573d5f5f3e3d5ffd5b505050505050565b5f3381806107e0838888886112a5565b91509150811580156107f6575063ffffffff8116155b1561084957828761080788886112f6565b6040516381c6f24b60e01b81526001600160a01b0393841660048201529290911660248301526001600160e01b03191660448201526064015b60405180910390fd5b5f61085684898989610bb8565b90505f63ffffffff831615158061087c575061087182610994565b65ffffffffffff1615155b1561088d5761088a8261130d565b90505b6003546108a38a61089e8b8b6112f6565b61140b565b6003819055506108ea8a8a8a8080601f0160208091040260200160405190810160405280939291908181526020018383808284375f92019190915250349250611430915050565b506003559450505050505b9392505050565b6109046110e1565b61091883836109128661071e565b846114fc565b50505050565b6001600160401b0382165f9081526001602090815260408083206001600160a01b03851684529091528120805465ffffffffffff81169291829182919061097490600160301b90046001600160701b0316611742565b969991985096509350505050565b61098a6110e1565b61076a8282611763565b5f8181526002602052604081205465ffffffffffff166109b381611806565b6109bd57806108f5565b5f9392505050565b6001600160a01b0381165f90815260208190526040812060010154610752906001600160701b0316611216565b6109fa6110e1565b61076a8282611834565b6001600160a01b0382165f908152602081815260408083206001600160e01b0319851684529091529020546001600160401b031692915050565b610a466110e1565b6001600160401b0383161580610a6457506001600160401b03838116145b15610a8d5760405163061c6a4360e21b81526001600160401b0384166004820152602401610840565b826001600160401b03167f1256f5b5ecb89caec12db449738f2fbcd1ba5806cf38f35413f4e5c15bf6a4508383604051610ac8929190612700565b60405180910390a2505050565b60408051638fb3603760e01b80825291513392918391638fb36037916004808201926020929091908290030181865afa158015610b14573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610b389190612713565b6001600160e01b03191614610b6b57604051630641fee960e31b81526001600160a01b0382166004820152602401610840565b610717610b7a85838686610bb8565b61130d565b6001600160a01b03165f90815260208190526040902060010154600160701b900460ff1690565b610bae6110e1565b61076a82826118e5565b5f84848484604051602001610bd0949392919061272e565b6040516020818303038152906040528051906020012090505b949350505050565b604080515f815260208101909152606090826001600160401b03811115610c1a57610c1a61279f565b604051908082528060200260200182016040528015610c4d57816020015b6060815260200190600190039081610c385790505b5091505f5b83811015610cce57610ca930868684818110610c7057610c706126a9565b9050602002810190610c8291906127b3565b85604051602001610c95939291906127f5565b6040516020818303038152906040526119f4565b838281518110610cbb57610cbb6126a9565b6020908102919091010152600101610c52565b505092915050565b5f5f610ce184610b7f565b15610cf057505f905080610dbf565b306001600160a01b03861603610d1457610d0a8484611a76565b5f91509150610dbf565b638561a1b560e01b6001600160e01b0319841601610d84575f5f610d385f88610dde565b915091505f610d46876109c5565b90505f610d5f8363ffffffff168363ffffffff16611a8c565b905083610d6d575f5f610d77565b63ffffffff811615815b9550955050505050610dbf565b5f610d8f8585610a04565b90505f5f610d9d8389610dde565b9150915081610dad575f5f610db7565b63ffffffff811615815b945094505050505b935093915050565b610dcf6110e1565b610dd98282611a9b565b505050565b5f8067fffffffffffffffe196001600160401b03851601610e045750600190505f610e50565b5f5f610e10868661091e565b5050915091508165ffffffffffff165f14158015610e455750610e31611b84565b65ffffffffffff168265ffffffffffff1611155b93509150610e509050565b9250929050565b610e5f6110e1565b61076a8282611b93565b5f3381610e7685856112f6565b90505f610e8588888888610bb8565b5f8181526002602052604081205491925065ffffffffffff9091169003610ec25760405163060a299b60e41b815260048101829052602401610840565b610ece88888888611c4e565b610f1657604051630ff89d4760e21b81526001600160a01b038085166004830152808a166024830152881660448201526001600160e01b031983166064820152608401610840565b5f81815260026020526040808220805465ffffffffffff1916908190559051600160301b90910463ffffffff1691829184917fbd9ac67a6e2f6463b80927326310338bcbb4bdb7936ce1365ea3e01067e7b9f791a398975050505050505050565b5f803381610f87828989896112a5565b9150505f8163ffffffff16610f9a611b84565b610fa49190612818565b905063ffffffff82161580610fda57505f8665ffffffffffff16118015610fda57508065ffffffffffff168665ffffffffffff16105b15610feb5782896108078a8a6112f6565b6110058665ffffffffffff168265ffffffffffff16611a8c565b9550611013838a8a8a610bb8565b945061101e85611d16565b5f8581526002602052604090819020805465ffffffffffff891669ffffffffffffffffffff19821617600160301b9182900463ffffffff90811660010190811692830291909117909255915190955086907f82a2da5dee54ea8021c6545b4444620291e07ee83be6dd57edb175062715f3b4906110a4908a9088908f908f908f90612836565b60405180910390a350505094509492505050565b6001600160a01b0381163314610dcf57604051635f159e6360e01b815260040160405180910390fd5b335f806110ef838236611d62565b9150915081610dd9578063ffffffff165f03611149575f6111108136611e25565b5060405163f07e038f60e01b81526001600160a01b03871660048201526001600160401b03821660248201529092506044019050610840565b610918610b7a84305f36610bb8565b638561a1b560e01b6001600160e01b031983160161119557604051637a3a272560e11b81526001600160e01b031983166004820152602401610840565b6001600160a01b0383165f818152602081815260408083206001600160e01b0319871680855290835292819020805467ffffffffffffffff19166001600160401b038716908117909155905192835292917f9ea6790c7dadfd01c9f8b9762b3682607af2c7e79e05a9f9fdf5580dde949151910160405180910390a3505050565b5f5f61122a836001600160701b0316611742565b5090949350505050565b6001600160a01b0382165f81815260208190526040908190206001018054841515600160701b0260ff60701b19909116179055517f90d4e7bb7e5d933792b3562e1741306f8be94837e1348dacef9b6f1df56eb1389061129990841515815260200190565b60405180910390a25050565b5f80306001600160a01b038616036112cb576112c2868585611d62565b915091506112ed565b600483106112e7576112e286866105c287876112f6565b6112c2565b505f9050805b94509492505050565b5f6113046004828486612778565b6108f59161287b565b5f8181526002602052604081205465ffffffffffff811690600160301b900463ffffffff168183036113555760405163060a299b60e41b815260048101859052602401610840565b61135d611b84565b65ffffffffffff168265ffffffffffff16111561139057604051630c65b5bd60e11b815260048101859052602401610840565b61139982611806565b156113ba57604051631e2975b960e21b815260048101859052602401610840565b5f84815260026020526040808220805465ffffffffffff191690555163ffffffff83169186917f76a2a46953689d4861a5d3f6ed883ad7e6af674a21f8e162707159fc9dde614d9190a39392505050565b6001600160a01b0382165f9081526001600160e01b03198216602052604081206108f5565b60608147101561145c5760405163cf47918160e01b815247600482015260248101839052604401610840565b5f61146885848661200b565b905080801561148957505f3d118061148957505f856001600160a01b03163b115b1561149e57611496612020565b9150506108f5565b80156114c857604051639996b31560e01b81526001600160a01b0386166004820152602401610840565b3d156114db576114d6612039565b6114f4565b60405163d6bda27560e01b815260040160405180910390fd5b509392505050565b5f67fffffffffffffffe196001600160401b0386160161153a5760405163061c6a4360e21b81526001600160401b0386166004820152602401610840565b6001600160401b0385165f9081526001602090815260408083206001600160a01b038816845290915281205465ffffffffffff161590811561162a578463ffffffff16611585611b84565b61158f9190612818565b905060405180604001604052808265ffffffffffff1681526020016115bd8663ffffffff1663ffffffff1690565b6001600160701b039081169091526001600160401b0389165f9081526001602090815260408083206001600160a01b038c1684528252909120835181549490920151909216600160301b026001600160a01b031990931665ffffffffffff909116179190911790556116d4565b6001600160401b0387165f9081526001602090815260408083206001600160a01b038a16845290915281205461167391600160301b9091046001600160701b0316908690612044565b6001600160401b0389165f9081526001602090815260408083206001600160a01b038c168452909152902080546001600160701b03909316600160301b0273ffffffffffffffffffffffffffff000000000000199093169290921790915590505b6040805163ffffffff8616815265ffffffffffff831660208201528315158183015290516001600160a01b038816916001600160401b038a16917ff98448b987f1428e0e230e1f3c6e2ce15b5693eaf31827fbd0b1ec4b424ae7cf9181900360600190a35095945050505050565b5f5f5f61175684611751611b84565b6120ea565b9250925092509193909250565b6001600160401b038216158061178157506001600160401b03828116145b156117aa5760405163061c6a4360e21b81526001600160401b0383166004820152602401610840565b6001600160401b038281165f818152600160208190526040808320909101805467ffffffffffffffff19169486169485179055517f1fd6dd7631312dfac2205b52913f99de03b4d7e381d5d27d3dbfe0713e6e63409190a35050565b5f61180f611b84565b65ffffffffffff1661182462093a8084612818565b65ffffffffffff16111592915050565b6001600160401b038216158061185257506001600160401b03828116145b1561187b5760405163061c6a4360e21b81526001600160401b0383166004820152602401610840565b6001600160401b038281165f81815260016020819052604080832090910180546fffffffffffffffff00000000000000001916600160401b958716958602179055517f7a8059630b897b5de4c08ade69f8b90c3ead1f8596d62d10b6c4d14a0afb4ae29190a35050565b67fffffffffffffffe196001600160401b038316016119225760405163061c6a4360e21b81526001600160401b0383166004820152602401610840565b6001600160401b0382165f9081526001602081905260408220015461195b90600160801b90046001600160701b03168362069780612044565b6001600160401b0385165f818152600160208190526040918290200180546001600160701b03909516600160801b026dffffffffffffffffffffffffffff60801b199095169490941790935591519092507ffeb69018ee8b8fd50ea86348f1267d07673379f72cffdeccec63853ee8ce8b4890610ac8908590859063ffffffff92909216825265ffffffffffff16602082015260400190565b60605f611a018484612136565b9050808015611a2257505f3d1180611a2257505f846001600160a01b03163b115b15611a3757611a2f612020565b915050610752565b8015611a6157604051639996b31560e01b81526001600160a01b0385166004820152602401610840565b3d156114db57611a6f612039565b5092915050565b5f611a81838361140b565b600354149392505050565b5f8282188284110282186108f5565b5f67fffffffffffffffe196001600160401b03841601611ad95760405163061c6a4360e21b81526001600160401b0384166004820152602401610840565b6001600160401b0383165f9081526001602090815260408083206001600160a01b038616845290915281205465ffffffffffff169003611b1a57505f610752565b6001600160401b0383165f8181526001602090815260408083206001600160a01b038716808552925280832080546001600160a01b0319169055519092917ff229baa593af28c41b1d16b748cd7688f0c83aaf92d4be41c44005defe84c16691a350600192915050565b5f611b8e42612149565b905090565b6001600160a01b0382165f90815260208190526040812060010154611bc5906001600160701b03168362069780612044565b6001600160a01b0385165f818152602081815260409182902060010180546dffffffffffffffffffffffffffff19166001600160701b039690961695909517909455805163ffffffff8716815265ffffffffffff841694810194909452919350917fa56b76017453f399ec2327ba00375dbfb1fd070ff854341ad6191e6a2e2de19c9101610ac8565b5f336001600160a01b038616819003611c6b576001915050610be9565b5f611c765f83610dde565b5090505f611c94611c8e61021a896104ab8a8a6112f6565b84610dde565b5090508180611ca05750805b15611cb15760019350505050610be9565b306001600160a01b03881603611d09575f5f611ccd8888611e25565b5091509150818015611ce757506001600160401b03811615155b15611d06575f611cf78287610dde565b509650610be995505050505050565b50505b505f979650505050505050565b5f8181526002602052604090205465ffffffffffff168015801590611d415750611d3f81611806565b155b1561076a5760405163813e945960e01b815260048101839052602401610840565b5f806004831015611d7757505f905080610dbf565b306001600160a01b03861603611d9a57610d0a30611d9586866112f6565b611a76565b5f5f5f611da78787611e25565b92509250925082158015611dbf5750611dbf30610b7f565b15611dd2575f5f94509450505050610dbf565b5f5f611dde848b610dde565b9150915081611df7575f5f965096505050505050610dbf565b611e0d8363ffffffff168263ffffffff16611a8c565b63ffffffff8116159b909a5098505050505050505050565b5f80806004841015611e3e57505f915081905080612004565b5f611e4986866112f6565b90506001600160e01b031981166310a6aa3760e31b1480611e7a57506001600160e01b031981166330cae18760e01b145b80611e9557506001600160e01b0319811663294b14a960e11b145b80611eb057506001600160e01b03198116635326cae760e11b145b80611ecb57506001600160e01b0319811663d22b598960e01b145b15611ee05760015f5f93509350935050612004565b6001600160e01b0319811663063fc60f60e21b1480611f0f57506001600160e01b0319811663167bd39560e01b145b80611f2a57506001600160e01b031981166308d6122d60e01b145b15611f69575f611f3e60246004888a612778565b810190611f4b9190612417565b90505f611f57826109c5565b600196505f9550935061200492505050565b6001600160e01b0319811663012e238d60e51b1480611f9857506001600160e01b03198116635be958b160e11b145b15611ff0575f611fac60246004888a612778565b810190611fb99190612253565b90506001611fe2826001600160401b039081165f90815260016020819052604090912001541690565b5f9450945094505050612004565b5f611ffb3083610a04565b5f935093509350505b9250925092565b5f5f5f83516020850186885af1949350505050565b6040513d81523d5f602083013e3d602001810160405290565b6040513d5f823e3d81fd5b5f5f5f612059866001600160701b0316611216565b90505f6120948563ffffffff168763ffffffff168463ffffffff161161207f575f612089565b61208988856128b1565b63ffffffff16611a8c565b90508063ffffffff166120a5611b84565b6120af9190612818565b925063ffffffff8616602083901b67ffffffff0000000016604085901b6dffffffffffff000000000000000016171793505050935093915050565b69ffffffffffffffffffff602083901c166001600160701b03831665ffffffffffff604085901c811690841681111561212557828282612129565b815f5f5b9250925092509250925092565b5f5f5f835160208501865af49392505050565b5f65ffffffffffff82111561217b576040516306dfcc6560e41b81526030600482015260248101839052604401610840565b5090565b6001600160a01b0381168114612193575f5ffd5b50565b5f5f83601f8401126121a6575f5ffd5b5081356001600160401b038111156121bc575f5ffd5b6020830191508360208260051b8501011115610e50575f5ffd5b80356001600160401b03811681146121ec575f5ffd5b919050565b5f5f5f5f60608587031215612204575f5ffd5b843561220f8161217f565b935060208501356001600160401b03811115612229575f5ffd5b61223587828801612196565b90945092506122489050604086016121d6565b905092959194509250565b5f60208284031215612263575f5ffd5b6108f5826121d6565b5f5f6040838503121561227d575f5ffd5b82356122888161217f565b91506020830135801515811461229c575f5ffd5b809150509250929050565b5f5f604083850312156122b8575f5ffd5b82356122c38161217f565b9150602083013561229c8161217f565b5f5f83601f8401126122e3575f5ffd5b5081356001600160401b038111156122f9575f5ffd5b602083019150836020828501011115610e50575f5ffd5b5f5f5f60408486031215612322575f5ffd5b833561232d8161217f565b925060208401356001600160401b03811115612347575f5ffd5b612353868287016122d3565b9497909650939450505050565b803563ffffffff811681146121ec575f5ffd5b5f5f5f60608486031215612385575f5ffd5b61238e846121d6565b9250602084013561239e8161217f565b91506123ac60408501612360565b90509250925092565b5f5f604083850312156123c6575f5ffd5b6122c3836121d6565b5f5f604083850312156123e0575f5ffd5b6123e9836121d6565b91506123f7602084016121d6565b90509250929050565b5f60208284031215612410575f5ffd5b5035919050565b5f60208284031215612427575f5ffd5b81356108f58161217f565b6001600160e01b031981168114612193575f5ffd5b5f5f60408385031215612458575f5ffd5b82356124638161217f565b9150602083013561229c81612432565b5f5f5f60408486031215612485575f5ffd5b61232d846121d6565b5f5f6040838503121561249f575f5ffd5b6124a8836121d6565b91506123f760208401612360565b5f5f5f5f606085870312156124c9575f5ffd5b84356124d48161217f565b935060208501356124e48161217f565b925060408501356001600160401b038111156124fe575f5ffd5b61250a878288016122d3565b95989497509550505050565b5f5f60208385031215612527575f5ffd5b82356001600160401b0381111561253c575f5ffd5b61254885828601612196565b90969095509350505050565b5f602082016020835280845180835260408501915060408160051b8601019250602086015f5b828110156125cc57603f19878603018452815180518087528060208301602089015e5f602082890101526020601f19601f8301168801019650505060208201915060208401935060018101905061257a565b50929695505050505050565b5f5f5f606084860312156125ea575f5ffd5b83356125f58161217f565b925060208401356126058161217f565b9150604084013561261581612432565b809150509250925092565b5f5f60408385031215612631575f5ffd5b82356124a88161217f565b5f5f5f5f6060858703121561264f575f5ffd5b843561265a8161217f565b935060208501356001600160401b03811115612674575f5ffd5b612680878288016122d3565b909450925050604085013565ffffffffffff8116811461269e575f5ffd5b939692955090935050565b634e487b7160e01b5f52603260045260245ffd5b5f602082840312156126cd575f5ffd5b81356108f581612432565b81835281816020850137505f828201602090810191909152601f909101601f19169091010190565b602081525f610be96020830184866126d8565b5f60208284031215612723575f5ffd5b81516108f581612432565b6001600160a01b038581168252841660208201526060604082018190525f9061275a90830184866126d8565b9695505050505050565b634e487b7160e01b5f52601160045260245ffd5b5f5f85851115612786575f5ffd5b83861115612792575f5ffd5b5050820193919092039150565b634e487b7160e01b5f52604160045260245ffd5b5f5f8335601e198436030181126127c8575f5ffd5b8301803591506001600160401b038211156127e1575f5ffd5b602001915036819003821315610e50575f5ffd5b828482375f8382015f815283518060208601835e5f910190815295945050505050565b65ffffffffffff818116838216019081111561075257610752612764565b65ffffffffffff861681526001600160a01b038581166020830152841660408201526080606082018190525f9061287090830184866126d8565b979650505050505050565b80356001600160e01b03198116906004841015611a6f576001600160e01b031960049490940360031b84901b1690921692915050565b63ffffffff82811682821603908111156107525761075261276456fea2646970667358221220a5f2a31bcab50ad1bf1dd7265dea5d3d16300eeb1d8024eaa29875390032ca7764736f6c63430008230033", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/Account.json b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/Account.json similarity index 100% rename from dependencies/@openzeppelin-contracts-5.5.0/build/contracts/Account.json rename to dependencies/@openzeppelin-contracts-5.7.0/build/contracts/Account.json diff --git a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/AccountERC7579.json b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/AccountERC7579.json similarity index 100% rename from dependencies/@openzeppelin-contracts-5.5.0/build/contracts/AccountERC7579.json rename to dependencies/@openzeppelin-contracts-5.7.0/build/contracts/AccountERC7579.json diff --git a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/AccountERC7579Hooked.json b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/AccountERC7579Hooked.json similarity index 100% rename from dependencies/@openzeppelin-contracts-5.5.0/build/contracts/AccountERC7579Hooked.json rename to dependencies/@openzeppelin-contracts-5.7.0/build/contracts/AccountERC7579Hooked.json diff --git a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/Accumulators.json b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/Accumulators.json similarity index 67% rename from dependencies/@openzeppelin-contracts-5.5.0/build/contracts/Accumulators.json rename to dependencies/@openzeppelin-contracts-5.7.0/build/contracts/Accumulators.json index 3f42c3e..9f5edc7 100644 --- a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/Accumulators.json +++ b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/Accumulators.json @@ -3,8 +3,8 @@ "contractName": "Accumulators", "sourceName": "contracts/utils/structs/Accumulators.sol", "abi": [], - "bytecode": "0x60556032600b8282823980515f1a607314602657634e487b7160e01b5f525f60045260245ffd5b305f52607381538281f3fe730000000000000000000000000000000000000000301460806040525f5ffdfea26469706673582212200ca17363cd971fcd96f101121bbccb4a1a08f31f40db4ba3bc8a4ab85d1d5d5c64736f6c634300081b0033", - "deployedBytecode": "0x730000000000000000000000000000000000000000301460806040525f5ffdfea26469706673582212200ca17363cd971fcd96f101121bbccb4a1a08f31f40db4ba3bc8a4ab85d1d5d5c64736f6c634300081b0033", + "bytecode": "0x60556032600b8282823980515f1a607314602657634e487b7160e01b5f525f60045260245ffd5b305f52607381538281f3fe730000000000000000000000000000000000000000301460806040525f5ffdfea264697066735822122009e33f1fb70bd8785ba6736c06326da5376e75b0651f9f69dabac79c59b2258a64736f6c63430008230033", + "deployedBytecode": "0x730000000000000000000000000000000000000000301460806040525f5ffdfea264697066735822122009e33f1fb70bd8785ba6736c06326da5376e75b0651f9f69dabac79c59b2258a64736f6c63430008230033", "linkReferences": {}, "deployedLinkReferences": {} } diff --git a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/Address.json b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/Address.json similarity index 74% rename from dependencies/@openzeppelin-contracts-5.5.0/build/contracts/Address.json rename to dependencies/@openzeppelin-contracts-5.7.0/build/contracts/Address.json index c67b007..5c4da23 100644 --- a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/Address.json +++ b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/Address.json @@ -15,8 +15,8 @@ "type": "error" } ], - "bytecode": "0x60556032600b8282823980515f1a607314602657634e487b7160e01b5f525f60045260245ffd5b305f52607381538281f3fe730000000000000000000000000000000000000000301460806040525f5ffdfea2646970667358221220a50f9bce664738e2a0edd81cda3c0d6249fefbca7e9596bc16d097d6f031ebd664736f6c634300081b0033", - "deployedBytecode": "0x730000000000000000000000000000000000000000301460806040525f5ffdfea2646970667358221220a50f9bce664738e2a0edd81cda3c0d6249fefbca7e9596bc16d097d6f031ebd664736f6c634300081b0033", + "bytecode": "0x60556032600b8282823980515f1a607314602657634e487b7160e01b5f525f60045260245ffd5b305f52607381538281f3fe730000000000000000000000000000000000000000301460806040525f5ffdfea2646970667358221220eef78171d26cfeb2cf06a1574efd740e05c744d297fd24112abd891c53a81dc564736f6c63430008230033", + "deployedBytecode": "0x730000000000000000000000000000000000000000301460806040525f5ffdfea2646970667358221220eef78171d26cfeb2cf06a1574efd740e05c744d297fd24112abd891c53a81dc564736f6c63430008230033", "linkReferences": {}, "deployedLinkReferences": {} } diff --git a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/Arrays.json b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/Arrays.json similarity index 66% rename from dependencies/@openzeppelin-contracts-5.5.0/build/contracts/Arrays.json rename to dependencies/@openzeppelin-contracts-5.7.0/build/contracts/Arrays.json index 4f53814..30615c8 100644 --- a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/Arrays.json +++ b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/Arrays.json @@ -3,8 +3,8 @@ "contractName": "Arrays", "sourceName": "contracts/utils/Arrays.sol", "abi": [], - "bytecode": "0x60556032600b8282823980515f1a607314602657634e487b7160e01b5f525f60045260245ffd5b305f52607381538281f3fe730000000000000000000000000000000000000000301460806040525f5ffdfea2646970667358221220521607d023a3ddbbff7be6d8ce49f1ffe53557a94d9c55dfbd308faad5a1ba4f64736f6c634300081b0033", - "deployedBytecode": "0x730000000000000000000000000000000000000000301460806040525f5ffdfea2646970667358221220521607d023a3ddbbff7be6d8ce49f1ffe53557a94d9c55dfbd308faad5a1ba4f64736f6c634300081b0033", + "bytecode": "0x60556032600b8282823980515f1a607314602657634e487b7160e01b5f525f60045260245ffd5b305f52607381538281f3fe730000000000000000000000000000000000000000301460806040525f5ffdfea26469706673582212205eb5b0e59c2bd7ef4554640cca4dd9eb6ca595ef68772fd6080f4645ec9876fe64736f6c63430008230033", + "deployedBytecode": "0x730000000000000000000000000000000000000000301460806040525f5ffdfea26469706673582212205eb5b0e59c2bd7ef4554640cca4dd9eb6ca595ef68772fd6080f4645ec9876fe64736f6c63430008230033", "linkReferences": {}, "deployedLinkReferences": {} } diff --git a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/AuthorityUtils.json b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/AuthorityUtils.json similarity index 67% rename from dependencies/@openzeppelin-contracts-5.5.0/build/contracts/AuthorityUtils.json rename to dependencies/@openzeppelin-contracts-5.7.0/build/contracts/AuthorityUtils.json index e5f7086..95a91f7 100644 --- a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/AuthorityUtils.json +++ b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/AuthorityUtils.json @@ -3,8 +3,8 @@ "contractName": "AuthorityUtils", "sourceName": "contracts/access/manager/AuthorityUtils.sol", "abi": [], - "bytecode": "0x60556032600b8282823980515f1a607314602657634e487b7160e01b5f525f60045260245ffd5b305f52607381538281f3fe730000000000000000000000000000000000000000301460806040525f5ffdfea2646970667358221220b9cd713c51ade5ddc2edcb79fa4d9cb7a8947ce92d2c688ea89c6cd0c578871f64736f6c634300081b0033", - "deployedBytecode": "0x730000000000000000000000000000000000000000301460806040525f5ffdfea2646970667358221220b9cd713c51ade5ddc2edcb79fa4d9cb7a8947ce92d2c688ea89c6cd0c578871f64736f6c634300081b0033", + "bytecode": "0x60556032600b8282823980515f1a607314602657634e487b7160e01b5f525f60045260245ffd5b305f52607381538281f3fe730000000000000000000000000000000000000000301460806040525f5ffdfea2646970667358221220508e794c9f0a132f33416cc0d5d218e525c9db0f2381859078283abeb386e46064736f6c63430008230033", + "deployedBytecode": "0x730000000000000000000000000000000000000000301460806040525f5ffdfea2646970667358221220508e794c9f0a132f33416cc0d5d218e525c9db0f2381859078283abeb386e46064736f6c63430008230033", "linkReferences": {}, "deployedLinkReferences": {} } diff --git a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/Base58.json b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/Base58.json similarity index 74% rename from dependencies/@openzeppelin-contracts-5.5.0/build/contracts/Base58.json rename to dependencies/@openzeppelin-contracts-5.7.0/build/contracts/Base58.json index ec4e640..39d2ea4 100644 --- a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/Base58.json +++ b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/Base58.json @@ -15,8 +15,8 @@ "type": "error" } ], - "bytecode": "0x60556032600b8282823980515f1a607314602657634e487b7160e01b5f525f60045260245ffd5b305f52607381538281f3fe730000000000000000000000000000000000000000301460806040525f5ffdfea264697066735822122011334f7216bd7d9c5e45b1b64abfc741595680f66dfaa0f44eed5453da50de2164736f6c634300081b0033", - "deployedBytecode": "0x730000000000000000000000000000000000000000301460806040525f5ffdfea264697066735822122011334f7216bd7d9c5e45b1b64abfc741595680f66dfaa0f44eed5453da50de2164736f6c634300081b0033", + "bytecode": "0x60556032600b8282823980515f1a607314602657634e487b7160e01b5f525f60045260245ffd5b305f52607381538281f3fe730000000000000000000000000000000000000000301460806040525f5ffdfea2646970667358221220947cd1c29a49292d1f40f9d9ae38c5f9184d698002b9804b717bdcb1d003226f64736f6c63430008230033", + "deployedBytecode": "0x730000000000000000000000000000000000000000301460806040525f5ffdfea2646970667358221220947cd1c29a49292d1f40f9d9ae38c5f9184d698002b9804b717bdcb1d003226f64736f6c63430008230033", "linkReferences": {}, "deployedLinkReferences": {} } diff --git a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/Base64.json b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/Base64.json similarity index 74% rename from dependencies/@openzeppelin-contracts-5.5.0/build/contracts/Base64.json rename to dependencies/@openzeppelin-contracts-5.7.0/build/contracts/Base64.json index a4c9c6f..a8ef8b3 100644 --- a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/Base64.json +++ b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/Base64.json @@ -15,8 +15,8 @@ "type": "error" } ], - "bytecode": "0x60556032600b8282823980515f1a607314602657634e487b7160e01b5f525f60045260245ffd5b305f52607381538281f3fe730000000000000000000000000000000000000000301460806040525f5ffdfea26469706673582212209a2134e5f3a2350b6622d477090c270ee5ee92a775b37058a2d980dc5f726d3364736f6c634300081b0033", - "deployedBytecode": "0x730000000000000000000000000000000000000000301460806040525f5ffdfea26469706673582212209a2134e5f3a2350b6622d477090c270ee5ee92a775b37058a2d980dc5f726d3364736f6c634300081b0033", + "bytecode": "0x60556032600b8282823980515f1a607314602657634e487b7160e01b5f525f60045260245ffd5b305f52607381538281f3fe730000000000000000000000000000000000000000301460806040525f5ffdfea2646970667358221220506266bbff936e941d5d3349949fdc360beb259bdba49e513e1e0dda0fc8bbb764736f6c63430008230033", + "deployedBytecode": "0x730000000000000000000000000000000000000000301460806040525f5ffdfea2646970667358221220506266bbff936e941d5d3349949fdc360beb259bdba49e513e1e0dda0fc8bbb764736f6c63430008230033", "linkReferences": {}, "deployedLinkReferences": {} } diff --git a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/BeaconProxy.json b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/BeaconProxy.json similarity index 95% rename from dependencies/@openzeppelin-contracts-5.5.0/build/contracts/BeaconProxy.json rename to dependencies/@openzeppelin-contracts-5.7.0/build/contracts/BeaconProxy.json index 196b3df..0e0814e 100644 --- a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/BeaconProxy.json +++ b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/BeaconProxy.json @@ -80,8 +80,8 @@ "type": "fallback" } ], - "bytecode": "0x60a060405260405161054538038061054583398101604081905261002291610331565b61002c828261003e565b506001600160a01b0316608052610413565b610047826100fb565b6040516001600160a01b038316907f1cf3b03a6cf19fa2baba4df148e9dcabedea7f8a5c07840e207e5c089be95d3e905f90a28051156100ef576100ea826001600160a01b0316635c60da1b6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156100c0573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906100e491906103f3565b82610209565b505050565b6100f76102aa565b5050565b806001600160a01b03163b5f0361013557604051631933b43b60e21b81526001600160a01b03821660048201526024015b60405180910390fd5b807fa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d5080546001600160a01b0319166001600160a01b0392831617905560408051635c60da1b60e01b815290515f92841691635c60da1b9160048083019260209291908290030181865afa1580156101ae573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906101d291906103f3565b9050806001600160a01b03163b5f036100f757604051634c9c8ce360e01b81526001600160a01b038216600482015260240161012c565b60605f61021684846102cb565b905080801561023757505f3d118061023757505f846001600160a01b03163b115b1561024c576102446102de565b9150506102a4565b801561027657604051639996b31560e01b81526001600160a01b038516600482015260240161012c565b3d15610289576102846102f7565b6102a2565b60405163d6bda27560e01b815260040160405180910390fd5b505b92915050565b34156102c95760405163b398979f60e01b815260040160405180910390fd5b565b5f5f5f835160208501865af49392505050565b6040513d81523d5f602083013e3d602001810160405290565b6040513d5f823e3d81fd5b80516001600160a01b0381168114610318575f5ffd5b919050565b634e487b7160e01b5f52604160045260245ffd5b5f5f60408385031215610342575f5ffd5b61034b83610302565b60208401519092506001600160401b03811115610366575f5ffd5b8301601f81018513610376575f5ffd5b80516001600160401b0381111561038f5761038f61031d565b604051601f8201601f19908116603f011681016001600160401b03811182821017156103bd576103bd61031d565b6040528181528282016020018710156103d4575f5ffd5b8160208401602083015e5f602083830101528093505050509250929050565b5f60208284031215610403575f5ffd5b61040c82610302565b9392505050565b60805161011b61042a5f395f601d015261011b5ff3fe6080604052600a600c565b005b60186014601a565b609d565b565b5f7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316635c60da1b6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156076573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906098919060ba565b905090565b365f5f375f5f365f845af43d5f5f3e80801560b6573d5ff35b3d5ffd5b5f6020828403121560c9575f5ffd5b81516001600160a01b038116811460de575f5ffd5b939250505056fea264697066735822122037553b70027a4aad2b22cb94e3b3778213de0fa0ec69474b0ab010e77b2ce23d64736f6c634300081b0033", - "deployedBytecode": "0x6080604052600a600c565b005b60186014601a565b609d565b565b5f7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316635c60da1b6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156076573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906098919060ba565b905090565b365f5f375f5f365f845af43d5f5f3e80801560b6573d5ff35b3d5ffd5b5f6020828403121560c9575f5ffd5b81516001600160a01b038116811460de575f5ffd5b939250505056fea264697066735822122037553b70027a4aad2b22cb94e3b3778213de0fa0ec69474b0ab010e77b2ce23d64736f6c634300081b0033", + "bytecode": "0x60a060405260405161054538038061054583398101604081905261002291610331565b61002c828261003e565b506001600160a01b0316608052610413565b610047826100fb565b6040516001600160a01b038316907f1cf3b03a6cf19fa2baba4df148e9dcabedea7f8a5c07840e207e5c089be95d3e905f90a28051156100ef576100ea826001600160a01b0316635c60da1b6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156100c0573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906100e491906103f3565b82610209565b505050565b6100f76102aa565b5050565b806001600160a01b03163b5f0361013557604051631933b43b60e21b81526001600160a01b03821660048201526024015b60405180910390fd5b807fa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d5080546001600160a01b0319166001600160a01b0392831617905560408051635c60da1b60e01b815290515f92841691635c60da1b9160048083019260209291908290030181865afa1580156101ae573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906101d291906103f3565b9050806001600160a01b03163b5f036100f757604051634c9c8ce360e01b81526001600160a01b038216600482015260240161012c565b60605f61021684846102cb565b905080801561023757505f3d118061023757505f846001600160a01b03163b115b1561024c576102446102de565b9150506102a4565b801561027657604051639996b31560e01b81526001600160a01b038516600482015260240161012c565b3d15610289576102846102f7565b6102a2565b60405163d6bda27560e01b815260040160405180910390fd5b505b92915050565b34156102c95760405163b398979f60e01b815260040160405180910390fd5b565b5f5f5f835160208501865af49392505050565b6040513d81523d5f602083013e3d602001810160405290565b6040513d5f823e3d81fd5b80516001600160a01b0381168114610318575f5ffd5b919050565b634e487b7160e01b5f52604160045260245ffd5b5f5f60408385031215610342575f5ffd5b61034b83610302565b60208401519092506001600160401b03811115610366575f5ffd5b8301601f81018513610376575f5ffd5b80516001600160401b0381111561038f5761038f61031d565b604051601f8201601f19908116603f011681016001600160401b03811182821017156103bd576103bd61031d565b6040528181528282016020018710156103d4575f5ffd5b8160208401602083015e5f602083830101528093505050509250929050565b5f60208284031215610403575f5ffd5b61040c82610302565b9392505050565b60805161011b61042a5f395f601d015261011b5ff3fe6080604052600a600c565b005b60186014601a565b609d565b565b5f7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316635c60da1b6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156076573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906098919060ba565b905090565b365f5f375f5f365f845af43d5f5f3e80801560b6573d5ff35b3d5ffd5b5f6020828403121560c9575f5ffd5b81516001600160a01b038116811460de575f5ffd5b939250505056fea2646970667358221220cdb2216dfc3883186e55c1caaa0ca0a3c892d9a02f48450e091948d84e1ed21d64736f6c63430008230033", + "deployedBytecode": "0x6080604052600a600c565b005b60186014601a565b609d565b565b5f7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316635c60da1b6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156076573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906098919060ba565b905090565b365f5f375f5f365f845af43d5f5f3e80801560b6573d5ff35b3d5ffd5b5f6020828403121560c9575f5ffd5b81516001600160a01b038116811460de575f5ffd5b939250505056fea2646970667358221220cdb2216dfc3883186e55c1caaa0ca0a3c892d9a02f48450e091948d84e1ed21d64736f6c63430008230033", "linkReferences": {}, "deployedLinkReferences": {} } diff --git a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/BitMaps.json b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/BitMaps.json similarity index 66% rename from dependencies/@openzeppelin-contracts-5.5.0/build/contracts/BitMaps.json rename to dependencies/@openzeppelin-contracts-5.7.0/build/contracts/BitMaps.json index 48b9b64..1da2444 100644 --- a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/BitMaps.json +++ b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/BitMaps.json @@ -3,8 +3,8 @@ "contractName": "BitMaps", "sourceName": "contracts/utils/structs/BitMaps.sol", "abi": [], - "bytecode": "0x60556032600b8282823980515f1a607314602657634e487b7160e01b5f525f60045260245ffd5b305f52607381538281f3fe730000000000000000000000000000000000000000301460806040525f5ffdfea2646970667358221220f8968052b6c914ec8df760e7c1806604ab7a793d17884410a6635309dcfcfe2f64736f6c634300081b0033", - "deployedBytecode": "0x730000000000000000000000000000000000000000301460806040525f5ffdfea2646970667358221220f8968052b6c914ec8df760e7c1806604ab7a793d17884410a6635309dcfcfe2f64736f6c634300081b0033", + "bytecode": "0x60556032600b8282823980515f1a607314602657634e487b7160e01b5f525f60045260245ffd5b305f52607381538281f3fe730000000000000000000000000000000000000000301460806040525f5ffdfea264697066735822122062bf17d85439cfb7edefb4457eb8bc339478917d07fefbbe7faaf0870b05833764736f6c63430008230033", + "deployedBytecode": "0x730000000000000000000000000000000000000000301460806040525f5ffdfea264697066735822122062bf17d85439cfb7edefb4457eb8bc339478917d07fefbbe7faaf0870b05833764736f6c63430008230033", "linkReferences": {}, "deployedLinkReferences": {} } diff --git a/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/BlockHeader.json b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/BlockHeader.json new file mode 100644 index 0000000..0a42521 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/BlockHeader.json @@ -0,0 +1,22 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "BlockHeader", + "sourceName": "contracts/utils/BlockHeader.sol", + "abi": [ + { + "inputs": [ + { + "internalType": "enum BlockHeader.HeaderField", + "name": "", + "type": "uint8" + } + ], + "name": "FieldNotPresentInBlockHeader", + "type": "error" + } + ], + "bytecode": "0x60556032600b8282823980515f1a607314602657634e487b7160e01b5f525f60045260245ffd5b305f52607381538281f3fe730000000000000000000000000000000000000000301460806040525f5ffdfea2646970667358221220e6f07b50a99c2452843a6a41ae3f327c743254979e0ac95e17390f118c5e8e1964736f6c63430008230033", + "deployedBytecode": "0x730000000000000000000000000000000000000000301460806040525f5ffdfea2646970667358221220e6f07b50a99c2452843a6a41ae3f327c743254979e0ac95e17390f118c5e8e1964736f6c63430008230033", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/Blockhash.json b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/Blockhash.json similarity index 66% rename from dependencies/@openzeppelin-contracts-5.5.0/build/contracts/Blockhash.json rename to dependencies/@openzeppelin-contracts-5.7.0/build/contracts/Blockhash.json index 35ee6cf..ab520c2 100644 --- a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/Blockhash.json +++ b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/Blockhash.json @@ -3,8 +3,8 @@ "contractName": "Blockhash", "sourceName": "contracts/utils/Blockhash.sol", "abi": [], - "bytecode": "0x60556032600b8282823980515f1a607314602657634e487b7160e01b5f525f60045260245ffd5b305f52607381538281f3fe730000000000000000000000000000000000000000301460806040525f5ffdfea2646970667358221220992fd48ab27a261868b719547cda97f6028e7c1725e26fd36e9c12b8fee9eb2464736f6c634300081b0033", - "deployedBytecode": "0x730000000000000000000000000000000000000000301460806040525f5ffdfea2646970667358221220992fd48ab27a261868b719547cda97f6028e7c1725e26fd36e9c12b8fee9eb2464736f6c634300081b0033", + "bytecode": "0x60556032600b8282823980515f1a607314602657634e487b7160e01b5f525f60045260245ffd5b305f52607381538281f3fe730000000000000000000000000000000000000000301460806040525f5ffdfea264697066735822122085710c3e87e82040d4727374bc44130b905836e3772f4106a61785ef52a4611764736f6c63430008230033", + "deployedBytecode": "0x730000000000000000000000000000000000000000301460806040525f5ffdfea264697066735822122085710c3e87e82040d4727374bc44130b905836e3772f4106a61785ef52a4611764736f6c63430008230033", "linkReferences": {}, "deployedLinkReferences": {} } diff --git a/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/BridgeERC1155.json b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/BridgeERC1155.json new file mode 100644 index 0000000..73a17dc --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/BridgeERC1155.json @@ -0,0 +1,505 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "BridgeERC1155", + "sourceName": "contracts/crosschain/bridges/BridgeERC1155.sol", + "abi": [ + { + "inputs": [], + "name": "CrosschainMultiTokenEmptyAddress", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "operator", + "type": "address" + }, + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "ERC1155MissingApprovalForAll", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "gateway", + "type": "address" + }, + { + "internalType": "bytes", + "name": "sender", + "type": "bytes" + } + ], + "name": "ERC7786RecipientUnauthorizedGateway", + "type": "error" + }, + { + "inputs": [], + "name": "InteroperableAddressEmptyReferenceAndAddress", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "name": "InteroperableAddressParsingError", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "chain", + "type": "bytes" + } + ], + "name": "LinkAlreadyRegistered", + "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": "receiveId", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "from", + "type": "bytes" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256[]", + "name": "ids", + "type": "uint256[]" + }, + { + "indexed": false, + "internalType": "uint256[]", + "name": "values", + "type": "uint256[]" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "CrosschainMultiTokenTransferReceived", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "sendId", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "to", + "type": "bytes" + }, + { + "indexed": false, + "internalType": "uint256[]", + "name": "ids", + "type": "uint256[]" + }, + { + "indexed": false, + "internalType": "uint256[]", + "name": "values", + "type": "uint256[]" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "CrosschainMultiTokenTransferSent", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "gateway", + "type": "address" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "counterpart", + "type": "bytes" + } + ], + "name": "LinkRegistered", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "bytes", + "name": "to", + "type": "bytes" + }, + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "crosschainTransferFrom", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "bytes", + "name": "to", + "type": "bytes" + }, + { + "internalType": "uint256[]", + "name": "ids", + "type": "uint256[]" + }, + { + "internalType": "uint256[]", + "name": "values", + "type": "uint256[]" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "crosschainTransferFrom", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "bytes", + "name": "to", + "type": "bytes" + }, + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "crosschainTransferFrom", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "bytes", + "name": "to", + "type": "bytes" + }, + { + "internalType": "uint256[]", + "name": "ids", + "type": "uint256[]" + }, + { + "internalType": "uint256[]", + "name": "values", + "type": "uint256[]" + } + ], + "name": "crosschainTransferFrom", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "chain", + "type": "bytes" + } + ], + "name": "getLink", + "outputs": [ + { + "internalType": "address", + "name": "gateway", + "type": "address" + }, + { + "internalType": "bytes", + "name": "counterpart", + "type": "bytes" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "operator", + "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": "operator", + "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": "bytes32", + "name": "receiveId", + "type": "bytes32" + }, + { + "internalType": "bytes", + "name": "sender", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "payload", + "type": "bytes" + } + ], + "name": "receiveMessage", + "outputs": [ + { + "internalType": "bytes4", + "name": "", + "type": "bytes4" + } + ], + "stateMutability": "payable", + "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 IERC1155", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + } + ], + "bytecode": "0x", + "deployedBytecode": "0x", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/BridgeERC20.json b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/BridgeERC20.json new file mode 100644 index 0000000..95ad7f0 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/BridgeERC20.json @@ -0,0 +1,257 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "BridgeERC20", + "sourceName": "contracts/crosschain/bridges/BridgeERC20.sol", + "abi": [ + { + "inputs": [], + "name": "CrosschainFungibleEmptyAddress", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "gateway", + "type": "address" + }, + { + "internalType": "bytes", + "name": "sender", + "type": "bytes" + } + ], + "name": "ERC7786RecipientUnauthorizedGateway", + "type": "error" + }, + { + "inputs": [], + "name": "InteroperableAddressEmptyReferenceAndAddress", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "name": "InteroperableAddressParsingError", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "chain", + "type": "bytes" + } + ], + "name": "LinkAlreadyRegistered", + "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": "bytes32", + "name": "receiveId", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "from", + "type": "bytes" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "CrosschainFungibleTransferReceived", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "sendId", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "to", + "type": "bytes" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "CrosschainFungibleTransferSent", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "gateway", + "type": "address" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "counterpart", + "type": "bytes" + } + ], + "name": "LinkRegistered", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "to", + "type": "bytes" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "crosschainTransfer", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "chain", + "type": "bytes" + } + ], + "name": "getLink", + "outputs": [ + { + "internalType": "address", + "name": "gateway", + "type": "address" + }, + { + "internalType": "bytes", + "name": "counterpart", + "type": "bytes" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "receiveId", + "type": "bytes32" + }, + { + "internalType": "bytes", + "name": "sender", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "payload", + "type": "bytes" + } + ], + "name": "receiveMessage", + "outputs": [ + { + "internalType": "bytes4", + "name": "", + "type": "bytes4" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [], + "name": "token", + "outputs": [ + { + "internalType": "contract IERC20", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + } + ], + "bytecode": "0x", + "deployedBytecode": "0x", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/BridgeERC721.json b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/BridgeERC721.json new file mode 100644 index 0000000..96047da --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/BridgeERC721.json @@ -0,0 +1,267 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "BridgeERC721", + "sourceName": "contracts/crosschain/bridges/BridgeERC721.sol", + "abi": [ + { + "inputs": [], + "name": "CrosschainNonFungibleEmptyAddress", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "operator", + "type": "address" + }, + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "ERC721InsufficientApproval", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "gateway", + "type": "address" + }, + { + "internalType": "bytes", + "name": "sender", + "type": "bytes" + } + ], + "name": "ERC7786RecipientUnauthorizedGateway", + "type": "error" + }, + { + "inputs": [], + "name": "InteroperableAddressEmptyReferenceAndAddress", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "name": "InteroperableAddressParsingError", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "chain", + "type": "bytes" + } + ], + "name": "LinkAlreadyRegistered", + "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": "receiveId", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "from", + "type": "bytes" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "CrosschainNonFungibleTransferReceived", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "sendId", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "to", + "type": "bytes" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "CrosschainNonFungibleTransferSent", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "gateway", + "type": "address" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "counterpart", + "type": "bytes" + } + ], + "name": "LinkRegistered", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "bytes", + "name": "to", + "type": "bytes" + }, + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "crosschainTransferFrom", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "chain", + "type": "bytes" + } + ], + "name": "getLink", + "outputs": [ + { + "internalType": "address", + "name": "gateway", + "type": "address" + }, + { + "internalType": "bytes", + "name": "counterpart", + "type": "bytes" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "receiveId", + "type": "bytes32" + }, + { + "internalType": "bytes", + "name": "sender", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "payload", + "type": "bytes" + } + ], + "name": "receiveMessage", + "outputs": [ + { + "internalType": "bytes4", + "name": "", + "type": "bytes4" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [], + "name": "token", + "outputs": [ + { + "internalType": "contract IERC721", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + } + ], + "bytecode": "0x", + "deployedBytecode": "0x", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/BridgeERC7802.json b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/BridgeERC7802.json new file mode 100644 index 0000000..0fb9e6c --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/BridgeERC7802.json @@ -0,0 +1,246 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "BridgeERC7802", + "sourceName": "contracts/crosschain/bridges/BridgeERC7802.sol", + "abi": [ + { + "inputs": [], + "name": "CrosschainFungibleEmptyAddress", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "gateway", + "type": "address" + }, + { + "internalType": "bytes", + "name": "sender", + "type": "bytes" + } + ], + "name": "ERC7786RecipientUnauthorizedGateway", + "type": "error" + }, + { + "inputs": [], + "name": "InteroperableAddressEmptyReferenceAndAddress", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "name": "InteroperableAddressParsingError", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "chain", + "type": "bytes" + } + ], + "name": "LinkAlreadyRegistered", + "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": "receiveId", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "from", + "type": "bytes" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "CrosschainFungibleTransferReceived", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "sendId", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "to", + "type": "bytes" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "CrosschainFungibleTransferSent", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "gateway", + "type": "address" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "counterpart", + "type": "bytes" + } + ], + "name": "LinkRegistered", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "to", + "type": "bytes" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "crosschainTransfer", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "chain", + "type": "bytes" + } + ], + "name": "getLink", + "outputs": [ + { + "internalType": "address", + "name": "gateway", + "type": "address" + }, + { + "internalType": "bytes", + "name": "counterpart", + "type": "bytes" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "receiveId", + "type": "bytes32" + }, + { + "internalType": "bytes", + "name": "sender", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "payload", + "type": "bytes" + } + ], + "name": "receiveMessage", + "outputs": [ + { + "internalType": "bytes4", + "name": "", + "type": "bytes4" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [], + "name": "token", + "outputs": [ + { + "internalType": "contract IERC7802", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + } + ], + "bytecode": "0x", + "deployedBytecode": "0x", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/BridgeFungible.json b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/BridgeFungible.json new file mode 100644 index 0000000..d625975 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/BridgeFungible.json @@ -0,0 +1,233 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "BridgeFungible", + "sourceName": "contracts/crosschain/bridges/abstract/BridgeFungible.sol", + "abi": [ + { + "inputs": [], + "name": "CrosschainFungibleEmptyAddress", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "gateway", + "type": "address" + }, + { + "internalType": "bytes", + "name": "sender", + "type": "bytes" + } + ], + "name": "ERC7786RecipientUnauthorizedGateway", + "type": "error" + }, + { + "inputs": [], + "name": "InteroperableAddressEmptyReferenceAndAddress", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "name": "InteroperableAddressParsingError", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "chain", + "type": "bytes" + } + ], + "name": "LinkAlreadyRegistered", + "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": "receiveId", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "from", + "type": "bytes" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "CrosschainFungibleTransferReceived", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "sendId", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "to", + "type": "bytes" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "CrosschainFungibleTransferSent", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "gateway", + "type": "address" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "counterpart", + "type": "bytes" + } + ], + "name": "LinkRegistered", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "to", + "type": "bytes" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "crosschainTransfer", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "chain", + "type": "bytes" + } + ], + "name": "getLink", + "outputs": [ + { + "internalType": "address", + "name": "gateway", + "type": "address" + }, + { + "internalType": "bytes", + "name": "counterpart", + "type": "bytes" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "receiveId", + "type": "bytes32" + }, + { + "internalType": "bytes", + "name": "sender", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "payload", + "type": "bytes" + } + ], + "name": "receiveMessage", + "outputs": [ + { + "internalType": "bytes4", + "name": "", + "type": "bytes4" + } + ], + "stateMutability": "payable", + "type": "function" + } + ], + "bytecode": "0x", + "deployedBytecode": "0x", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/BridgeMultiToken.json b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/BridgeMultiToken.json new file mode 100644 index 0000000..994b008 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/BridgeMultiToken.json @@ -0,0 +1,233 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "BridgeMultiToken", + "sourceName": "contracts/crosschain/bridges/abstract/BridgeMultiToken.sol", + "abi": [ + { + "inputs": [], + "name": "CrosschainMultiTokenEmptyAddress", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "gateway", + "type": "address" + }, + { + "internalType": "bytes", + "name": "sender", + "type": "bytes" + } + ], + "name": "ERC7786RecipientUnauthorizedGateway", + "type": "error" + }, + { + "inputs": [], + "name": "InteroperableAddressEmptyReferenceAndAddress", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "name": "InteroperableAddressParsingError", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "chain", + "type": "bytes" + } + ], + "name": "LinkAlreadyRegistered", + "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": "receiveId", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "from", + "type": "bytes" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256[]", + "name": "ids", + "type": "uint256[]" + }, + { + "indexed": false, + "internalType": "uint256[]", + "name": "values", + "type": "uint256[]" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "CrosschainMultiTokenTransferReceived", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "sendId", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "to", + "type": "bytes" + }, + { + "indexed": false, + "internalType": "uint256[]", + "name": "ids", + "type": "uint256[]" + }, + { + "indexed": false, + "internalType": "uint256[]", + "name": "values", + "type": "uint256[]" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "CrosschainMultiTokenTransferSent", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "gateway", + "type": "address" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "counterpart", + "type": "bytes" + } + ], + "name": "LinkRegistered", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "chain", + "type": "bytes" + } + ], + "name": "getLink", + "outputs": [ + { + "internalType": "address", + "name": "gateway", + "type": "address" + }, + { + "internalType": "bytes", + "name": "counterpart", + "type": "bytes" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "receiveId", + "type": "bytes32" + }, + { + "internalType": "bytes", + "name": "sender", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "payload", + "type": "bytes" + } + ], + "name": "receiveMessage", + "outputs": [ + { + "internalType": "bytes4", + "name": "", + "type": "bytes4" + } + ], + "stateMutability": "payable", + "type": "function" + } + ], + "bytecode": "0x", + "deployedBytecode": "0x", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/BridgeNonFungible.json b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/BridgeNonFungible.json new file mode 100644 index 0000000..cb37604 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/BridgeNonFungible.json @@ -0,0 +1,209 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "BridgeNonFungible", + "sourceName": "contracts/crosschain/bridges/abstract/BridgeNonFungible.sol", + "abi": [ + { + "inputs": [], + "name": "CrosschainNonFungibleEmptyAddress", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "gateway", + "type": "address" + }, + { + "internalType": "bytes", + "name": "sender", + "type": "bytes" + } + ], + "name": "ERC7786RecipientUnauthorizedGateway", + "type": "error" + }, + { + "inputs": [], + "name": "InteroperableAddressEmptyReferenceAndAddress", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "name": "InteroperableAddressParsingError", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "chain", + "type": "bytes" + } + ], + "name": "LinkAlreadyRegistered", + "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": "receiveId", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "from", + "type": "bytes" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "CrosschainNonFungibleTransferReceived", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "sendId", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "to", + "type": "bytes" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "CrosschainNonFungibleTransferSent", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "gateway", + "type": "address" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "counterpart", + "type": "bytes" + } + ], + "name": "LinkRegistered", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "chain", + "type": "bytes" + } + ], + "name": "getLink", + "outputs": [ + { + "internalType": "address", + "name": "gateway", + "type": "address" + }, + { + "internalType": "bytes", + "name": "counterpart", + "type": "bytes" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "receiveId", + "type": "bytes32" + }, + { + "internalType": "bytes", + "name": "sender", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "payload", + "type": "bytes" + } + ], + "name": "receiveMessage", + "outputs": [ + { + "internalType": "bytes4", + "name": "", + "type": "bytes4" + } + ], + "stateMutability": "payable", + "type": "function" + } + ], + "bytecode": "0x", + "deployedBytecode": "0x", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/Bytes.json b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/Bytes.json similarity index 66% rename from dependencies/@openzeppelin-contracts-5.5.0/build/contracts/Bytes.json rename to dependencies/@openzeppelin-contracts-5.7.0/build/contracts/Bytes.json index 2b46808..3d37a1b 100644 --- a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/Bytes.json +++ b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/Bytes.json @@ -3,8 +3,8 @@ "contractName": "Bytes", "sourceName": "contracts/utils/Bytes.sol", "abi": [], - "bytecode": "0x60556032600b8282823980515f1a607314602657634e487b7160e01b5f525f60045260245ffd5b305f52607381538281f3fe730000000000000000000000000000000000000000301460806040525f5ffdfea2646970667358221220bce574d459cd95649fb9796ef81b7109dfd686ea0fdb4c366d1b469037e5c66b64736f6c634300081b0033", - "deployedBytecode": "0x730000000000000000000000000000000000000000301460806040525f5ffdfea2646970667358221220bce574d459cd95649fb9796ef81b7109dfd686ea0fdb4c366d1b469037e5c66b64736f6c634300081b0033", + "bytecode": "0x60556032600b8282823980515f1a607314602657634e487b7160e01b5f525f60045260245ffd5b305f52607381538281f3fe730000000000000000000000000000000000000000301460806040525f5ffdfea2646970667358221220e75fdcd16e31bf686110aac0caaba438783d18cf22416316386f515a45f4e2f864736f6c63430008230033", + "deployedBytecode": "0x730000000000000000000000000000000000000000301460806040525f5ffdfea2646970667358221220e75fdcd16e31bf686110aac0caaba438783d18cf22416316386f515a45f4e2f864736f6c63430008230033", "linkReferences": {}, "deployedLinkReferences": {} } diff --git a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/CAIP10.json b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/CAIP10.json similarity index 66% rename from dependencies/@openzeppelin-contracts-5.5.0/build/contracts/CAIP10.json rename to dependencies/@openzeppelin-contracts-5.7.0/build/contracts/CAIP10.json index 8a736ca..d6c7780 100644 --- a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/CAIP10.json +++ b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/CAIP10.json @@ -3,8 +3,8 @@ "contractName": "CAIP10", "sourceName": "contracts/utils/CAIP10.sol", "abi": [], - "bytecode": "0x60556032600b8282823980515f1a607314602657634e487b7160e01b5f525f60045260245ffd5b305f52607381538281f3fe730000000000000000000000000000000000000000301460806040525f5ffdfea2646970667358221220ea32e32f594b4a50c078a91ab844f06e257e66893ca74e75df94d8c40f9e6ae364736f6c634300081b0033", - "deployedBytecode": "0x730000000000000000000000000000000000000000301460806040525f5ffdfea2646970667358221220ea32e32f594b4a50c078a91ab844f06e257e66893ca74e75df94d8c40f9e6ae364736f6c634300081b0033", + "bytecode": "0x60556032600b8282823980515f1a607314602657634e487b7160e01b5f525f60045260245ffd5b305f52607381538281f3fe730000000000000000000000000000000000000000301460806040525f5ffdfea2646970667358221220773ce506e29d459751b611b06c20d80ff7b7941a4b406bf1838bb7a0b2a0c62d64736f6c63430008230033", + "deployedBytecode": "0x730000000000000000000000000000000000000000301460806040525f5ffdfea2646970667358221220773ce506e29d459751b611b06c20d80ff7b7941a4b406bf1838bb7a0b2a0c62d64736f6c63430008230033", "linkReferences": {}, "deployedLinkReferences": {} } diff --git a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/CAIP2.json b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/CAIP2.json similarity index 66% rename from dependencies/@openzeppelin-contracts-5.5.0/build/contracts/CAIP2.json rename to dependencies/@openzeppelin-contracts-5.7.0/build/contracts/CAIP2.json index f9dc914..12c6ba1 100644 --- a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/CAIP2.json +++ b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/CAIP2.json @@ -3,8 +3,8 @@ "contractName": "CAIP2", "sourceName": "contracts/utils/CAIP2.sol", "abi": [], - "bytecode": "0x60556032600b8282823980515f1a607314602657634e487b7160e01b5f525f60045260245ffd5b305f52607381538281f3fe730000000000000000000000000000000000000000301460806040525f5ffdfea26469706673582212206c30098518ef89aa934840ceefc56e3e9df819029ab0f35e549f5b38f39f453264736f6c634300081b0033", - "deployedBytecode": "0x730000000000000000000000000000000000000000301460806040525f5ffdfea26469706673582212206c30098518ef89aa934840ceefc56e3e9df819029ab0f35e549f5b38f39f453264736f6c634300081b0033", + "bytecode": "0x60556032600b8282823980515f1a607314602657634e487b7160e01b5f525f60045260245ffd5b305f52607381538281f3fe730000000000000000000000000000000000000000301460806040525f5ffdfea26469706673582212209f601c86d8ce9f52c86deccb2eef5abf7ae294a6f89835b73a334ebbdc2dedca64736f6c63430008230033", + "deployedBytecode": "0x730000000000000000000000000000000000000000301460806040525f5ffdfea26469706673582212209f601c86d8ce9f52c86deccb2eef5abf7ae294a6f89835b73a334ebbdc2dedca64736f6c63430008230033", "linkReferences": {}, "deployedLinkReferences": {} } diff --git a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/Calldata.json b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/Calldata.json similarity index 66% rename from dependencies/@openzeppelin-contracts-5.5.0/build/contracts/Calldata.json rename to dependencies/@openzeppelin-contracts-5.7.0/build/contracts/Calldata.json index d1b4bcb..873ff5f 100644 --- a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/Calldata.json +++ b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/Calldata.json @@ -3,8 +3,8 @@ "contractName": "Calldata", "sourceName": "contracts/utils/Calldata.sol", "abi": [], - "bytecode": "0x60556032600b8282823980515f1a607314602657634e487b7160e01b5f525f60045260245ffd5b305f52607381538281f3fe730000000000000000000000000000000000000000301460806040525f5ffdfea2646970667358221220506f6e918ef26ff04a4fe97cde177d339251c154181b745c2c11e6c64788831c64736f6c634300081b0033", - "deployedBytecode": "0x730000000000000000000000000000000000000000301460806040525f5ffdfea2646970667358221220506f6e918ef26ff04a4fe97cde177d339251c154181b745c2c11e6c64788831c64736f6c634300081b0033", + "bytecode": "0x60556032600b8282823980515f1a607314602657634e487b7160e01b5f525f60045260245ffd5b305f52607381538281f3fe730000000000000000000000000000000000000000301460806040525f5ffdfea2646970667358221220b9f3ca3831c274d85a540ad896b927a61d9570e2f987be5021536dffd4582bb964736f6c63430008230033", + "deployedBytecode": "0x730000000000000000000000000000000000000000301460806040525f5ffdfea2646970667358221220b9f3ca3831c274d85a540ad896b927a61d9570e2f987be5021536dffd4582bb964736f6c63430008230033", "linkReferences": {}, "deployedLinkReferences": {} } diff --git a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/Checkpoints.json b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/Checkpoints.json similarity index 71% rename from dependencies/@openzeppelin-contracts-5.5.0/build/contracts/Checkpoints.json rename to dependencies/@openzeppelin-contracts-5.7.0/build/contracts/Checkpoints.json index 904f36b..7e1a6f8 100644 --- a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/Checkpoints.json +++ b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/Checkpoints.json @@ -9,8 +9,8 @@ "type": "error" } ], - "bytecode": "0x60556032600b8282823980515f1a607314602657634e487b7160e01b5f525f60045260245ffd5b305f52607381538281f3fe730000000000000000000000000000000000000000301460806040525f5ffdfea2646970667358221220998e099a633eaacbad6e676d9375c1bd8239e3bd9efc134c20aa0fd4d59058a164736f6c634300081b0033", - "deployedBytecode": "0x730000000000000000000000000000000000000000301460806040525f5ffdfea2646970667358221220998e099a633eaacbad6e676d9375c1bd8239e3bd9efc134c20aa0fd4d59058a164736f6c634300081b0033", + "bytecode": "0x60556032600b8282823980515f1a607314602657634e487b7160e01b5f525f60045260245ffd5b305f52607381538281f3fe730000000000000000000000000000000000000000301460806040525f5ffdfea26469706673582212201fbf041e1c15dc8a1f2305bb765999f6ca3e4077db4c78a6ff717615b063be4d64736f6c63430008230033", + "deployedBytecode": "0x730000000000000000000000000000000000000000301460806040525f5ffdfea26469706673582212201fbf041e1c15dc8a1f2305bb765999f6ca3e4077db4c78a6ff717615b063be4d64736f6c63430008230033", "linkReferences": {}, "deployedLinkReferences": {} } diff --git a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/CircularBuffer.json b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/CircularBuffer.json similarity index 71% rename from dependencies/@openzeppelin-contracts-5.5.0/build/contracts/CircularBuffer.json rename to dependencies/@openzeppelin-contracts-5.7.0/build/contracts/CircularBuffer.json index 16542bf..59c322a 100644 --- a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/CircularBuffer.json +++ b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/CircularBuffer.json @@ -9,8 +9,8 @@ "type": "error" } ], - "bytecode": "0x60556032600b8282823980515f1a607314602657634e487b7160e01b5f525f60045260245ffd5b305f52607381538281f3fe730000000000000000000000000000000000000000301460806040525f5ffdfea2646970667358221220e9a90e2b93ab9d314a9470eb70556ac3631a8ae4c037fe4c8c1699b617a509ec64736f6c634300081b0033", - "deployedBytecode": "0x730000000000000000000000000000000000000000301460806040525f5ffdfea2646970667358221220e9a90e2b93ab9d314a9470eb70556ac3631a8ae4c037fe4c8c1699b617a509ec64736f6c634300081b0033", + "bytecode": "0x60556032600b8282823980515f1a607314602657634e487b7160e01b5f525f60045260245ffd5b305f52607381538281f3fe730000000000000000000000000000000000000000301460806040525f5ffdfea26469706673582212201d55e2fff2036bd8e8f1fddb596bc00d44b894b0dc040a17aef7210a56a4378d64736f6c63430008230033", + "deployedBytecode": "0x730000000000000000000000000000000000000000301460806040525f5ffdfea26469706673582212201d55e2fff2036bd8e8f1fddb596bc00d44b894b0dc040a17aef7210a56a4378d64736f6c63430008230033", "linkReferences": {}, "deployedLinkReferences": {} } diff --git a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/Clones.json b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/Clones.json similarity index 70% rename from dependencies/@openzeppelin-contracts-5.5.0/build/contracts/Clones.json rename to dependencies/@openzeppelin-contracts-5.7.0/build/contracts/Clones.json index 3f62cc1..60042f8 100644 --- a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/Clones.json +++ b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/Clones.json @@ -9,8 +9,8 @@ "type": "error" } ], - "bytecode": "0x60556032600b8282823980515f1a607314602657634e487b7160e01b5f525f60045260245ffd5b305f52607381538281f3fe730000000000000000000000000000000000000000301460806040525f5ffdfea2646970667358221220095412ba622fe112c650168531a075074504501470e61dd30d95166d16f3739564736f6c634300081b0033", - "deployedBytecode": "0x730000000000000000000000000000000000000000301460806040525f5ffdfea2646970667358221220095412ba622fe112c650168531a075074504501470e61dd30d95166d16f3739564736f6c634300081b0033", + "bytecode": "0x60556032600b8282823980515f1a607314602657634e487b7160e01b5f525f60045260245ffd5b305f52607381538281f3fe730000000000000000000000000000000000000000301460806040525f5ffdfea2646970667358221220e672599e09415c6cb8991107466c9301f18e119afbb6e2906c1641df0759471e64736f6c63430008230033", + "deployedBytecode": "0x730000000000000000000000000000000000000000301460806040525f5ffdfea2646970667358221220e672599e09415c6cb8991107466c9301f18e119afbb6e2906c1641df0759471e64736f6c63430008230033", "linkReferences": {}, "deployedLinkReferences": {} } diff --git a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/Comparators.json b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/Comparators.json similarity index 66% rename from dependencies/@openzeppelin-contracts-5.5.0/build/contracts/Comparators.json rename to dependencies/@openzeppelin-contracts-5.7.0/build/contracts/Comparators.json index f490d3c..54b4ac8 100644 --- a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/Comparators.json +++ b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/Comparators.json @@ -3,8 +3,8 @@ "contractName": "Comparators", "sourceName": "contracts/utils/Comparators.sol", "abi": [], - "bytecode": "0x60556032600b8282823980515f1a607314602657634e487b7160e01b5f525f60045260245ffd5b305f52607381538281f3fe730000000000000000000000000000000000000000301460806040525f5ffdfea2646970667358221220ada21df4adb0d4c2668e55a8c600d50cf0965c7272ac0c34d8f031672b648a1864736f6c634300081b0033", - "deployedBytecode": "0x730000000000000000000000000000000000000000301460806040525f5ffdfea2646970667358221220ada21df4adb0d4c2668e55a8c600d50cf0965c7272ac0c34d8f031672b648a1864736f6c634300081b0033", + "bytecode": "0x60556032600b8282823980515f1a607314602657634e487b7160e01b5f525f60045260245ffd5b305f52607381538281f3fe730000000000000000000000000000000000000000301460806040525f5ffdfea264697066735822122085f04bcdaee813a5a7e4c97df184b45898c8afb77ba007b3716fd121a41fa58464736f6c63430008230033", + "deployedBytecode": "0x730000000000000000000000000000000000000000301460806040525f5ffdfea264697066735822122085f04bcdaee813a5a7e4c97df184b45898c8afb77ba007b3716fd121a41fa58464736f6c63430008230033", "linkReferences": {}, "deployedLinkReferences": {} } diff --git a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/Context.json b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/Context.json similarity index 100% rename from dependencies/@openzeppelin-contracts-5.5.0/build/contracts/Context.json rename to dependencies/@openzeppelin-contracts-5.7.0/build/contracts/Context.json diff --git a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/Create2.json b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/Create2.json similarity index 70% rename from dependencies/@openzeppelin-contracts-5.5.0/build/contracts/Create2.json rename to dependencies/@openzeppelin-contracts-5.7.0/build/contracts/Create2.json index 3529a37..05a33b5 100644 --- a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/Create2.json +++ b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/Create2.json @@ -9,8 +9,8 @@ "type": "error" } ], - "bytecode": "0x60556032600b8282823980515f1a607314602657634e487b7160e01b5f525f60045260245ffd5b305f52607381538281f3fe730000000000000000000000000000000000000000301460806040525f5ffdfea26469706673582212201ff79331a3a2776f3f25b3db7058c03e3971b263bfb0684760d3453f46815cf764736f6c634300081b0033", - "deployedBytecode": "0x730000000000000000000000000000000000000000301460806040525f5ffdfea26469706673582212201ff79331a3a2776f3f25b3db7058c03e3971b263bfb0684760d3453f46815cf764736f6c634300081b0033", + "bytecode": "0x60556032600b8282823980515f1a607314602657634e487b7160e01b5f525f60045260245ffd5b305f52607381538281f3fe730000000000000000000000000000000000000000301460806040525f5ffdfea2646970667358221220bf4bb5db5e8837dd8dea2cc9ec82f0ee3863e31c4a57003ffda3d4cd2efdae7e64736f6c63430008230033", + "deployedBytecode": "0x730000000000000000000000000000000000000000301460806040525f5ffdfea2646970667358221220bf4bb5db5e8837dd8dea2cc9ec82f0ee3863e31c4a57003ffda3d4cd2efdae7e64736f6c63430008230033", "linkReferences": {}, "deployedLinkReferences": {} } diff --git a/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/Create3.json b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/Create3.json new file mode 100644 index 0000000..10ffb5c --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/Create3.json @@ -0,0 +1,16 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "Create3", + "sourceName": "contracts/utils/Create3.sol", + "abi": [ + { + "inputs": [], + "name": "Create3EmptyBytecode", + "type": "error" + } + ], + "bytecode": "0x60556032600b8282823980515f1a607314602657634e487b7160e01b5f525f60045260245ffd5b305f52607381538281f3fe730000000000000000000000000000000000000000301460806040525f5ffdfea264697066735822122095a982c544c06c7fab9ef4bfc2348064005c0afa344a4817a4caae43f7dd598564736f6c63430008230033", + "deployedBytecode": "0x730000000000000000000000000000000000000000301460806040525f5ffdfea264697066735822122095a982c544c06c7fab9ef4bfc2348064005c0afa344a4817a4caae43f7dd598564736f6c63430008230033", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/CrosschainLinked.json b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/CrosschainLinked.json new file mode 100644 index 0000000..1fcf033 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/CrosschainLinked.json @@ -0,0 +1,142 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "CrosschainLinked", + "sourceName": "contracts/crosschain/CrosschainLinked.sol", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "gateway", + "type": "address" + }, + { + "internalType": "bytes", + "name": "sender", + "type": "bytes" + } + ], + "name": "ERC7786RecipientUnauthorizedGateway", + "type": "error" + }, + { + "inputs": [], + "name": "InteroperableAddressEmptyReferenceAndAddress", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "name": "InteroperableAddressParsingError", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "chain", + "type": "bytes" + } + ], + "name": "LinkAlreadyRegistered", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint8", + "name": "bits", + "type": "uint8" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "SafeCastOverflowedUintDowncast", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "gateway", + "type": "address" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "counterpart", + "type": "bytes" + } + ], + "name": "LinkRegistered", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "chain", + "type": "bytes" + } + ], + "name": "getLink", + "outputs": [ + { + "internalType": "address", + "name": "gateway", + "type": "address" + }, + { + "internalType": "bytes", + "name": "counterpart", + "type": "bytes" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "receiveId", + "type": "bytes32" + }, + { + "internalType": "bytes", + "name": "sender", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "payload", + "type": "bytes" + } + ], + "name": "receiveMessage", + "outputs": [ + { + "internalType": "bytes4", + "name": "", + "type": "bytes4" + } + ], + "stateMutability": "payable", + "type": "function" + } + ], + "bytecode": "0x", + "deployedBytecode": "0x", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/CrosschainRemoteExecutor.json b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/CrosschainRemoteExecutor.json new file mode 100644 index 0000000..8810041 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/CrosschainRemoteExecutor.json @@ -0,0 +1,196 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "CrosschainRemoteExecutor", + "sourceName": "contracts/crosschain/CrosschainRemoteExecutor.sol", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "initialGateway", + "type": "address" + }, + { + "internalType": "bytes", + "name": "initialController", + "type": "bytes" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [], + "name": "AccessRestricted", + "type": "error" + }, + { + "inputs": [], + "name": "ERC7579DecodingError", + "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": "address", + "name": "gateway", + "type": "address" + }, + { + "internalType": "bytes", + "name": "sender", + "type": "bytes" + } + ], + "name": "ERC7786RecipientUnauthorizedGateway", + "type": "error" + }, + { + "inputs": [], + "name": "FailedCall", + "type": "error" + }, + { + "inputs": [], + "name": "OutOfRangeAccess", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "gateway", + "type": "address" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "controller", + "type": "bytes" + } + ], + "name": "CrosschainControllerSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "batchExecutionIndex", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "returndata", + "type": "bytes" + } + ], + "name": "ERC7579TryExecuteFail", + "type": "event" + }, + { + "inputs": [], + "name": "controller", + "outputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "gateway", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "receiveId", + "type": "bytes32" + }, + { + "internalType": "bytes", + "name": "sender", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "payload", + "type": "bytes" + } + ], + "name": "receiveMessage", + "outputs": [ + { + "internalType": "bytes4", + "name": "", + "type": "bytes4" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newGateway", + "type": "address" + }, + { + "internalType": "bytes", + "name": "newController", + "type": "bytes" + } + ], + "name": "reconfigure", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } + ], + "bytecode": "0x608060405234801561000f575f5ffd5b5060405161136a38038061136a83398101604081905261002e9161011e565b610038828261003f565b50506103a4565b60405163dc680a0f60e01b81525f60048201526001600160a01b0383169063dc680a0f90602401602060405180830381865afa158015610081573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906100a591906101ed565b505f80546001600160a01b0319166001600160a01b03841617905560016100cc82826102a2565b507f0cff5007efcafd99cdeb44bb49f05a247d4147bd8c51588a483d7598b782bd0582826040516100fe929190610360565b60405180910390a15050565b634e487b7160e01b5f52604160045260245ffd5b5f5f6040838503121561012f575f5ffd5b82516001600160a01b0381168114610145575f5ffd5b60208401519092506001600160401b03811115610160575f5ffd5b8301601f81018513610170575f5ffd5b80516001600160401b038111156101895761018961010a565b604051601f8201601f19908116603f011681016001600160401b03811182821017156101b7576101b761010a565b6040528181528282016020018710156101ce575f5ffd5b8160208401602083015e5f602083830101528093505050509250929050565b5f602082840312156101fd575f5ffd5b8151801515811461020c575f5ffd5b9392505050565b600181811c9082168061022757607f821691505b60208210810361024557634e487b7160e01b5f52602260045260245ffd5b50919050565b601f82111561029d578282111561029d57805f5260205f20601f840160051c602085101561027657505f5b90810190601f840160051c035f5b81811015610299575f83820155600101610284565b5050505b505050565b81516001600160401b038111156102bb576102bb61010a565b6102cf816102c98454610213565b8461024b565b6020601f821160018114610301575f83156102ea5750848201515b5f19600385901b1c1916600184901b178455610359565b5f84815260208120601f198516915b828110156103305787850151825560209485019460019092019101610310565b508482101561034d57868401515f19600387901b60f8161c191681555b505060018360011b0184555b5050505050565b60018060a01b0383168152604060208201525f82518060408401528060208501606085015e5f606082850101526060601f19601f8301168401019150509392505050565b610fb9806103b15f395ff3fe60806040526004361061003e575f3560e01c8063116191b6146100425780632432ef261461006d578063362ad6c014610099578063f77c4791146100ba575b5f5ffd5b34801561004d575f5ffd5b505f546040516001600160a01b0390911681526020015b60405180910390f35b61008061007b366004610abb565b6100db565b6040516001600160e01b03199091168152602001610064565b3480156100a4575f5ffd5b506100b86100b3366004610b63565b610133565b005b3480156100c5575f5ffd5b506100ce610161565b6040516100649190610c55565b5f6100e73386866101f1565b6101135733858560405163cddea73760e01b815260040161010a93929190610c67565b60405180910390fd5b61012133878787878761026e565b50631219779360e11b95945050505050565b3330146101535760405163c240bad360e01b815260040160405180910390fd5b61015d8282610337565b5050565b60606001805461017090610ca6565b80601f016020809104026020016040519081016040528092919081815260200182805461019c90610ca6565b80156101e75780601f106101be576101008083540402835291602001916101e7565b820191905f5260205f20905b8154815290600101906020018083116101ca57829003601f168201915b5050505050905090565b5f836001600160a01b031661020d5f546001600160a01b031690565b6001600160a01b0316148015610266575061026683838080601f0160208091040260200160405190810160405280939291908181526020018383808284375f920191909152506102609250610161915050565b90610402565b949350505050565b5f8061028e6102806020838688610cde565b61028991610d05565b61042a565b5091935091503690505f6102a58560208189610cde565b90925090506001600160f81b031984166102ca576102c4828285610468565b5061032b565b6001600160f81b03198416600160f81b036102ea576102c48282856104e4565b6001600160f81b031980851603610306576102c4828285610615565b6040516358df354b60e11b81526001600160f81b03198516600482015260240161010a565b50505050505050505050565b60405163dc680a0f60e01b81525f60048201526001600160a01b0383169063dc680a0f90602401602060405180830381865afa158015610379573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061039d9190610d22565b505f80546001600160a01b0319166001600160a01b03841617905560016103c48282610d9f565b507f0cff5007efcafd99cdeb44bb49f05a247d4147bd8c51588a483d7598b782bd0582826040516103f6929190610e5e565b60405180910390a15050565b5f81518351148015610421575081805190602001208380519060200120145b90505b92915050565b5f5f5f5f610438855f61068b565b61044386600161068b565b61044e8760066106c3565b61045988600a6106fb565b93509350935093509193509193565b60605f5f365f6104788888610736565b6040805160018082528183019092529498509296509094509250816020015b60608152602001906001900390816104975790505094506104bc5f878686868661077a565b855f815181106104ce576104ce610e81565b6020026020010181905250505050509392505050565b6060365f6104f2868661080c565b90925090508067ffffffffffffffff81111561051057610510610b4f565b60405190808252806020026020018201604052801561054357816020015b606081526020019060019003908161052e5790505b5092505f5b8181101561060b576105e6818685858581811061056757610567610e81565b90506020028101906105799190610e95565b610587906020810190610eb3565b86868681811061059957610599610e81565b90506020028101906105ab9190610e95565b602001358787878181106105c1576105c1610e81565b90506020028101906105d39190610e95565b6105e1906040810190610ecc565b61077a565b8482815181106105f8576105f8610e81565b6020908102919091010152600101610548565b5050509392505050565b60605f365f61062487876108d2565b6040805160018082528183019092529396509194509250816020015b60608152602001906001900390816106405790505093506106645f868585856108fc565b845f8151811061067657610676610e81565b60200260200101819052505050509392505050565b5f601f8260ff1611156106b157604051631dd4bb1b60e11b815260040160405180910390fd5b506008021b6001600160f81b03191690565b5f601c8260ff1611156106e957604051631dd4bb1b60e11b815260040160405180910390fd5b506008021b6001600160e01b03191690565b5f600a8260ff16111561072157604051631dd4bb1b60e11b815260040160405180910390fd5b506008021b69ffffffffffffffffffff191690565b5f8036816107448587610f0f565b60601c9350610757603460148789610cde565b61076091610d05565b925061076f8560348189610cde565b949793965094505050565b60605f806001600160a01b038716156107935786610795565b305b6001600160a01b03168686866040516107af929190610f5c565b5f6040518083038185875af1925050503d805f81146107e9576040519150601f19603f3d011682016040523d82523d5f602084013e6107ee565b606091505b50915091506107ff8989848461098a565b9998505050505050505050565b365f8260208110156108315760405163eb0bcc5d60e01b815260040160405180910390fd5b5f61083f6020828789610cde565b61084891610d05565b9050601f19820181111561086f5760405163eb0bcc5d60e01b815260040160405180910390fd5b5f61087f6020830183888a610cde565b61088891610d05565b905067ffffffffffffffff8111806108a7575080602002602083850303105b156108c55760405163eb0bcc5d60e01b815260040160405180910390fd5b9501602001959350505050565b5f36816108df8486610f0f565b60601c92506108f18460148188610cde565b915091509250925092565b60605f806001600160a01b038616156109155785610917565b305b6001600160a01b03168585604051610930929190610f5c565b5f60405180830381855af49150503d805f8114610968576040519150601f19603f3d011682016040523d82523d5f602084013e61096d565b606091505b509150915061097e8888848461098a565b98975050505050505050565b60606001600160f81b031984166109ab576109a58383610a31565b50610a29565b6001600160f81b03198416600160f81b03610a0457826109ff577f2eea2f51f83910481f4b5ba28b7003a6e045d4b59f67dfff8d4c90119405008985836040516109f6929190610f6b565b60405180910390a15b610a29565b6040516323a2408560e01b81526001600160f81b03198516600482015260240161010a565b509392505050565b60608215610a40575080610424565b815115610a5557610a5082610a6e565b610424565b60405163d6bda27560e01b815260040160405180910390fd5b805160208201fd5b5f5f83601f840112610a86575f5ffd5b50813567ffffffffffffffff811115610a9d575f5ffd5b602083019150836020828501011115610ab4575f5ffd5b9250929050565b5f5f5f5f5f60608688031215610acf575f5ffd5b85359450602086013567ffffffffffffffff811115610aec575f5ffd5b610af888828901610a76565b909550935050604086013567ffffffffffffffff811115610b17575f5ffd5b610b2388828901610a76565b969995985093965092949392505050565b80356001600160a01b0381168114610b4a575f5ffd5b919050565b634e487b7160e01b5f52604160045260245ffd5b5f5f60408385031215610b74575f5ffd5b610b7d83610b34565b9150602083013567ffffffffffffffff811115610b98575f5ffd5b8301601f81018513610ba8575f5ffd5b803567ffffffffffffffff811115610bc257610bc2610b4f565b604051601f8201601f19908116603f0116810167ffffffffffffffff81118282101715610bf157610bf1610b4f565b604052818152828201602001871015610c08575f5ffd5b816020840160208301375f602083830101528093505050509250929050565b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b602081525f6104216020830184610c27565b6001600160a01b03841681526040602082018190528101829052818360608301375f818301606090810191909152601f909201601f1916010192915050565b600181811c90821680610cba57607f821691505b602082108103610cd857634e487b7160e01b5f52602260045260245ffd5b50919050565b5f5f85851115610cec575f5ffd5b83861115610cf8575f5ffd5b5050820193919092039150565b80356020831015610424575f19602084900360031b1b1692915050565b5f60208284031215610d32575f5ffd5b81518015158114610d41575f5ffd5b9392505050565b601f821115610d9a5782821115610d9a57805f5260205f20601f840160051c6020851015610d7357505f5b90810190601f840160051c035f5b81811015610d96575f83820155600101610d81565b5050505b505050565b815167ffffffffffffffff811115610db957610db9610b4f565b610dcd81610dc78454610ca6565b84610d48565b6020601f821160018114610dff575f8315610de85750848201515b5f19600385901b1c1916600184901b178455610e57565b5f84815260208120601f198516915b82811015610e2e5787850151825560209485019460019092019101610e0e565b5084821015610e4b57868401515f19600387901b60f8161c191681555b505060018360011b0184555b5050505050565b6001600160a01b03831681526040602082018190525f9061026690830184610c27565b634e487b7160e01b5f52603260045260245ffd5b5f8235605e19833603018112610ea9575f5ffd5b9190910192915050565b5f60208284031215610ec3575f5ffd5b61042182610b34565b5f5f8335601e19843603018112610ee1575f5ffd5b83018035915067ffffffffffffffff821115610efb575f5ffd5b602001915036819003821315610ab4575f5ffd5b80356bffffffffffffffffffffffff198116906014841015610f55576bffffffffffffffffffffffff196bffffffffffffffffffffffff198560140360031b1b82161691505b5092915050565b818382375f9101908152919050565b828152604060208201525f6102666040830184610c2756fea264697066735822122067416223f76bee200783bec215b0c583bdf0781afa4b0a9353f31b4a2fc2b72b64736f6c63430008230033", + "deployedBytecode": "0x60806040526004361061003e575f3560e01c8063116191b6146100425780632432ef261461006d578063362ad6c014610099578063f77c4791146100ba575b5f5ffd5b34801561004d575f5ffd5b505f546040516001600160a01b0390911681526020015b60405180910390f35b61008061007b366004610abb565b6100db565b6040516001600160e01b03199091168152602001610064565b3480156100a4575f5ffd5b506100b86100b3366004610b63565b610133565b005b3480156100c5575f5ffd5b506100ce610161565b6040516100649190610c55565b5f6100e73386866101f1565b6101135733858560405163cddea73760e01b815260040161010a93929190610c67565b60405180910390fd5b61012133878787878761026e565b50631219779360e11b95945050505050565b3330146101535760405163c240bad360e01b815260040160405180910390fd5b61015d8282610337565b5050565b60606001805461017090610ca6565b80601f016020809104026020016040519081016040528092919081815260200182805461019c90610ca6565b80156101e75780601f106101be576101008083540402835291602001916101e7565b820191905f5260205f20905b8154815290600101906020018083116101ca57829003601f168201915b5050505050905090565b5f836001600160a01b031661020d5f546001600160a01b031690565b6001600160a01b0316148015610266575061026683838080601f0160208091040260200160405190810160405280939291908181526020018383808284375f920191909152506102609250610161915050565b90610402565b949350505050565b5f8061028e6102806020838688610cde565b61028991610d05565b61042a565b5091935091503690505f6102a58560208189610cde565b90925090506001600160f81b031984166102ca576102c4828285610468565b5061032b565b6001600160f81b03198416600160f81b036102ea576102c48282856104e4565b6001600160f81b031980851603610306576102c4828285610615565b6040516358df354b60e11b81526001600160f81b03198516600482015260240161010a565b50505050505050505050565b60405163dc680a0f60e01b81525f60048201526001600160a01b0383169063dc680a0f90602401602060405180830381865afa158015610379573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061039d9190610d22565b505f80546001600160a01b0319166001600160a01b03841617905560016103c48282610d9f565b507f0cff5007efcafd99cdeb44bb49f05a247d4147bd8c51588a483d7598b782bd0582826040516103f6929190610e5e565b60405180910390a15050565b5f81518351148015610421575081805190602001208380519060200120145b90505b92915050565b5f5f5f5f610438855f61068b565b61044386600161068b565b61044e8760066106c3565b61045988600a6106fb565b93509350935093509193509193565b60605f5f365f6104788888610736565b6040805160018082528183019092529498509296509094509250816020015b60608152602001906001900390816104975790505094506104bc5f878686868661077a565b855f815181106104ce576104ce610e81565b6020026020010181905250505050509392505050565b6060365f6104f2868661080c565b90925090508067ffffffffffffffff81111561051057610510610b4f565b60405190808252806020026020018201604052801561054357816020015b606081526020019060019003908161052e5790505b5092505f5b8181101561060b576105e6818685858581811061056757610567610e81565b90506020028101906105799190610e95565b610587906020810190610eb3565b86868681811061059957610599610e81565b90506020028101906105ab9190610e95565b602001358787878181106105c1576105c1610e81565b90506020028101906105d39190610e95565b6105e1906040810190610ecc565b61077a565b8482815181106105f8576105f8610e81565b6020908102919091010152600101610548565b5050509392505050565b60605f365f61062487876108d2565b6040805160018082528183019092529396509194509250816020015b60608152602001906001900390816106405790505093506106645f868585856108fc565b845f8151811061067657610676610e81565b60200260200101819052505050509392505050565b5f601f8260ff1611156106b157604051631dd4bb1b60e11b815260040160405180910390fd5b506008021b6001600160f81b03191690565b5f601c8260ff1611156106e957604051631dd4bb1b60e11b815260040160405180910390fd5b506008021b6001600160e01b03191690565b5f600a8260ff16111561072157604051631dd4bb1b60e11b815260040160405180910390fd5b506008021b69ffffffffffffffffffff191690565b5f8036816107448587610f0f565b60601c9350610757603460148789610cde565b61076091610d05565b925061076f8560348189610cde565b949793965094505050565b60605f806001600160a01b038716156107935786610795565b305b6001600160a01b03168686866040516107af929190610f5c565b5f6040518083038185875af1925050503d805f81146107e9576040519150601f19603f3d011682016040523d82523d5f602084013e6107ee565b606091505b50915091506107ff8989848461098a565b9998505050505050505050565b365f8260208110156108315760405163eb0bcc5d60e01b815260040160405180910390fd5b5f61083f6020828789610cde565b61084891610d05565b9050601f19820181111561086f5760405163eb0bcc5d60e01b815260040160405180910390fd5b5f61087f6020830183888a610cde565b61088891610d05565b905067ffffffffffffffff8111806108a7575080602002602083850303105b156108c55760405163eb0bcc5d60e01b815260040160405180910390fd5b9501602001959350505050565b5f36816108df8486610f0f565b60601c92506108f18460148188610cde565b915091509250925092565b60605f806001600160a01b038616156109155785610917565b305b6001600160a01b03168585604051610930929190610f5c565b5f60405180830381855af49150503d805f8114610968576040519150601f19603f3d011682016040523d82523d5f602084013e61096d565b606091505b509150915061097e8888848461098a565b98975050505050505050565b60606001600160f81b031984166109ab576109a58383610a31565b50610a29565b6001600160f81b03198416600160f81b03610a0457826109ff577f2eea2f51f83910481f4b5ba28b7003a6e045d4b59f67dfff8d4c90119405008985836040516109f6929190610f6b565b60405180910390a15b610a29565b6040516323a2408560e01b81526001600160f81b03198516600482015260240161010a565b509392505050565b60608215610a40575080610424565b815115610a5557610a5082610a6e565b610424565b60405163d6bda27560e01b815260040160405180910390fd5b805160208201fd5b5f5f83601f840112610a86575f5ffd5b50813567ffffffffffffffff811115610a9d575f5ffd5b602083019150836020828501011115610ab4575f5ffd5b9250929050565b5f5f5f5f5f60608688031215610acf575f5ffd5b85359450602086013567ffffffffffffffff811115610aec575f5ffd5b610af888828901610a76565b909550935050604086013567ffffffffffffffff811115610b17575f5ffd5b610b2388828901610a76565b969995985093965092949392505050565b80356001600160a01b0381168114610b4a575f5ffd5b919050565b634e487b7160e01b5f52604160045260245ffd5b5f5f60408385031215610b74575f5ffd5b610b7d83610b34565b9150602083013567ffffffffffffffff811115610b98575f5ffd5b8301601f81018513610ba8575f5ffd5b803567ffffffffffffffff811115610bc257610bc2610b4f565b604051601f8201601f19908116603f0116810167ffffffffffffffff81118282101715610bf157610bf1610b4f565b604052818152828201602001871015610c08575f5ffd5b816020840160208301375f602083830101528093505050509250929050565b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b602081525f6104216020830184610c27565b6001600160a01b03841681526040602082018190528101829052818360608301375f818301606090810191909152601f909201601f1916010192915050565b600181811c90821680610cba57607f821691505b602082108103610cd857634e487b7160e01b5f52602260045260245ffd5b50919050565b5f5f85851115610cec575f5ffd5b83861115610cf8575f5ffd5b5050820193919092039150565b80356020831015610424575f19602084900360031b1b1692915050565b5f60208284031215610d32575f5ffd5b81518015158114610d41575f5ffd5b9392505050565b601f821115610d9a5782821115610d9a57805f5260205f20601f840160051c6020851015610d7357505f5b90810190601f840160051c035f5b81811015610d96575f83820155600101610d81565b5050505b505050565b815167ffffffffffffffff811115610db957610db9610b4f565b610dcd81610dc78454610ca6565b84610d48565b6020601f821160018114610dff575f8315610de85750848201515b5f19600385901b1c1916600184901b178455610e57565b5f84815260208120601f198516915b82811015610e2e5787850151825560209485019460019092019101610e0e565b5084821015610e4b57868401515f19600387901b60f8161c191681555b505060018360011b0184555b5050505050565b6001600160a01b03831681526040602082018190525f9061026690830184610c27565b634e487b7160e01b5f52603260045260245ffd5b5f8235605e19833603018112610ea9575f5ffd5b9190910192915050565b5f60208284031215610ec3575f5ffd5b61042182610b34565b5f5f8335601e19843603018112610ee1575f5ffd5b83018035915067ffffffffffffffff821115610efb575f5ffd5b602001915036819003821315610ab4575f5ffd5b80356bffffffffffffffffffffffff198116906014841015610f55576bffffffffffffffffffffffff196bffffffffffffffffffffffff198560140360031b1b82161691505b5092915050565b818382375f9101908152919050565b828152604060208201525f6102666040830184610c2756fea264697066735822122067416223f76bee200783bec215b0c583bdf0781afa4b0a9353f31b4a2fc2b72b64736f6c63430008230033", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/DoubleEndedQueue.json b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/DoubleEndedQueue.json similarity index 67% rename from dependencies/@openzeppelin-contracts-5.5.0/build/contracts/DoubleEndedQueue.json rename to dependencies/@openzeppelin-contracts-5.7.0/build/contracts/DoubleEndedQueue.json index a021e91..c4da6b9 100644 --- a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/DoubleEndedQueue.json +++ b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/DoubleEndedQueue.json @@ -3,8 +3,8 @@ "contractName": "DoubleEndedQueue", "sourceName": "contracts/utils/structs/DoubleEndedQueue.sol", "abi": [], - "bytecode": "0x60556032600b8282823980515f1a607314602657634e487b7160e01b5f525f60045260245ffd5b305f52607381538281f3fe730000000000000000000000000000000000000000301460806040525f5ffdfea2646970667358221220fec2a619b619939a4c620cfa859a72e7778a25891b435c1dbf62ef97f0e599d664736f6c634300081b0033", - "deployedBytecode": "0x730000000000000000000000000000000000000000301460806040525f5ffdfea2646970667358221220fec2a619b619939a4c620cfa859a72e7778a25891b435c1dbf62ef97f0e599d664736f6c634300081b0033", + "bytecode": "0x60556032600b8282823980515f1a607314602657634e487b7160e01b5f525f60045260245ffd5b305f52607381538281f3fe730000000000000000000000000000000000000000301460806040525f5ffdfea264697066735822122020161bd5a425d35ad05739589e6c418c46e387509a8388ec21be4f7c22309c9164736f6c63430008230033", + "deployedBytecode": "0x730000000000000000000000000000000000000000301460806040525f5ffdfea264697066735822122020161bd5a425d35ad05739589e6c418c46e387509a8388ec21be4f7c22309c9164736f6c63430008230033", "linkReferences": {}, "deployedLinkReferences": {} } diff --git a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/ECDSA.json b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/ECDSA.json similarity index 81% rename from dependencies/@openzeppelin-contracts-5.5.0/build/contracts/ECDSA.json rename to dependencies/@openzeppelin-contracts-5.7.0/build/contracts/ECDSA.json index 8c85fc7..1df487c 100644 --- a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/ECDSA.json +++ b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/ECDSA.json @@ -31,8 +31,8 @@ "type": "error" } ], - "bytecode": "0x60556032600b8282823980515f1a607314602657634e487b7160e01b5f525f60045260245ffd5b305f52607381538281f3fe730000000000000000000000000000000000000000301460806040525f5ffdfea2646970667358221220f8fbf1d1740affd54e7a1744a3190b5f3da73398bc63fcc390cbb34b611d65fb64736f6c634300081b0033", - "deployedBytecode": "0x730000000000000000000000000000000000000000301460806040525f5ffdfea2646970667358221220f8fbf1d1740affd54e7a1744a3190b5f3da73398bc63fcc390cbb34b611d65fb64736f6c634300081b0033", + "bytecode": "0x60556032600b8282823980515f1a607314602657634e487b7160e01b5f525f60045260245ffd5b305f52607381538281f3fe730000000000000000000000000000000000000000301460806040525f5ffdfea264697066735822122070b2f3206777877eb6b5b14304849dafbbb73534cd354c784e547290994463ac64736f6c63430008230033", + "deployedBytecode": "0x730000000000000000000000000000000000000000301460806040525f5ffdfea264697066735822122070b2f3206777877eb6b5b14304849dafbbb73534cd354c784e547290994463ac64736f6c63430008230033", "linkReferences": {}, "deployedLinkReferences": {} } diff --git a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/EIP712.json b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/EIP712.json similarity index 100% rename from dependencies/@openzeppelin-contracts-5.5.0/build/contracts/EIP712.json rename to dependencies/@openzeppelin-contracts-5.7.0/build/contracts/EIP712.json diff --git a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/EIP7702Utils.json b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/EIP7702Utils.json similarity index 67% rename from dependencies/@openzeppelin-contracts-5.5.0/build/contracts/EIP7702Utils.json rename to dependencies/@openzeppelin-contracts-5.7.0/build/contracts/EIP7702Utils.json index 6089833..21bba93 100644 --- a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/EIP7702Utils.json +++ b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/EIP7702Utils.json @@ -3,8 +3,8 @@ "contractName": "EIP7702Utils", "sourceName": "contracts/account/utils/EIP7702Utils.sol", "abi": [], - "bytecode": "0x60556032600b8282823980515f1a607314602657634e487b7160e01b5f525f60045260245ffd5b305f52607381538281f3fe730000000000000000000000000000000000000000301460806040525f5ffdfea26469706673582212207ef191e73d145361e32e0d1cff3dab76e0f69c9f0986c4781710c9e57e329b2264736f6c634300081b0033", - "deployedBytecode": "0x730000000000000000000000000000000000000000301460806040525f5ffdfea26469706673582212207ef191e73d145361e32e0d1cff3dab76e0f69c9f0986c4781710c9e57e329b2264736f6c634300081b0033", + "bytecode": "0x60556032600b8282823980515f1a607314602657634e487b7160e01b5f525f60045260245ffd5b305f52607381538281f3fe730000000000000000000000000000000000000000301460806040525f5ffdfea2646970667358221220441d34d1c619df3c0ac9164ef28fbeb3af0052ff3efdd7913b73bf53e77b23e064736f6c63430008230033", + "deployedBytecode": "0x730000000000000000000000000000000000000000301460806040525f5ffdfea2646970667358221220441d34d1c619df3c0ac9164ef28fbeb3af0052ff3efdd7913b73bf53e77b23e064736f6c63430008230033", "linkReferences": {}, "deployedLinkReferences": {} } diff --git a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/ERC1155.json b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/ERC1155.json similarity index 100% rename from dependencies/@openzeppelin-contracts-5.5.0/build/contracts/ERC1155.json rename to dependencies/@openzeppelin-contracts-5.7.0/build/contracts/ERC1155.json diff --git a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/ERC1155Burnable.json b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/ERC1155Burnable.json similarity index 100% rename from dependencies/@openzeppelin-contracts-5.5.0/build/contracts/ERC1155Burnable.json rename to dependencies/@openzeppelin-contracts-5.7.0/build/contracts/ERC1155Burnable.json diff --git a/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/ERC1155Crosschain.json b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/ERC1155Crosschain.json new file mode 100644 index 0000000..dd738b7 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/ERC1155Crosschain.json @@ -0,0 +1,793 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "ERC1155Crosschain", + "sourceName": "contracts/token/ERC1155/extensions/ERC1155Crosschain.sol", + "abi": [ + { + "inputs": [], + "name": "CrosschainMultiTokenEmptyAddress", + "type": "error" + }, + { + "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": [ + { + "internalType": "address", + "name": "gateway", + "type": "address" + }, + { + "internalType": "bytes", + "name": "sender", + "type": "bytes" + } + ], + "name": "ERC7786RecipientUnauthorizedGateway", + "type": "error" + }, + { + "inputs": [], + "name": "InteroperableAddressEmptyReferenceAndAddress", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "name": "InteroperableAddressParsingError", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "chain", + "type": "bytes" + } + ], + "name": "LinkAlreadyRegistered", + "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": "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": "bytes32", + "name": "receiveId", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "from", + "type": "bytes" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256[]", + "name": "ids", + "type": "uint256[]" + }, + { + "indexed": false, + "internalType": "uint256[]", + "name": "values", + "type": "uint256[]" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "CrosschainMultiTokenTransferReceived", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "sendId", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "to", + "type": "bytes" + }, + { + "indexed": false, + "internalType": "uint256[]", + "name": "ids", + "type": "uint256[]" + }, + { + "indexed": false, + "internalType": "uint256[]", + "name": "values", + "type": "uint256[]" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "CrosschainMultiTokenTransferSent", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "gateway", + "type": "address" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "counterpart", + "type": "bytes" + } + ], + "name": "LinkRegistered", + "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": "from", + "type": "address" + }, + { + "internalType": "bytes", + "name": "to", + "type": "bytes" + }, + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "crosschainTransferFrom", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "bytes", + "name": "to", + "type": "bytes" + }, + { + "internalType": "uint256[]", + "name": "ids", + "type": "uint256[]" + }, + { + "internalType": "uint256[]", + "name": "values", + "type": "uint256[]" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "crosschainTransferFrom", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "bytes", + "name": "to", + "type": "bytes" + }, + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "crosschainTransferFrom", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "bytes", + "name": "to", + "type": "bytes" + }, + { + "internalType": "uint256[]", + "name": "ids", + "type": "uint256[]" + }, + { + "internalType": "uint256[]", + "name": "values", + "type": "uint256[]" + } + ], + "name": "crosschainTransferFrom", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "chain", + "type": "bytes" + } + ], + "name": "getLink", + "outputs": [ + { + "internalType": "address", + "name": "gateway", + "type": "address" + }, + { + "internalType": "bytes", + "name": "counterpart", + "type": "bytes" + } + ], + "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": "bytes32", + "name": "receiveId", + "type": "bytes32" + }, + { + "internalType": "bytes", + "name": "sender", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "payload", + "type": "bytes" + } + ], + "name": "receiveMessage", + "outputs": [ + { + "internalType": "bytes4", + "name": "", + "type": "bytes4" + } + ], + "stateMutability": "payable", + "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.5.0/build/contracts/ERC1155Holder.json b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/ERC1155Holder.json similarity index 100% rename from dependencies/@openzeppelin-contracts-5.5.0/build/contracts/ERC1155Holder.json rename to dependencies/@openzeppelin-contracts-5.7.0/build/contracts/ERC1155Holder.json diff --git a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/ERC1155Pausable.json b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/ERC1155Pausable.json similarity index 100% rename from dependencies/@openzeppelin-contracts-5.5.0/build/contracts/ERC1155Pausable.json rename to dependencies/@openzeppelin-contracts-5.7.0/build/contracts/ERC1155Pausable.json diff --git a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/ERC1155Supply.json b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/ERC1155Supply.json similarity index 100% rename from dependencies/@openzeppelin-contracts-5.5.0/build/contracts/ERC1155Supply.json rename to dependencies/@openzeppelin-contracts-5.7.0/build/contracts/ERC1155Supply.json diff --git a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/ERC1155URIStorage.json b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/ERC1155URIStorage.json similarity index 100% rename from dependencies/@openzeppelin-contracts-5.5.0/build/contracts/ERC1155URIStorage.json rename to dependencies/@openzeppelin-contracts-5.7.0/build/contracts/ERC1155URIStorage.json diff --git a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/ERC1155Utils.json b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/ERC1155Utils.json similarity index 67% rename from dependencies/@openzeppelin-contracts-5.5.0/build/contracts/ERC1155Utils.json rename to dependencies/@openzeppelin-contracts-5.7.0/build/contracts/ERC1155Utils.json index 74c0c59..5150db0 100644 --- a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/ERC1155Utils.json +++ b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/ERC1155Utils.json @@ -3,8 +3,8 @@ "contractName": "ERC1155Utils", "sourceName": "contracts/token/ERC1155/utils/ERC1155Utils.sol", "abi": [], - "bytecode": "0x60556032600b8282823980515f1a607314602657634e487b7160e01b5f525f60045260245ffd5b305f52607381538281f3fe730000000000000000000000000000000000000000301460806040525f5ffdfea26469706673582212202c404e63a13828b0180524ac9d5a977283c12801966e57d03a051d9ee33ca65e64736f6c634300081b0033", - "deployedBytecode": "0x730000000000000000000000000000000000000000301460806040525f5ffdfea26469706673582212202c404e63a13828b0180524ac9d5a977283c12801966e57d03a051d9ee33ca65e64736f6c634300081b0033", + "bytecode": "0x60556032600b8282823980515f1a607314602657634e487b7160e01b5f525f60045260245ffd5b305f52607381538281f3fe730000000000000000000000000000000000000000301460806040525f5ffdfea264697066735822122036ca5da93466ec5c344689bf8f37720852e78969c9e0193040e4689d3594c94b64736f6c63430008230033", + "deployedBytecode": "0x730000000000000000000000000000000000000000301460806040525f5ffdfea264697066735822122036ca5da93466ec5c344689bf8f37720852e78969c9e0193040e4689d3594c94b64736f6c63430008230033", "linkReferences": {}, "deployedLinkReferences": {} } diff --git a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/ERC1363.json b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/ERC1363.json similarity index 100% rename from dependencies/@openzeppelin-contracts-5.5.0/build/contracts/ERC1363.json rename to dependencies/@openzeppelin-contracts-5.7.0/build/contracts/ERC1363.json diff --git a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/ERC1363Utils.json b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/ERC1363Utils.json similarity index 79% rename from dependencies/@openzeppelin-contracts-5.5.0/build/contracts/ERC1363Utils.json rename to dependencies/@openzeppelin-contracts-5.7.0/build/contracts/ERC1363Utils.json index e8b220d..f95ec78 100644 --- a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/ERC1363Utils.json +++ b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/ERC1363Utils.json @@ -26,8 +26,8 @@ "type": "error" } ], - "bytecode": "0x60556032600b8282823980515f1a607314602657634e487b7160e01b5f525f60045260245ffd5b305f52607381538281f3fe730000000000000000000000000000000000000000301460806040525f5ffdfea264697066735822122000d3f31db57c613822f20faac816d201f94a662e82977cf0e5e133b4f2fcf9a364736f6c634300081b0033", - "deployedBytecode": "0x730000000000000000000000000000000000000000301460806040525f5ffdfea264697066735822122000d3f31db57c613822f20faac816d201f94a662e82977cf0e5e133b4f2fcf9a364736f6c634300081b0033", + "bytecode": "0x60556032600b8282823980515f1a607314602657634e487b7160e01b5f525f60045260245ffd5b305f52607381538281f3fe730000000000000000000000000000000000000000301460806040525f5ffdfea2646970667358221220ca58dbf9feb53ae40948da3d96c1d7d8e0a0c3328331161405709f378c38534364736f6c63430008230033", + "deployedBytecode": "0x730000000000000000000000000000000000000000301460806040525f5ffdfea2646970667358221220ca58dbf9feb53ae40948da3d96c1d7d8e0a0c3328331161405709f378c38534364736f6c63430008230033", "linkReferences": {}, "deployedLinkReferences": {} } diff --git a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/ERC165.json b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/ERC165.json similarity index 100% rename from dependencies/@openzeppelin-contracts-5.5.0/build/contracts/ERC165.json rename to dependencies/@openzeppelin-contracts-5.7.0/build/contracts/ERC165.json diff --git a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/ERC165Checker.json b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/ERC165Checker.json similarity index 67% rename from dependencies/@openzeppelin-contracts-5.5.0/build/contracts/ERC165Checker.json rename to dependencies/@openzeppelin-contracts-5.7.0/build/contracts/ERC165Checker.json index 9014a1f..6350e07 100644 --- a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/ERC165Checker.json +++ b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/ERC165Checker.json @@ -3,8 +3,8 @@ "contractName": "ERC165Checker", "sourceName": "contracts/utils/introspection/ERC165Checker.sol", "abi": [], - "bytecode": "0x60556032600b8282823980515f1a607314602657634e487b7160e01b5f525f60045260245ffd5b305f52607381538281f3fe730000000000000000000000000000000000000000301460806040525f5ffdfea264697066735822122026ac0832d0b0b1271603a20bb62b3acc974e7c76ea15dedb084810d25e0fd92b64736f6c634300081b0033", - "deployedBytecode": "0x730000000000000000000000000000000000000000301460806040525f5ffdfea264697066735822122026ac0832d0b0b1271603a20bb62b3acc974e7c76ea15dedb084810d25e0fd92b64736f6c634300081b0033", + "bytecode": "0x60556032600b8282823980515f1a607314602657634e487b7160e01b5f525f60045260245ffd5b305f52607381538281f3fe730000000000000000000000000000000000000000301460806040525f5ffdfea264697066735822122090f28e9fc906d980ee203f15e38650d125776e53b61ad2d79ff1af0478def32564736f6c63430008230033", + "deployedBytecode": "0x730000000000000000000000000000000000000000301460806040525f5ffdfea264697066735822122090f28e9fc906d980ee203f15e38650d125776e53b61ad2d79ff1af0478def32564736f6c63430008230033", "linkReferences": {}, "deployedLinkReferences": {} } diff --git a/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/ERC1967Clones.json b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/ERC1967Clones.json new file mode 100644 index 0000000..ce597d0 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/ERC1967Clones.json @@ -0,0 +1,10 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "ERC1967Clones", + "sourceName": "contracts/proxy/ERC1967/ERC1967Clones.sol", + "abi": [], + "bytecode": "0x60556032600b8282823980515f1a607314602657634e487b7160e01b5f525f60045260245ffd5b305f52607381538281f3fe730000000000000000000000000000000000000000301460806040525f5ffdfea26469706673582212200268b50d953e74c21b8d4ed5e3ef8e8fc86e36d9b5488ee4ecf2768aaf23db6364736f6c63430008230033", + "deployedBytecode": "0x730000000000000000000000000000000000000000301460806040525f5ffdfea26469706673582212200268b50d953e74c21b8d4ed5e3ef8e8fc86e36d9b5488ee4ecf2768aaf23db6364736f6c63430008230033", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/ERC1967Proxy.json b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/ERC1967Proxy.json new file mode 100644 index 0000000..8e02b46 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/ERC1967Proxy.json @@ -0,0 +1,81 @@ +{ + "_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": "ERC1967ProxyUninitialized", + "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": "0x60806040526040516103b63803806103b683398101604081905261002291610238565b8051610041576040516330a289cf60e21b815260040160405180910390fd5b61004b8282610052565b5050610307565b61005b826100b0565b6040516001600160a01b038316907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b905f90a28051156100a45761009f828261012b565b505050565b6100ac6101cc565b5050565b806001600160a01b03163b5f036100ea57604051634c9c8ce360e01b81526001600160a01b03821660048201526024015b60405180910390fd5b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc80546001600160a01b0319166001600160a01b0392909216919091179055565b60605f61013884846101ed565b905080801561015957505f3d118061015957505f846001600160a01b03163b115b1561016e57610166610200565b9150506101c6565b801561019857604051639996b31560e01b81526001600160a01b03851660048201526024016100e1565b3d156101ab576101a6610219565b6101c4565b60405163d6bda27560e01b815260040160405180910390fd5b505b92915050565b34156101eb5760405163b398979f60e01b815260040160405180910390fd5b565b5f5f5f835160208501865af49392505050565b6040513d81523d5f602083013e3d602001810160405290565b6040513d5f823e3d81fd5b634e487b7160e01b5f52604160045260245ffd5b5f5f60408385031215610249575f5ffd5b82516001600160a01b038116811461025f575f5ffd5b60208401519092506001600160401b0381111561027a575f5ffd5b8301601f8101851361028a575f5ffd5b80516001600160401b038111156102a3576102a3610224565b604051601f8201601f19908116603f011681016001600160401b03811182821017156102d1576102d1610224565b6040528181528282016020018710156102e8575f5ffd5b8160208401602083015e5f602083830101528093505050509250929050565b60a3806103135f395ff3fe6080604052600a600c565b005b60186014601a565b6050565b565b5f604b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc546001600160a01b031690565b905090565b365f5f375f5f365f845af43d5f5f3e8080156069573d5ff35b3d5ffdfea26469706673582212201d830a0b321476b4b0af8b56a12d3c8e48912cf4acf7e23c74080c8b447a2a1d64736f6c63430008230033", + "deployedBytecode": "0x6080604052600a600c565b005b60186014601a565b6050565b565b5f604b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc546001600160a01b031690565b905090565b365f5f375f5f365f845af43d5f5f3e8080156069573d5ff35b3d5ffdfea26469706673582212201d830a0b321476b4b0af8b56a12d3c8e48912cf4acf7e23c74080c8b447a2a1d64736f6c63430008230033", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/ERC1967Utils.json b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/ERC1967Utils.json similarity index 84% rename from dependencies/@openzeppelin-contracts-5.5.0/build/contracts/ERC1967Utils.json rename to dependencies/@openzeppelin-contracts-5.7.0/build/contracts/ERC1967Utils.json index 774fade..5d6f262 100644 --- a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/ERC1967Utils.json +++ b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/ERC1967Utils.json @@ -42,8 +42,8 @@ "type": "error" } ], - "bytecode": "0x60556032600b8282823980515f1a607314602657634e487b7160e01b5f525f60045260245ffd5b305f52607381538281f3fe730000000000000000000000000000000000000000301460806040525f5ffdfea264697066735822122096a96aa09a8d8dcdd7c77a7a870b385109ee9e838a3d11259508461f8d82940364736f6c634300081b0033", - "deployedBytecode": "0x730000000000000000000000000000000000000000301460806040525f5ffdfea264697066735822122096a96aa09a8d8dcdd7c77a7a870b385109ee9e838a3d11259508461f8d82940364736f6c634300081b0033", + "bytecode": "0x60556032600b8282823980515f1a607314602657634e487b7160e01b5f525f60045260245ffd5b305f52607381538281f3fe730000000000000000000000000000000000000000301460806040525f5ffdfea2646970667358221220d6b87a401f21492c26a73a18baf13a880937b7a6a156302ecdc661c8811cdfa464736f6c63430008230033", + "deployedBytecode": "0x730000000000000000000000000000000000000000301460806040525f5ffdfea2646970667358221220d6b87a401f21492c26a73a18baf13a880937b7a6a156302ecdc661c8811cdfa464736f6c63430008230033", "linkReferences": {}, "deployedLinkReferences": {} } diff --git a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/ERC20.json b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/ERC20.json similarity index 100% rename from dependencies/@openzeppelin-contracts-5.5.0/build/contracts/ERC20.json rename to dependencies/@openzeppelin-contracts-5.7.0/build/contracts/ERC20.json diff --git a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/ERC20Bridgeable.json b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/ERC20Bridgeable.json similarity index 100% rename from dependencies/@openzeppelin-contracts-5.5.0/build/contracts/ERC20Bridgeable.json rename to dependencies/@openzeppelin-contracts-5.7.0/build/contracts/ERC20Bridgeable.json diff --git a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/ERC20Burnable.json b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/ERC20Burnable.json similarity index 100% rename from dependencies/@openzeppelin-contracts-5.5.0/build/contracts/ERC20Burnable.json rename to dependencies/@openzeppelin-contracts-5.7.0/build/contracts/ERC20Burnable.json diff --git a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/ERC20Capped.json b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/ERC20Capped.json similarity index 100% rename from dependencies/@openzeppelin-contracts-5.5.0/build/contracts/ERC20Capped.json rename to dependencies/@openzeppelin-contracts-5.7.0/build/contracts/ERC20Capped.json diff --git a/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/ERC20Crosschain.json b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/ERC20Crosschain.json new file mode 100644 index 0000000..81f46b4 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/ERC20Crosschain.json @@ -0,0 +1,570 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "ERC20Crosschain", + "sourceName": "contracts/token/ERC20/extensions/ERC20Crosschain.sol", + "abi": [ + { + "inputs": [], + "name": "CrosschainFungibleEmptyAddress", + "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": "address", + "name": "gateway", + "type": "address" + }, + { + "internalType": "bytes", + "name": "sender", + "type": "bytes" + } + ], + "name": "ERC7786RecipientUnauthorizedGateway", + "type": "error" + }, + { + "inputs": [], + "name": "InteroperableAddressEmptyReferenceAndAddress", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "name": "InteroperableAddressParsingError", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "chain", + "type": "bytes" + } + ], + "name": "LinkAlreadyRegistered", + "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": "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": "bytes32", + "name": "receiveId", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "from", + "type": "bytes" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "CrosschainFungibleTransferReceived", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "sendId", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "to", + "type": "bytes" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "CrosschainFungibleTransferSent", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "gateway", + "type": "address" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "counterpart", + "type": "bytes" + } + ], + "name": "LinkRegistered", + "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": "bytes", + "name": "to", + "type": "bytes" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "crosschainTransfer", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "bytes", + "name": "to", + "type": "bytes" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "crosschainTransferFrom", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "decimals", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "chain", + "type": "bytes" + } + ], + "name": "getLink", + "outputs": [ + { + "internalType": "address", + "name": "gateway", + "type": "address" + }, + { + "internalType": "bytes", + "name": "counterpart", + "type": "bytes" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "receiveId", + "type": "bytes32" + }, + { + "internalType": "bytes", + "name": "sender", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "payload", + "type": "bytes" + } + ], + "name": "receiveMessage", + "outputs": [ + { + "internalType": "bytes4", + "name": "", + "type": "bytes4" + } + ], + "stateMutability": "payable", + "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.5.0/build/contracts/ERC20FlashMint.json b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/ERC20FlashMint.json similarity index 100% rename from dependencies/@openzeppelin-contracts-5.5.0/build/contracts/ERC20FlashMint.json rename to dependencies/@openzeppelin-contracts-5.7.0/build/contracts/ERC20FlashMint.json diff --git a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/ERC20Pausable.json b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/ERC20Pausable.json similarity index 100% rename from dependencies/@openzeppelin-contracts-5.5.0/build/contracts/ERC20Pausable.json rename to dependencies/@openzeppelin-contracts-5.7.0/build/contracts/ERC20Pausable.json diff --git a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/ERC20Permit.json b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/ERC20Permit.json similarity index 100% rename from dependencies/@openzeppelin-contracts-5.5.0/build/contracts/ERC20Permit.json rename to dependencies/@openzeppelin-contracts-5.7.0/build/contracts/ERC20Permit.json diff --git a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/ERC20TemporaryApproval.json b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/ERC20TemporaryApproval.json similarity index 100% rename from dependencies/@openzeppelin-contracts-5.5.0/build/contracts/ERC20TemporaryApproval.json rename to dependencies/@openzeppelin-contracts-5.7.0/build/contracts/ERC20TemporaryApproval.json diff --git a/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/ERC20TransferAuthorization.json b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/ERC20TransferAuthorization.json new file mode 100644 index 0000000..e245a1b --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/ERC20TransferAuthorization.json @@ -0,0 +1,833 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "ERC20TransferAuthorization", + "sourceName": "contracts/token/ERC20/extensions/ERC20TransferAuthorization.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": "validAfter", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "validBefore", + "type": "uint256" + } + ], + "name": "ERC3009InvalidAuthorizationTime", + "type": "error" + }, + { + "inputs": [], + "name": "ERC3009InvalidSignature", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "authorizer", + "type": "address" + }, + { + "internalType": "bytes32", + "name": "nonce", + "type": "bytes32" + } + ], + "name": "ERC3009UsedAuthorization", + "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": 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": "authorizer", + "type": "address" + }, + { + "indexed": true, + "internalType": "bytes32", + "name": "nonce", + "type": "bytes32" + } + ], + "name": "AuthorizationCanceled", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "authorizer", + "type": "address" + }, + { + "indexed": true, + "internalType": "bytes32", + "name": "nonce", + "type": "bytes32" + } + ], + "name": "AuthorizationUsed", + "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": [ + { + "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": "authorizer", + "type": "address" + }, + { + "internalType": "bytes32", + "name": "nonce", + "type": "bytes32" + } + ], + "name": "authorizationState", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "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": "address", + "name": "authorizer", + "type": "address" + }, + { + "internalType": "bytes32", + "name": "nonce", + "type": "bytes32" + }, + { + "internalType": "uint8", + "name": "v", + "type": "uint8" + }, + { + "internalType": "bytes32", + "name": "r", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "s", + "type": "bytes32" + } + ], + "name": "cancelAuthorization", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "authorizer", + "type": "address" + }, + { + "internalType": "bytes32", + "name": "nonce", + "type": "bytes32" + }, + { + "internalType": "bytes", + "name": "signature", + "type": "bytes" + } + ], + "name": "cancelAuthorization", + "outputs": [], + "stateMutability": "nonpayable", + "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": "uint192", + "name": "key", + "type": "uint192" + } + ], + "name": "nonces", + "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": "value", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "validAfter", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "validBefore", + "type": "uint256" + }, + { + "internalType": "bytes32", + "name": "nonce", + "type": "bytes32" + }, + { + "internalType": "bytes", + "name": "signature", + "type": "bytes" + } + ], + "name": "receiveWithAuthorization", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "validAfter", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "validBefore", + "type": "uint256" + }, + { + "internalType": "bytes32", + "name": "nonce", + "type": "bytes32" + }, + { + "internalType": "uint8", + "name": "v", + "type": "uint8" + }, + { + "internalType": "bytes32", + "name": "r", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "s", + "type": "bytes32" + } + ], + "name": "receiveWithAuthorization", + "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" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "validAfter", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "validBefore", + "type": "uint256" + }, + { + "internalType": "bytes32", + "name": "nonce", + "type": "bytes32" + }, + { + "internalType": "bytes", + "name": "signature", + "type": "bytes" + } + ], + "name": "transferWithAuthorization", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "validAfter", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "validBefore", + "type": "uint256" + }, + { + "internalType": "bytes32", + "name": "nonce", + "type": "bytes32" + }, + { + "internalType": "uint8", + "name": "v", + "type": "uint8" + }, + { + "internalType": "bytes32", + "name": "r", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "s", + "type": "bytes32" + } + ], + "name": "transferWithAuthorization", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } + ], + "bytecode": "0x", + "deployedBytecode": "0x", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/ERC20Votes.json b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/ERC20Votes.json similarity index 100% rename from dependencies/@openzeppelin-contracts-5.5.0/build/contracts/ERC20Votes.json rename to dependencies/@openzeppelin-contracts-5.7.0/build/contracts/ERC20Votes.json diff --git a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/ERC20Wrapper.json b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/ERC20Wrapper.json similarity index 100% rename from dependencies/@openzeppelin-contracts-5.5.0/build/contracts/ERC20Wrapper.json rename to dependencies/@openzeppelin-contracts-5.7.0/build/contracts/ERC20Wrapper.json diff --git a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/ERC2771Context.json b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/ERC2771Context.json similarity index 100% rename from dependencies/@openzeppelin-contracts-5.5.0/build/contracts/ERC2771Context.json rename to dependencies/@openzeppelin-contracts-5.7.0/build/contracts/ERC2771Context.json diff --git a/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/ERC2771Forwarder.json b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/ERC2771Forwarder.json new file mode 100644 index 0000000..5526935 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/ERC2771Forwarder.json @@ -0,0 +1,393 @@ +{ + "_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": [], + "name": "ERC2771ForwarderNoRefundReceiver", + "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": "0x610160604052348015610010575f5ffd5b506040516110b43803806110b483398101604081905261002f91610154565b6040805180820190915260018152603160f81b60208201528190610052826100fa565b6101205261005f816100fa565b61014052815160208084019190912060e052815190820120610100524660a0526100eb60e05161010051604080517f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f60208201529081019290925260608201524660808201523060a08201525f9060c00160405160208183030381529060405280519060200120905090565b60805250503060c0525061025f565b5f5f829050601f8151111561012d578260405163305a27a960e01b81526004016101249190610204565b60405180910390fd5b805161013882610239565b179392505050565b634e487b7160e01b5f52604160045260245ffd5b5f60208284031215610164575f5ffd5b81516001600160401b03811115610179575f5ffd5b8201601f81018413610189575f5ffd5b80516001600160401b038111156101a2576101a2610140565b604051601f8201601f19908116603f011681016001600160401b03811182821017156101d0576101d0610140565b6040528181528282016020018610156101e7575f5ffd5b8160208401602083015e5f91810160200191909152949350505050565b602081525f82518060208401528060208501604085015e5f604082850101526040601f19601f83011684010191505092915050565b80516020808301519190811015610259575f198160200360031b1b821691505b50919050565b60805160a05160c05160e051610100516101205161014051610e046102b05f395f6103bc01525f61038c01525f6109db01525f6109b301525f61090e01525f61093801525f6109620152610e045ff3fe608060405260043610610049575f3560e01c806319d8d38c1461004d5780637ecebe001461008157806384b0196e146100c3578063ccf96b4a146100ea578063df905caf146100ff575b5f5ffd5b348015610058575f5ffd5b5061006c610067366004610af3565b610112565b60405190151581526020015b60405180910390f35b34801561008c575f5ffd5b506100b561009b366004610b45565b6001600160a01b03165f9081526002602052604090205490565b604051908152602001610078565b3480156100ce575f5ffd5b506100d7610142565b6040516100789796959493929190610b8e565b6100fd6100f8366004610c24565b610184565b005b6100fd61010d366004610af3565b6102a8565b5f5f5f5f61011f85610303565b509250925092508280156101305750815b80156101395750805b95945050505050565b5f6060805f5f5f6060610153610385565b61015b6103b5565b604080515f80825260208201909252600f60f81b9b939a50919850469750309650945092509050565b6001600160a01b038116155f80805b85811015610242578686828181106101ad576101ad610ca6565b90506020028101906101bf9190610cba565b6101cd906040013584610cd8565b92505f6101fd8888848181106101e5576101e5610ca6565b90506020028101906101f79190610cba565b866103e0565b9050806102395787878381811061021657610216610ca6565b90506020028101906102289190610cba565b610236906040013584610cd8565b92505b50600101610193565b50348214610271576040516370647f7960e01b8152600481018390523460248201526044015b60405180910390fd5b80156102a0578215610296576040516339c6e3b760e01b815260040160405180910390fd5b6102a084826105bb565b505050505050565b806040013534146102d857604080516370647f7960e01b8152908201356004820152346024820152604401610268565b6102e38160016103e0565b6103005760405163d6bda27560e01b815260040160405180910390fd5b50565b5f5f5f5f5f5f61031287610632565b909250905061032f61032a6040890160208a01610b45565b610774565b4261034060a08a0160808b01610cf7565b65ffffffffffff161015838015610374575061035f60208a018a610b45565b6001600160a01b0316836001600160a01b0316145b919750955093509150509193509193565b60606103b07f00000000000000000000000000000000000000000000000000000000000000006107ed565b905090565b60606103b07f00000000000000000000000000000000000000000000000000000000000000006107ed565b5f5f5f5f5f6103ee87610303565b935093509350935085156104b4578361043c576104116040880160208901610b45565b60405163d2650cd160e01b81526001600160a01b039091166004820152306024820152604401610268565b826104755761045160a0880160808901610cf7565b604051634a777ac560e11b815265ffffffffffff9091166004820152602401610268565b816104b457806104886020890189610b45565b604051636422d02b60e11b81526001600160a01b03928316600482015291166024820152604401610268565b8380156104be5750815b80156104c75750825b156105b1576001600160a01b0381165f908152600260205260408120805460018101909155905060608801355f61050460408b0160208c01610b45565b905060408a01355f61051960a08d018d610d1c565b61052660208f018f610b45565b60405160200161053893929190610d66565b60405160208183030381529060405290505f5f5f83516020850186888af19a505a9050610565818e61082a565b604080518781528c151560208201526001600160a01b038916917f842fb24a83793558587a3dab2be7674da4a51d09c5542d6dd354e5d0ea70813c910160405180910390a25050505050505b5050505092915050565b804710156105e55760405163cf47918160e01b815247600482015260248101829052604401610268565b6105fe828260405180602001604052805f815250610842565b15610607575050565b3d1561061957610615610857565b5050565b60405163d6bda27560e01b815260040160405180910390fd5b5f80808061074f61064660c0870187610d1c565b6107487f7f96328b83274ebc7c1cf4f7a3abda602b51a78b7fa1d86a2ce353d75e587cac61067760208b018b610b45565b61068760408c0160208d01610b45565b8b604001358c606001356106a68e5f01602081019061009b9190610b45565b8e60800160208101906106b99190610cf7565b8f8060a001906106c99190610d1c565b6040516106d7929190610d8c565b6040805191829003822060208301999099526001600160a01b0397881690820152959094166060860152608085019290925260a084015260c083015265ffffffffffff1660e08201526101008101919091526101200160405160208183030381529060405280519060200120610862565b9190610894565b5090925090505f81600381111561076857610768610d9b565b14959194509092505050565b6040513060248201525f90819060440160408051601f19818403018152919052602080820180516001600160e01b031663572b6c0560e01b17815282519293505f928392839290918391895afa92503d91505f5190508280156107d8575060208210155b80156107e357505f81115b9695505050505050565b60605f6107f9836108db565b6040805160208082528183019092529192505f91906020820181803683375050509182525060208101929092525090565b610839603f6060830135610daf565b82101561061557fe5b5f5f5f83516020850186885af1949350505050565b6040513d5f823e3d81fd5b5f61088e61086e610902565b8360405161190160f01b8152600281019290925260228201526042902090565b92915050565b5f808060418490036108c8578435602086013560408701355f1a6108ba89828585610a2b565b9550955095505050506108d2565b505f915060029050825b93509350939050565b5f60ff8216601f81111561088e57604051632cd44ac360e21b815260040160405180910390fd5b5f306001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614801561095a57507f000000000000000000000000000000000000000000000000000000000000000046145b1561098457507f000000000000000000000000000000000000000000000000000000000000000090565b6103b0604080517f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f60208201527f0000000000000000000000000000000000000000000000000000000000000000918101919091527f000000000000000000000000000000000000000000000000000000000000000060608201524660808201523060a08201525f9060c00160405160208183030381529060405280519060200120905090565b5f80807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0841115610a6457505f91506003905082610ae9565b604080515f808252602082018084528a905260ff891692820192909252606081018790526080810186905260019060a0016020604051602081039080840390855afa158015610ab5573d5f5f3e3d5ffd5b5050604051601f1901519150506001600160a01b038116610ae057505f925060019150829050610ae9565b92505f91508190505b9450945094915050565b5f60208284031215610b03575f5ffd5b813567ffffffffffffffff811115610b19575f5ffd5b820160e08185031215610b2a575f5ffd5b9392505050565b6001600160a01b0381168114610300575f5ffd5b5f60208284031215610b55575f5ffd5b8135610b2a81610b31565b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b60ff60f81b8816815260e060208201525f610bac60e0830189610b60565b8281036040840152610bbe8189610b60565b606084018890526001600160a01b038716608085015260a0840186905283810360c0850152845180825260208087019350909101905f5b81811015610c13578351835260209384019390920191600101610bf5565b50909b9a5050505050505050505050565b5f5f5f60408486031215610c36575f5ffd5b833567ffffffffffffffff811115610c4c575f5ffd5b8401601f81018613610c5c575f5ffd5b803567ffffffffffffffff811115610c72575f5ffd5b8660208260051b8401011115610c86575f5ffd5b602091820194509250840135610c9b81610b31565b809150509250925092565b634e487b7160e01b5f52603260045260245ffd5b5f823560de19833603018112610cce575f5ffd5b9190910192915050565b8082018082111561088e57634e487b7160e01b5f52601160045260245ffd5b5f60208284031215610d07575f5ffd5b813565ffffffffffff81168114610b2a575f5ffd5b5f5f8335601e19843603018112610d31575f5ffd5b83018035915067ffffffffffffffff821115610d4b575f5ffd5b602001915036819003821315610d5f575f5ffd5b9250929050565b8284823760609190911b6bffffffffffffffffffffffff19169101908152601401919050565b818382375f9101908152919050565b634e487b7160e01b5f52602160045260245ffd5b5f82610dc957634e487b7160e01b5f52601260045260245ffd5b50049056fea26469706673582212200a050b7972be438f89ca86c26dfd52c978f43dd5b2e1f000560cb6a0006b250e64736f6c63430008230033", + "deployedBytecode": "0x608060405260043610610049575f3560e01c806319d8d38c1461004d5780637ecebe001461008157806384b0196e146100c3578063ccf96b4a146100ea578063df905caf146100ff575b5f5ffd5b348015610058575f5ffd5b5061006c610067366004610af3565b610112565b60405190151581526020015b60405180910390f35b34801561008c575f5ffd5b506100b561009b366004610b45565b6001600160a01b03165f9081526002602052604090205490565b604051908152602001610078565b3480156100ce575f5ffd5b506100d7610142565b6040516100789796959493929190610b8e565b6100fd6100f8366004610c24565b610184565b005b6100fd61010d366004610af3565b6102a8565b5f5f5f5f61011f85610303565b509250925092508280156101305750815b80156101395750805b95945050505050565b5f6060805f5f5f6060610153610385565b61015b6103b5565b604080515f80825260208201909252600f60f81b9b939a50919850469750309650945092509050565b6001600160a01b038116155f80805b85811015610242578686828181106101ad576101ad610ca6565b90506020028101906101bf9190610cba565b6101cd906040013584610cd8565b92505f6101fd8888848181106101e5576101e5610ca6565b90506020028101906101f79190610cba565b866103e0565b9050806102395787878381811061021657610216610ca6565b90506020028101906102289190610cba565b610236906040013584610cd8565b92505b50600101610193565b50348214610271576040516370647f7960e01b8152600481018390523460248201526044015b60405180910390fd5b80156102a0578215610296576040516339c6e3b760e01b815260040160405180910390fd5b6102a084826105bb565b505050505050565b806040013534146102d857604080516370647f7960e01b8152908201356004820152346024820152604401610268565b6102e38160016103e0565b6103005760405163d6bda27560e01b815260040160405180910390fd5b50565b5f5f5f5f5f5f61031287610632565b909250905061032f61032a6040890160208a01610b45565b610774565b4261034060a08a0160808b01610cf7565b65ffffffffffff161015838015610374575061035f60208a018a610b45565b6001600160a01b0316836001600160a01b0316145b919750955093509150509193509193565b60606103b07f00000000000000000000000000000000000000000000000000000000000000006107ed565b905090565b60606103b07f00000000000000000000000000000000000000000000000000000000000000006107ed565b5f5f5f5f5f6103ee87610303565b935093509350935085156104b4578361043c576104116040880160208901610b45565b60405163d2650cd160e01b81526001600160a01b039091166004820152306024820152604401610268565b826104755761045160a0880160808901610cf7565b604051634a777ac560e11b815265ffffffffffff9091166004820152602401610268565b816104b457806104886020890189610b45565b604051636422d02b60e11b81526001600160a01b03928316600482015291166024820152604401610268565b8380156104be5750815b80156104c75750825b156105b1576001600160a01b0381165f908152600260205260408120805460018101909155905060608801355f61050460408b0160208c01610b45565b905060408a01355f61051960a08d018d610d1c565b61052660208f018f610b45565b60405160200161053893929190610d66565b60405160208183030381529060405290505f5f5f83516020850186888af19a505a9050610565818e61082a565b604080518781528c151560208201526001600160a01b038916917f842fb24a83793558587a3dab2be7674da4a51d09c5542d6dd354e5d0ea70813c910160405180910390a25050505050505b5050505092915050565b804710156105e55760405163cf47918160e01b815247600482015260248101829052604401610268565b6105fe828260405180602001604052805f815250610842565b15610607575050565b3d1561061957610615610857565b5050565b60405163d6bda27560e01b815260040160405180910390fd5b5f80808061074f61064660c0870187610d1c565b6107487f7f96328b83274ebc7c1cf4f7a3abda602b51a78b7fa1d86a2ce353d75e587cac61067760208b018b610b45565b61068760408c0160208d01610b45565b8b604001358c606001356106a68e5f01602081019061009b9190610b45565b8e60800160208101906106b99190610cf7565b8f8060a001906106c99190610d1c565b6040516106d7929190610d8c565b6040805191829003822060208301999099526001600160a01b0397881690820152959094166060860152608085019290925260a084015260c083015265ffffffffffff1660e08201526101008101919091526101200160405160208183030381529060405280519060200120610862565b9190610894565b5090925090505f81600381111561076857610768610d9b565b14959194509092505050565b6040513060248201525f90819060440160408051601f19818403018152919052602080820180516001600160e01b031663572b6c0560e01b17815282519293505f928392839290918391895afa92503d91505f5190508280156107d8575060208210155b80156107e357505f81115b9695505050505050565b60605f6107f9836108db565b6040805160208082528183019092529192505f91906020820181803683375050509182525060208101929092525090565b610839603f6060830135610daf565b82101561061557fe5b5f5f5f83516020850186885af1949350505050565b6040513d5f823e3d81fd5b5f61088e61086e610902565b8360405161190160f01b8152600281019290925260228201526042902090565b92915050565b5f808060418490036108c8578435602086013560408701355f1a6108ba89828585610a2b565b9550955095505050506108d2565b505f915060029050825b93509350939050565b5f60ff8216601f81111561088e57604051632cd44ac360e21b815260040160405180910390fd5b5f306001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614801561095a57507f000000000000000000000000000000000000000000000000000000000000000046145b1561098457507f000000000000000000000000000000000000000000000000000000000000000090565b6103b0604080517f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f60208201527f0000000000000000000000000000000000000000000000000000000000000000918101919091527f000000000000000000000000000000000000000000000000000000000000000060608201524660808201523060a08201525f9060c00160405160208183030381529060405280519060200120905090565b5f80807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0841115610a6457505f91506003905082610ae9565b604080515f808252602082018084528a905260ff891692820192909252606081018790526080810186905260019060a0016020604051602081039080840390855afa158015610ab5573d5f5f3e3d5ffd5b5050604051601f1901519150506001600160a01b038116610ae057505f925060019150829050610ae9565b92505f91508190505b9450945094915050565b5f60208284031215610b03575f5ffd5b813567ffffffffffffffff811115610b19575f5ffd5b820160e08185031215610b2a575f5ffd5b9392505050565b6001600160a01b0381168114610300575f5ffd5b5f60208284031215610b55575f5ffd5b8135610b2a81610b31565b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b60ff60f81b8816815260e060208201525f610bac60e0830189610b60565b8281036040840152610bbe8189610b60565b606084018890526001600160a01b038716608085015260a0840186905283810360c0850152845180825260208087019350909101905f5b81811015610c13578351835260209384019390920191600101610bf5565b50909b9a5050505050505050505050565b5f5f5f60408486031215610c36575f5ffd5b833567ffffffffffffffff811115610c4c575f5ffd5b8401601f81018613610c5c575f5ffd5b803567ffffffffffffffff811115610c72575f5ffd5b8660208260051b8401011115610c86575f5ffd5b602091820194509250840135610c9b81610b31565b809150509250925092565b634e487b7160e01b5f52603260045260245ffd5b5f823560de19833603018112610cce575f5ffd5b9190910192915050565b8082018082111561088e57634e487b7160e01b5f52601160045260245ffd5b5f60208284031215610d07575f5ffd5b813565ffffffffffff81168114610b2a575f5ffd5b5f5f8335601e19843603018112610d31575f5ffd5b83018035915067ffffffffffffffff821115610d4b575f5ffd5b602001915036819003821315610d5f575f5ffd5b9250929050565b8284823760609190911b6bffffffffffffffffffffffff19169101908152601401919050565b818382375f9101908152919050565b634e487b7160e01b5f52602160045260245ffd5b5f82610dc957634e487b7160e01b5f52601260045260245ffd5b50049056fea26469706673582212200a050b7972be438f89ca86c26dfd52c978f43dd5b2e1f000560cb6a0006b250e64736f6c63430008230033", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/ERC2981.json b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/ERC2981.json similarity index 100% rename from dependencies/@openzeppelin-contracts-5.5.0/build/contracts/ERC2981.json rename to dependencies/@openzeppelin-contracts-5.7.0/build/contracts/ERC2981.json diff --git a/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/ERC3009.json b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/ERC3009.json new file mode 100644 index 0000000..143c38e --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/ERC3009.json @@ -0,0 +1,665 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "ERC3009", + "sourceName": "contracts/token/ERC20/extensions/draft-ERC3009.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": "validAfter", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "validBefore", + "type": "uint256" + } + ], + "name": "ERC3009InvalidAuthorizationTime", + "type": "error" + }, + { + "inputs": [], + "name": "ERC3009InvalidSignature", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "authorizer", + "type": "address" + }, + { + "internalType": "bytes32", + "name": "nonce", + "type": "bytes32" + } + ], + "name": "ERC3009UsedAuthorization", + "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": 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": "authorizer", + "type": "address" + }, + { + "indexed": true, + "internalType": "bytes32", + "name": "nonce", + "type": "bytes32" + } + ], + "name": "AuthorizationCanceled", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "authorizer", + "type": "address" + }, + { + "indexed": true, + "internalType": "bytes32", + "name": "nonce", + "type": "bytes32" + } + ], + "name": "AuthorizationUsed", + "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": [ + { + "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": "authorizer", + "type": "address" + }, + { + "internalType": "bytes32", + "name": "nonce", + "type": "bytes32" + } + ], + "name": "authorizationState", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "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": "address", + "name": "authorizer", + "type": "address" + }, + { + "internalType": "bytes32", + "name": "nonce", + "type": "bytes32" + }, + { + "internalType": "uint8", + "name": "v", + "type": "uint8" + }, + { + "internalType": "bytes32", + "name": "r", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "s", + "type": "bytes32" + } + ], + "name": "cancelAuthorization", + "outputs": [], + "stateMutability": "nonpayable", + "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": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "validAfter", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "validBefore", + "type": "uint256" + }, + { + "internalType": "bytes32", + "name": "nonce", + "type": "bytes32" + }, + { + "internalType": "uint8", + "name": "v", + "type": "uint8" + }, + { + "internalType": "bytes32", + "name": "r", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "s", + "type": "bytes32" + } + ], + "name": "receiveWithAuthorization", + "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" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "validAfter", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "validBefore", + "type": "uint256" + }, + { + "internalType": "bytes32", + "name": "nonce", + "type": "bytes32" + }, + { + "internalType": "uint8", + "name": "v", + "type": "uint8" + }, + { + "internalType": "bytes32", + "name": "r", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "s", + "type": "bytes32" + } + ], + "name": "transferWithAuthorization", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } + ], + "bytecode": "0x", + "deployedBytecode": "0x", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/ERC4337Utils.json b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/ERC4337Utils.json similarity index 57% rename from dependencies/@openzeppelin-contracts-5.5.0/build/contracts/ERC4337Utils.json rename to dependencies/@openzeppelin-contracts-5.7.0/build/contracts/ERC4337Utils.json index 6f65858..669d7a7 100644 --- a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/ERC4337Utils.json +++ b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/ERC4337Utils.json @@ -1,10 +1,10 @@ { "_format": "hh-sol-artifact-1", "contractName": "ERC4337Utils", - "sourceName": "contracts/account/utils/draft-ERC4337Utils.sol", + "sourceName": "contracts/account/utils/ERC4337Utils.sol", "abi": [], - "bytecode": "0x60556032600b8282823980515f1a607314602657634e487b7160e01b5f525f60045260245ffd5b305f52607381538281f3fe730000000000000000000000000000000000000000301460806040525f5ffdfea26469706673582212204851c2a6ba2d471126c7593ab85b089794d6508ddfa609dc311497e37d9ae74164736f6c634300081b0033", - "deployedBytecode": "0x730000000000000000000000000000000000000000301460806040525f5ffdfea26469706673582212204851c2a6ba2d471126c7593ab85b089794d6508ddfa609dc311497e37d9ae74164736f6c634300081b0033", + "bytecode": "0x60556032600b8282823980515f1a607314602657634e487b7160e01b5f525f60045260245ffd5b305f52607381538281f3fe730000000000000000000000000000000000000000301460806040525f5ffdfea26469706673582212202b34f766de3450d404d52ee296e686c81274405e70dca1bbc6f87dc351f47d0f64736f6c63430008230033", + "deployedBytecode": "0x730000000000000000000000000000000000000000301460806040525f5ffdfea26469706673582212202b34f766de3450d404d52ee296e686c81274405e70dca1bbc6f87dc351f47d0f64736f6c63430008230033", "linkReferences": {}, "deployedLinkReferences": {} } diff --git a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/ERC4626.json b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/ERC4626.json similarity index 100% rename from dependencies/@openzeppelin-contracts-5.5.0/build/contracts/ERC4626.json rename to dependencies/@openzeppelin-contracts-5.7.0/build/contracts/ERC4626.json diff --git a/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/ERC6372Utils.json b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/ERC6372Utils.json new file mode 100644 index 0000000..f72f5a0 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/ERC6372Utils.json @@ -0,0 +1,16 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "ERC6372Utils", + "sourceName": "contracts/utils/ERC6372Utils.sol", + "abi": [ + { + "inputs": [], + "name": "ERC6372InconsistentClock", + "type": "error" + } + ], + "bytecode": "0x60556032600b8282823980515f1a607314602657634e487b7160e01b5f525f60045260245ffd5b305f52607381538281f3fe730000000000000000000000000000000000000000301460806040525f5ffdfea2646970667358221220b5ba13787c6586435f949304df912eb93e4e5d8ea1d650eabe564133b7553ce164736f6c63430008230033", + "deployedBytecode": "0x730000000000000000000000000000000000000000301460806040525f5ffdfea2646970667358221220b5ba13787c6586435f949304df912eb93e4e5d8ea1d650eabe564133b7553ce164736f6c63430008230033", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/ERC6909.json b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/ERC6909.json similarity index 98% rename from dependencies/@openzeppelin-contracts-5.5.0/build/contracts/ERC6909.json rename to dependencies/@openzeppelin-contracts-5.7.0/build/contracts/ERC6909.json index 9c98380..3d7e3f2 100644 --- a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/ERC6909.json +++ b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/ERC6909.json @@ -405,8 +405,8 @@ "type": "function" } ], - "bytecode": "0x6080604052348015600e575f5ffd5b506108368061001c5f395ff3fe608060405234801561000f575f5ffd5b5060043610610084575f3560e01c8063558a729711610058578063558a7297146100f7578063598af9e71461010a578063b6363cf214610149578063fe99049a14610184575f5ffd5b8062fdd58e1461008857806301ffc9a7146100ae578063095bcdb6146100d1578063426a8493146100e4575b5f5ffd5b61009b610096366004610678565b610197565b6040519081526020015b60405180910390f35b6100c16100bc3660046106a0565b6101bf565b60405190151581526020016100a5565b6100c16100df3660046106ce565b6101f3565b6100c16100f23660046106ce565b61020a565b6100c16101053660046106fe565b610217565b61009b610118366004610737565b6001600160a01b039283165f9081526002602090815260408083209490951682529283528381209181529152205490565b6100c1610157366004610771565b6001600160a01b039182165f90815260016020908152604080832093909416825291909152205460ff1690565b6100c16101923660046107a2565b61022c565b6001600160a01b0382165f908152602081815260408083208484529091529020545b92915050565b5f6001600160e01b03198216630f632fb360e01b14806101b957506301ffc9a760e01b6001600160e01b03198316146101b9565b5f61020033858585610295565b5060019392505050565b5f610200338585856102fe565b5f6102233384846103bd565b50600192915050565b5f336001600160a01b038616811480159061026c57506001600160a01b038087165f9081526001602090815260408083209385168352929052205460ff16155b1561027d5761027d8682868661047b565b61028986868686610295565b50600195945050505050565b6001600160a01b0384166102c3576040516301486a4160e71b81525f60048201526024015b60405180910390fd5b6001600160a01b0383166102ec57604051630b8bbd6160e41b81525f60048201526024016102ba565b6102f88484848461052b565b50505050565b6001600160a01b0384166103275760405163198ecd5360e31b81525f60048201526024016102ba565b6001600160a01b03831661035057604051636f65f46560e01b81525f60048201526024016102ba565b6001600160a01b038481165f8181526002602090815260408083209488168084529482528083208784528252918290208590559051848152859392917fb3fd5071835887567a0671151121894ddccc2842f1d10bedad13e0d17cace9a7910160405180910390a450505050565b6001600160a01b0383166103e65760405163198ecd5360e31b81525f60048201526024016102ba565b6001600160a01b03821661040f57604051636f65f46560e01b81525f60048201526024016102ba565b6001600160a01b038381165f81815260016020908152604080832094871680845294825291829020805460ff191686151590811790915591519182527fceb576d9f15e4e200fdb5096d64d5dfd667e16def20c1eefd14256d8e3faa267910160405180910390a3505050565b6001600160a01b038481165f9081526002602090815260408083209387168352928152828220858352905220545f1981101561052457818110156104f257604051632c51fead60e11b81526001600160a01b03851660048201526024810182905260448101839052606481018490526084016102ba565b6001600160a01b038086165f908152600260209081526040808320938816835292815282822086835290522082820390555b5050505050565b336001600160a01b038516156105c4576001600160a01b0385165f908152602081815260408083208684529091529020548281101561059d576040516302c6d3fb60e61b81526001600160a01b03871660048201526024810182905260448101849052606481018590526084016102ba565b6001600160a01b0386165f9081526020818152604080832087845290915290209083900390555b6001600160a01b03841615610609576001600160a01b0384165f90815260208181526040808320868452909152812080548492906106039084906107e1565b90915550505b604080516001600160a01b03838116825260208201859052859281881692918916917f1b3d7edb2e9c0b0e7c525b20aaaef0f5940d2ed71663c7d39266ecafac728859910160405180910390a45050505050565b80356001600160a01b0381168114610673575f5ffd5b919050565b5f5f60408385031215610689575f5ffd5b6106928361065d565b946020939093013593505050565b5f602082840312156106b0575f5ffd5b81356001600160e01b0319811681146106c7575f5ffd5b9392505050565b5f5f5f606084860312156106e0575f5ffd5b6106e98461065d565b95602085013595506040909401359392505050565b5f5f6040838503121561070f575f5ffd5b6107188361065d565b91506020830135801515811461072c575f5ffd5b809150509250929050565b5f5f5f60608486031215610749575f5ffd5b6107528461065d565b92506107606020850161065d565b929592945050506040919091013590565b5f5f60408385031215610782575f5ffd5b61078b8361065d565b91506107996020840161065d565b90509250929050565b5f5f5f5f608085870312156107b5575f5ffd5b6107be8561065d565b93506107cc6020860161065d565b93969395505050506040820135916060013590565b808201808211156101b957634e487b7160e01b5f52601160045260245ffdfea26469706673582212206ae48430b51e065a3a304752b510e8ef5bee4244b8392f1550e4a2c1e93e259e64736f6c634300081b0033", - "deployedBytecode": "0x608060405234801561000f575f5ffd5b5060043610610084575f3560e01c8063558a729711610058578063558a7297146100f7578063598af9e71461010a578063b6363cf214610149578063fe99049a14610184575f5ffd5b8062fdd58e1461008857806301ffc9a7146100ae578063095bcdb6146100d1578063426a8493146100e4575b5f5ffd5b61009b610096366004610678565b610197565b6040519081526020015b60405180910390f35b6100c16100bc3660046106a0565b6101bf565b60405190151581526020016100a5565b6100c16100df3660046106ce565b6101f3565b6100c16100f23660046106ce565b61020a565b6100c16101053660046106fe565b610217565b61009b610118366004610737565b6001600160a01b039283165f9081526002602090815260408083209490951682529283528381209181529152205490565b6100c1610157366004610771565b6001600160a01b039182165f90815260016020908152604080832093909416825291909152205460ff1690565b6100c16101923660046107a2565b61022c565b6001600160a01b0382165f908152602081815260408083208484529091529020545b92915050565b5f6001600160e01b03198216630f632fb360e01b14806101b957506301ffc9a760e01b6001600160e01b03198316146101b9565b5f61020033858585610295565b5060019392505050565b5f610200338585856102fe565b5f6102233384846103bd565b50600192915050565b5f336001600160a01b038616811480159061026c57506001600160a01b038087165f9081526001602090815260408083209385168352929052205460ff16155b1561027d5761027d8682868661047b565b61028986868686610295565b50600195945050505050565b6001600160a01b0384166102c3576040516301486a4160e71b81525f60048201526024015b60405180910390fd5b6001600160a01b0383166102ec57604051630b8bbd6160e41b81525f60048201526024016102ba565b6102f88484848461052b565b50505050565b6001600160a01b0384166103275760405163198ecd5360e31b81525f60048201526024016102ba565b6001600160a01b03831661035057604051636f65f46560e01b81525f60048201526024016102ba565b6001600160a01b038481165f8181526002602090815260408083209488168084529482528083208784528252918290208590559051848152859392917fb3fd5071835887567a0671151121894ddccc2842f1d10bedad13e0d17cace9a7910160405180910390a450505050565b6001600160a01b0383166103e65760405163198ecd5360e31b81525f60048201526024016102ba565b6001600160a01b03821661040f57604051636f65f46560e01b81525f60048201526024016102ba565b6001600160a01b038381165f81815260016020908152604080832094871680845294825291829020805460ff191686151590811790915591519182527fceb576d9f15e4e200fdb5096d64d5dfd667e16def20c1eefd14256d8e3faa267910160405180910390a3505050565b6001600160a01b038481165f9081526002602090815260408083209387168352928152828220858352905220545f1981101561052457818110156104f257604051632c51fead60e11b81526001600160a01b03851660048201526024810182905260448101839052606481018490526084016102ba565b6001600160a01b038086165f908152600260209081526040808320938816835292815282822086835290522082820390555b5050505050565b336001600160a01b038516156105c4576001600160a01b0385165f908152602081815260408083208684529091529020548281101561059d576040516302c6d3fb60e61b81526001600160a01b03871660048201526024810182905260448101849052606481018590526084016102ba565b6001600160a01b0386165f9081526020818152604080832087845290915290209083900390555b6001600160a01b03841615610609576001600160a01b0384165f90815260208181526040808320868452909152812080548492906106039084906107e1565b90915550505b604080516001600160a01b03838116825260208201859052859281881692918916917f1b3d7edb2e9c0b0e7c525b20aaaef0f5940d2ed71663c7d39266ecafac728859910160405180910390a45050505050565b80356001600160a01b0381168114610673575f5ffd5b919050565b5f5f60408385031215610689575f5ffd5b6106928361065d565b946020939093013593505050565b5f602082840312156106b0575f5ffd5b81356001600160e01b0319811681146106c7575f5ffd5b9392505050565b5f5f5f606084860312156106e0575f5ffd5b6106e98461065d565b95602085013595506040909401359392505050565b5f5f6040838503121561070f575f5ffd5b6107188361065d565b91506020830135801515811461072c575f5ffd5b809150509250929050565b5f5f5f60608486031215610749575f5ffd5b6107528461065d565b92506107606020850161065d565b929592945050506040919091013590565b5f5f60408385031215610782575f5ffd5b61078b8361065d565b91506107996020840161065d565b90509250929050565b5f5f5f5f608085870312156107b5575f5ffd5b6107be8561065d565b93506107cc6020860161065d565b93969395505050506040820135916060013590565b808201808211156101b957634e487b7160e01b5f52601160045260245ffdfea26469706673582212206ae48430b51e065a3a304752b510e8ef5bee4244b8392f1550e4a2c1e93e259e64736f6c634300081b0033", + "bytecode": "0x6080604052348015600e575f5ffd5b506108368061001c5f395ff3fe608060405234801561000f575f5ffd5b5060043610610084575f3560e01c8063558a729711610058578063558a7297146100f7578063598af9e71461010a578063b6363cf214610149578063fe99049a14610184575f5ffd5b8062fdd58e1461008857806301ffc9a7146100ae578063095bcdb6146100d1578063426a8493146100e4575b5f5ffd5b61009b610096366004610678565b610197565b6040519081526020015b60405180910390f35b6100c16100bc3660046106a0565b6101bf565b60405190151581526020016100a5565b6100c16100df3660046106ce565b6101f3565b6100c16100f23660046106ce565b61020a565b6100c16101053660046106fe565b610217565b61009b610118366004610737565b6001600160a01b039283165f9081526002602090815260408083209490951682529283528381209181529152205490565b6100c1610157366004610771565b6001600160a01b039182165f90815260016020908152604080832093909416825291909152205460ff1690565b6100c16101923660046107a2565b61022c565b6001600160a01b0382165f908152602081815260408083208484529091529020545b92915050565b5f6001600160e01b03198216630f632fb360e01b14806101b957506301ffc9a760e01b6001600160e01b03198316146101b9565b5f61020033858585610295565b5060019392505050565b5f610200338585856102fe565b5f6102233384846103bd565b50600192915050565b5f336001600160a01b038616811480159061026c57506001600160a01b038087165f9081526001602090815260408083209385168352929052205460ff16155b1561027d5761027d8682868661047b565b61028986868686610295565b50600195945050505050565b6001600160a01b0384166102c3576040516301486a4160e71b81525f60048201526024015b60405180910390fd5b6001600160a01b0383166102ec57604051630b8bbd6160e41b81525f60048201526024016102ba565b6102f88484848461052b565b50505050565b6001600160a01b0384166103275760405163198ecd5360e31b81525f60048201526024016102ba565b6001600160a01b03831661035057604051636f65f46560e01b81525f60048201526024016102ba565b6001600160a01b038481165f8181526002602090815260408083209488168084529482528083208784528252918290208590559051848152859392917fb3fd5071835887567a0671151121894ddccc2842f1d10bedad13e0d17cace9a7910160405180910390a450505050565b6001600160a01b0383166103e65760405163198ecd5360e31b81525f60048201526024016102ba565b6001600160a01b03821661040f57604051636f65f46560e01b81525f60048201526024016102ba565b6001600160a01b038381165f81815260016020908152604080832094871680845294825291829020805460ff191686151590811790915591519182527fceb576d9f15e4e200fdb5096d64d5dfd667e16def20c1eefd14256d8e3faa267910160405180910390a3505050565b6001600160a01b038481165f9081526002602090815260408083209387168352928152828220858352905220545f1981101561052457818110156104f257604051632c51fead60e11b81526001600160a01b03851660048201526024810182905260448101839052606481018490526084016102ba565b6001600160a01b038086165f908152600260209081526040808320938816835292815282822086835290522082820390555b5050505050565b336001600160a01b038516156105c4576001600160a01b0385165f908152602081815260408083208684529091529020548281101561059d576040516302c6d3fb60e61b81526001600160a01b03871660048201526024810182905260448101849052606481018590526084016102ba565b6001600160a01b0386165f9081526020818152604080832087845290915290209083900390555b6001600160a01b03841615610609576001600160a01b0384165f90815260208181526040808320868452909152812080548492906106039084906107e1565b90915550505b604080516001600160a01b03838116825260208201859052859281881692918916917f1b3d7edb2e9c0b0e7c525b20aaaef0f5940d2ed71663c7d39266ecafac728859910160405180910390a45050505050565b80356001600160a01b0381168114610673575f5ffd5b919050565b5f5f60408385031215610689575f5ffd5b6106928361065d565b946020939093013593505050565b5f602082840312156106b0575f5ffd5b81356001600160e01b0319811681146106c7575f5ffd5b9392505050565b5f5f5f606084860312156106e0575f5ffd5b6106e98461065d565b95602085013595506040909401359392505050565b5f5f6040838503121561070f575f5ffd5b6107188361065d565b91506020830135801515811461072c575f5ffd5b809150509250929050565b5f5f5f60608486031215610749575f5ffd5b6107528461065d565b92506107606020850161065d565b929592945050506040919091013590565b5f5f60408385031215610782575f5ffd5b61078b8361065d565b91506107996020840161065d565b90509250929050565b5f5f5f5f608085870312156107b5575f5ffd5b6107be8561065d565b93506107cc6020860161065d565b93969395505050506040820135916060013590565b808201808211156101b957634e487b7160e01b5f52601160045260245ffdfea2646970667358221220c37a5fcd9b50f0ba3f8397668e3c80273253e417641ca46eb84f76aa1f4277ab64736f6c63430008230033", + "deployedBytecode": "0x608060405234801561000f575f5ffd5b5060043610610084575f3560e01c8063558a729711610058578063558a7297146100f7578063598af9e71461010a578063b6363cf214610149578063fe99049a14610184575f5ffd5b8062fdd58e1461008857806301ffc9a7146100ae578063095bcdb6146100d1578063426a8493146100e4575b5f5ffd5b61009b610096366004610678565b610197565b6040519081526020015b60405180910390f35b6100c16100bc3660046106a0565b6101bf565b60405190151581526020016100a5565b6100c16100df3660046106ce565b6101f3565b6100c16100f23660046106ce565b61020a565b6100c16101053660046106fe565b610217565b61009b610118366004610737565b6001600160a01b039283165f9081526002602090815260408083209490951682529283528381209181529152205490565b6100c1610157366004610771565b6001600160a01b039182165f90815260016020908152604080832093909416825291909152205460ff1690565b6100c16101923660046107a2565b61022c565b6001600160a01b0382165f908152602081815260408083208484529091529020545b92915050565b5f6001600160e01b03198216630f632fb360e01b14806101b957506301ffc9a760e01b6001600160e01b03198316146101b9565b5f61020033858585610295565b5060019392505050565b5f610200338585856102fe565b5f6102233384846103bd565b50600192915050565b5f336001600160a01b038616811480159061026c57506001600160a01b038087165f9081526001602090815260408083209385168352929052205460ff16155b1561027d5761027d8682868661047b565b61028986868686610295565b50600195945050505050565b6001600160a01b0384166102c3576040516301486a4160e71b81525f60048201526024015b60405180910390fd5b6001600160a01b0383166102ec57604051630b8bbd6160e41b81525f60048201526024016102ba565b6102f88484848461052b565b50505050565b6001600160a01b0384166103275760405163198ecd5360e31b81525f60048201526024016102ba565b6001600160a01b03831661035057604051636f65f46560e01b81525f60048201526024016102ba565b6001600160a01b038481165f8181526002602090815260408083209488168084529482528083208784528252918290208590559051848152859392917fb3fd5071835887567a0671151121894ddccc2842f1d10bedad13e0d17cace9a7910160405180910390a450505050565b6001600160a01b0383166103e65760405163198ecd5360e31b81525f60048201526024016102ba565b6001600160a01b03821661040f57604051636f65f46560e01b81525f60048201526024016102ba565b6001600160a01b038381165f81815260016020908152604080832094871680845294825291829020805460ff191686151590811790915591519182527fceb576d9f15e4e200fdb5096d64d5dfd667e16def20c1eefd14256d8e3faa267910160405180910390a3505050565b6001600160a01b038481165f9081526002602090815260408083209387168352928152828220858352905220545f1981101561052457818110156104f257604051632c51fead60e11b81526001600160a01b03851660048201526024810182905260448101839052606481018490526084016102ba565b6001600160a01b038086165f908152600260209081526040808320938816835292815282822086835290522082820390555b5050505050565b336001600160a01b038516156105c4576001600160a01b0385165f908152602081815260408083208684529091529020548281101561059d576040516302c6d3fb60e61b81526001600160a01b03871660048201526024810182905260448101849052606481018590526084016102ba565b6001600160a01b0386165f9081526020818152604080832087845290915290209083900390555b6001600160a01b03841615610609576001600160a01b0384165f90815260208181526040808320868452909152812080548492906106039084906107e1565b90915550505b604080516001600160a01b03838116825260208201859052859281881692918916917f1b3d7edb2e9c0b0e7c525b20aaaef0f5940d2ed71663c7d39266ecafac728859910160405180910390a45050505050565b80356001600160a01b0381168114610673575f5ffd5b919050565b5f5f60408385031215610689575f5ffd5b6106928361065d565b946020939093013593505050565b5f602082840312156106b0575f5ffd5b81356001600160e01b0319811681146106c7575f5ffd5b9392505050565b5f5f5f606084860312156106e0575f5ffd5b6106e98461065d565b95602085013595506040909401359392505050565b5f5f6040838503121561070f575f5ffd5b6107188361065d565b91506020830135801515811461072c575f5ffd5b809150509250929050565b5f5f5f60608486031215610749575f5ffd5b6107528461065d565b92506107606020850161065d565b929592945050506040919091013590565b5f5f60408385031215610782575f5ffd5b61078b8361065d565b91506107996020840161065d565b90509250929050565b5f5f5f5f608085870312156107b5575f5ffd5b6107be8561065d565b93506107cc6020860161065d565b93969395505050506040820135916060013590565b808201808211156101b957634e487b7160e01b5f52601160045260245ffdfea2646970667358221220c37a5fcd9b50f0ba3f8397668e3c80273253e417641ca46eb84f76aa1f4277ab64736f6c63430008230033", "linkReferences": {}, "deployedLinkReferences": {} } diff --git a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/ERC6909ContentURI.json b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/ERC6909ContentURI.json similarity index 52% rename from dependencies/@openzeppelin-contracts-5.5.0/build/contracts/ERC6909ContentURI.json rename to dependencies/@openzeppelin-contracts-5.7.0/build/contracts/ERC6909ContentURI.json index d74b0e0..53c9df6 100644 --- a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/ERC6909ContentURI.json +++ b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/ERC6909ContentURI.json @@ -462,8 +462,8 @@ "type": "function" } ], - "bytecode": "0x6080604052348015600e575f5ffd5b50610a278061001c5f395ff3fe608060405234801561000f575f5ffd5b506004361061009a575f3560e01c8063598af9e711610063578063598af9e714610120578063b6363cf21461015f578063c87b56dd1461019a578063e8a3d485146101ba578063fe99049a146101c2575f5ffd5b8062fdd58e1461009e57806301ffc9a7146100c4578063095bcdb6146100e7578063426a8493146100fa578063558a72971461010d575b5f5ffd5b6100b16100ac3660046107e5565b6101d5565b6040519081526020015b60405180910390f35b6100d76100d236600461080d565b6101fd565b60405190151581526020016100bb565b6100d76100f536600461083b565b610231565b6100d761010836600461083b565b610248565b6100d761011b36600461086b565b610255565b6100b161012e3660046108a4565b6001600160a01b039283165f9081526002602090815260408083209490951682529283528381209181529152205490565b6100d761016d3660046108de565b6001600160a01b039182165f90815260016020908152604080832093909416825291909152205460ff1690565b6101ad6101a836600461090f565b61026a565b6040516100bb9190610926565b6101ad610309565b6100d76101d036600461095b565b610399565b6001600160a01b0382165f908152602081815260408083208484529091529020545b92915050565b5f6001600160e01b03198216630f632fb360e01b14806101f757506301ffc9a760e01b6001600160e01b03198316146101f7565b5f61023e33858585610402565b5060019392505050565b5f61023e3385858561046b565b5f61026133848461052a565b50600192915050565b5f8181526004602052604090208054606091906102869061099a565b80601f01602080910402602001604051908101604052809291908181526020018280546102b29061099a565b80156102fd5780601f106102d4576101008083540402835291602001916102fd565b820191905f5260205f20905b8154815290600101906020018083116102e057829003601f168201915b50505050509050919050565b6060600380546103189061099a565b80601f01602080910402602001604051908101604052809291908181526020018280546103449061099a565b801561038f5780601f106103665761010080835404028352916020019161038f565b820191905f5260205f20905b81548152906001019060200180831161037257829003601f168201915b5050505050905090565b5f336001600160a01b03861681148015906103d957506001600160a01b038087165f9081526001602090815260408083209385168352929052205460ff16155b156103ea576103ea868286866105e8565b6103f686868686610402565b50600195945050505050565b6001600160a01b038416610430576040516301486a4160e71b81525f60048201526024015b60405180910390fd5b6001600160a01b03831661045957604051630b8bbd6160e41b81525f6004820152602401610427565b61046584848484610698565b50505050565b6001600160a01b0384166104945760405163198ecd5360e31b81525f6004820152602401610427565b6001600160a01b0383166104bd57604051636f65f46560e01b81525f6004820152602401610427565b6001600160a01b038481165f8181526002602090815260408083209488168084529482528083208784528252918290208590559051848152859392917fb3fd5071835887567a0671151121894ddccc2842f1d10bedad13e0d17cace9a7910160405180910390a450505050565b6001600160a01b0383166105535760405163198ecd5360e31b81525f6004820152602401610427565b6001600160a01b03821661057c57604051636f65f46560e01b81525f6004820152602401610427565b6001600160a01b038381165f81815260016020908152604080832094871680845294825291829020805460ff191686151590811790915591519182527fceb576d9f15e4e200fdb5096d64d5dfd667e16def20c1eefd14256d8e3faa267910160405180910390a3505050565b6001600160a01b038481165f9081526002602090815260408083209387168352928152828220858352905220545f19811015610691578181101561065f57604051632c51fead60e11b81526001600160a01b0385166004820152602481018290526044810183905260648101849052608401610427565b6001600160a01b038086165f908152600260209081526040808320938816835292815282822086835290522082820390555b5050505050565b336001600160a01b03851615610731576001600160a01b0385165f908152602081815260408083208684529091529020548281101561070a576040516302c6d3fb60e61b81526001600160a01b0387166004820152602481018290526044810184905260648101859052608401610427565b6001600160a01b0386165f9081526020818152604080832087845290915290209083900390555b6001600160a01b03841615610776576001600160a01b0384165f90815260208181526040808320868452909152812080548492906107709084906109d2565b90915550505b604080516001600160a01b03838116825260208201859052859281881692918916917f1b3d7edb2e9c0b0e7c525b20aaaef0f5940d2ed71663c7d39266ecafac728859910160405180910390a45050505050565b80356001600160a01b03811681146107e0575f5ffd5b919050565b5f5f604083850312156107f6575f5ffd5b6107ff836107ca565b946020939093013593505050565b5f6020828403121561081d575f5ffd5b81356001600160e01b031981168114610834575f5ffd5b9392505050565b5f5f5f6060848603121561084d575f5ffd5b610856846107ca565b95602085013595506040909401359392505050565b5f5f6040838503121561087c575f5ffd5b610885836107ca565b915060208301358015158114610899575f5ffd5b809150509250929050565b5f5f5f606084860312156108b6575f5ffd5b6108bf846107ca565b92506108cd602085016107ca565b929592945050506040919091013590565b5f5f604083850312156108ef575f5ffd5b6108f8836107ca565b9150610906602084016107ca565b90509250929050565b5f6020828403121561091f575f5ffd5b5035919050565b602081525f82518060208401528060208501604085015e5f604082850101526040601f19601f83011684010191505092915050565b5f5f5f5f6080858703121561096e575f5ffd5b610977856107ca565b9350610985602086016107ca565b93969395505050506040820135916060013590565b600181811c908216806109ae57607f821691505b6020821081036109cc57634e487b7160e01b5f52602260045260245ffd5b50919050565b808201808211156101f757634e487b7160e01b5f52601160045260245ffdfea26469706673582212207248559d8a97570b7883a6de8699d11e9407e877882e573091a4fa40552791b464736f6c634300081b0033", - "deployedBytecode": "0x608060405234801561000f575f5ffd5b506004361061009a575f3560e01c8063598af9e711610063578063598af9e714610120578063b6363cf21461015f578063c87b56dd1461019a578063e8a3d485146101ba578063fe99049a146101c2575f5ffd5b8062fdd58e1461009e57806301ffc9a7146100c4578063095bcdb6146100e7578063426a8493146100fa578063558a72971461010d575b5f5ffd5b6100b16100ac3660046107e5565b6101d5565b6040519081526020015b60405180910390f35b6100d76100d236600461080d565b6101fd565b60405190151581526020016100bb565b6100d76100f536600461083b565b610231565b6100d761010836600461083b565b610248565b6100d761011b36600461086b565b610255565b6100b161012e3660046108a4565b6001600160a01b039283165f9081526002602090815260408083209490951682529283528381209181529152205490565b6100d761016d3660046108de565b6001600160a01b039182165f90815260016020908152604080832093909416825291909152205460ff1690565b6101ad6101a836600461090f565b61026a565b6040516100bb9190610926565b6101ad610309565b6100d76101d036600461095b565b610399565b6001600160a01b0382165f908152602081815260408083208484529091529020545b92915050565b5f6001600160e01b03198216630f632fb360e01b14806101f757506301ffc9a760e01b6001600160e01b03198316146101f7565b5f61023e33858585610402565b5060019392505050565b5f61023e3385858561046b565b5f61026133848461052a565b50600192915050565b5f8181526004602052604090208054606091906102869061099a565b80601f01602080910402602001604051908101604052809291908181526020018280546102b29061099a565b80156102fd5780601f106102d4576101008083540402835291602001916102fd565b820191905f5260205f20905b8154815290600101906020018083116102e057829003601f168201915b50505050509050919050565b6060600380546103189061099a565b80601f01602080910402602001604051908101604052809291908181526020018280546103449061099a565b801561038f5780601f106103665761010080835404028352916020019161038f565b820191905f5260205f20905b81548152906001019060200180831161037257829003601f168201915b5050505050905090565b5f336001600160a01b03861681148015906103d957506001600160a01b038087165f9081526001602090815260408083209385168352929052205460ff16155b156103ea576103ea868286866105e8565b6103f686868686610402565b50600195945050505050565b6001600160a01b038416610430576040516301486a4160e71b81525f60048201526024015b60405180910390fd5b6001600160a01b03831661045957604051630b8bbd6160e41b81525f6004820152602401610427565b61046584848484610698565b50505050565b6001600160a01b0384166104945760405163198ecd5360e31b81525f6004820152602401610427565b6001600160a01b0383166104bd57604051636f65f46560e01b81525f6004820152602401610427565b6001600160a01b038481165f8181526002602090815260408083209488168084529482528083208784528252918290208590559051848152859392917fb3fd5071835887567a0671151121894ddccc2842f1d10bedad13e0d17cace9a7910160405180910390a450505050565b6001600160a01b0383166105535760405163198ecd5360e31b81525f6004820152602401610427565b6001600160a01b03821661057c57604051636f65f46560e01b81525f6004820152602401610427565b6001600160a01b038381165f81815260016020908152604080832094871680845294825291829020805460ff191686151590811790915591519182527fceb576d9f15e4e200fdb5096d64d5dfd667e16def20c1eefd14256d8e3faa267910160405180910390a3505050565b6001600160a01b038481165f9081526002602090815260408083209387168352928152828220858352905220545f19811015610691578181101561065f57604051632c51fead60e11b81526001600160a01b0385166004820152602481018290526044810183905260648101849052608401610427565b6001600160a01b038086165f908152600260209081526040808320938816835292815282822086835290522082820390555b5050505050565b336001600160a01b03851615610731576001600160a01b0385165f908152602081815260408083208684529091529020548281101561070a576040516302c6d3fb60e61b81526001600160a01b0387166004820152602481018290526044810184905260648101859052608401610427565b6001600160a01b0386165f9081526020818152604080832087845290915290209083900390555b6001600160a01b03841615610776576001600160a01b0384165f90815260208181526040808320868452909152812080548492906107709084906109d2565b90915550505b604080516001600160a01b03838116825260208201859052859281881692918916917f1b3d7edb2e9c0b0e7c525b20aaaef0f5940d2ed71663c7d39266ecafac728859910160405180910390a45050505050565b80356001600160a01b03811681146107e0575f5ffd5b919050565b5f5f604083850312156107f6575f5ffd5b6107ff836107ca565b946020939093013593505050565b5f6020828403121561081d575f5ffd5b81356001600160e01b031981168114610834575f5ffd5b9392505050565b5f5f5f6060848603121561084d575f5ffd5b610856846107ca565b95602085013595506040909401359392505050565b5f5f6040838503121561087c575f5ffd5b610885836107ca565b915060208301358015158114610899575f5ffd5b809150509250929050565b5f5f5f606084860312156108b6575f5ffd5b6108bf846107ca565b92506108cd602085016107ca565b929592945050506040919091013590565b5f5f604083850312156108ef575f5ffd5b6108f8836107ca565b9150610906602084016107ca565b90509250929050565b5f6020828403121561091f575f5ffd5b5035919050565b602081525f82518060208401528060208501604085015e5f604082850101526040601f19601f83011684010191505092915050565b5f5f5f5f6080858703121561096e575f5ffd5b610977856107ca565b9350610985602086016107ca565b93969395505050506040820135916060013590565b600181811c908216806109ae57607f821691505b6020821081036109cc57634e487b7160e01b5f52602260045260245ffd5b50919050565b808201808211156101f757634e487b7160e01b5f52601160045260245ffdfea26469706673582212207248559d8a97570b7883a6de8699d11e9407e877882e573091a4fa40552791b464736f6c634300081b0033", + "bytecode": "0x6080604052348015600e575f5ffd5b50610a4b8061001c5f395ff3fe608060405234801561000f575f5ffd5b506004361061009a575f3560e01c8063598af9e711610063578063598af9e714610120578063b6363cf21461015f578063c87b56dd1461019a578063e8a3d485146101ba578063fe99049a146101c2575f5ffd5b8062fdd58e1461009e57806301ffc9a7146100c4578063095bcdb6146100e7578063426a8493146100fa578063558a72971461010d575b5f5ffd5b6100b16100ac366004610809565b6101d5565b6040519081526020015b60405180910390f35b6100d76100d2366004610831565b6101fd565b60405190151581526020016100bb565b6100d76100f536600461085f565b610221565b6100d761010836600461085f565b610238565b6100d761011b36600461088f565b610245565b6100b161012e3660046108c8565b6001600160a01b039283165f9081526002602090815260408083209490951682529283528381209181529152205490565b6100d761016d366004610902565b6001600160a01b039182165f90815260016020908152604080832093909416825291909152205460ff1690565b6101ad6101a8366004610933565b61025a565b6040516100bb919061094a565b6101ad6102f9565b6100d76101d036600461097f565b610389565b6001600160a01b0382165f908152602081815260408083208484529091529020545b92915050565b5f6001600160e01b0319821663041b104b60e31b14806101f757506101f7826103f2565b5f61022e33858585610426565b5060019392505050565b5f61022e3385858561048f565b5f61025133848461054e565b50600192915050565b5f818152600460205260409020805460609190610276906109be565b80601f01602080910402602001604051908101604052809291908181526020018280546102a2906109be565b80156102ed5780601f106102c4576101008083540402835291602001916102ed565b820191905f5260205f20905b8154815290600101906020018083116102d057829003601f168201915b50505050509050919050565b606060038054610308906109be565b80601f0160208091040260200160405190810160405280929190818152602001828054610334906109be565b801561037f5780601f106103565761010080835404028352916020019161037f565b820191905f5260205f20905b81548152906001019060200180831161036257829003601f168201915b5050505050905090565b5f336001600160a01b03861681148015906103c957506001600160a01b038087165f9081526001602090815260408083209385168352929052205460ff16155b156103da576103da8682868661060c565b6103e686868686610426565b50600195945050505050565b5f6001600160e01b03198216630f632fb360e01b14806101f757506301ffc9a760e01b6001600160e01b03198316146101f7565b6001600160a01b038416610454576040516301486a4160e71b81525f60048201526024015b60405180910390fd5b6001600160a01b03831661047d57604051630b8bbd6160e41b81525f600482015260240161044b565b610489848484846106bc565b50505050565b6001600160a01b0384166104b85760405163198ecd5360e31b81525f600482015260240161044b565b6001600160a01b0383166104e157604051636f65f46560e01b81525f600482015260240161044b565b6001600160a01b038481165f8181526002602090815260408083209488168084529482528083208784528252918290208590559051848152859392917fb3fd5071835887567a0671151121894ddccc2842f1d10bedad13e0d17cace9a7910160405180910390a450505050565b6001600160a01b0383166105775760405163198ecd5360e31b81525f600482015260240161044b565b6001600160a01b0382166105a057604051636f65f46560e01b81525f600482015260240161044b565b6001600160a01b038381165f81815260016020908152604080832094871680845294825291829020805460ff191686151590811790915591519182527fceb576d9f15e4e200fdb5096d64d5dfd667e16def20c1eefd14256d8e3faa267910160405180910390a3505050565b6001600160a01b038481165f9081526002602090815260408083209387168352928152828220858352905220545f198110156106b5578181101561068357604051632c51fead60e11b81526001600160a01b038516600482015260248101829052604481018390526064810184905260840161044b565b6001600160a01b038086165f908152600260209081526040808320938816835292815282822086835290522082820390555b5050505050565b336001600160a01b03851615610755576001600160a01b0385165f908152602081815260408083208684529091529020548281101561072e576040516302c6d3fb60e61b81526001600160a01b038716600482015260248101829052604481018490526064810185905260840161044b565b6001600160a01b0386165f9081526020818152604080832087845290915290209083900390555b6001600160a01b0384161561079a576001600160a01b0384165f90815260208181526040808320868452909152812080548492906107949084906109f6565b90915550505b604080516001600160a01b03838116825260208201859052859281881692918916917f1b3d7edb2e9c0b0e7c525b20aaaef0f5940d2ed71663c7d39266ecafac728859910160405180910390a45050505050565b80356001600160a01b0381168114610804575f5ffd5b919050565b5f5f6040838503121561081a575f5ffd5b610823836107ee565b946020939093013593505050565b5f60208284031215610841575f5ffd5b81356001600160e01b031981168114610858575f5ffd5b9392505050565b5f5f5f60608486031215610871575f5ffd5b61087a846107ee565b95602085013595506040909401359392505050565b5f5f604083850312156108a0575f5ffd5b6108a9836107ee565b9150602083013580151581146108bd575f5ffd5b809150509250929050565b5f5f5f606084860312156108da575f5ffd5b6108e3846107ee565b92506108f1602085016107ee565b929592945050506040919091013590565b5f5f60408385031215610913575f5ffd5b61091c836107ee565b915061092a602084016107ee565b90509250929050565b5f60208284031215610943575f5ffd5b5035919050565b602081525f82518060208401528060208501604085015e5f604082850101526040601f19601f83011684010191505092915050565b5f5f5f5f60808587031215610992575f5ffd5b61099b856107ee565b93506109a9602086016107ee565b93969395505050506040820135916060013590565b600181811c908216806109d257607f821691505b6020821081036109f057634e487b7160e01b5f52602260045260245ffd5b50919050565b808201808211156101f757634e487b7160e01b5f52601160045260245ffdfea26469706673582212208bd17bf09dc650ce7cea3cac69d0717b4d366e4f5fb26fa23d81375ad9521f1d64736f6c63430008230033", + "deployedBytecode": "0x608060405234801561000f575f5ffd5b506004361061009a575f3560e01c8063598af9e711610063578063598af9e714610120578063b6363cf21461015f578063c87b56dd1461019a578063e8a3d485146101ba578063fe99049a146101c2575f5ffd5b8062fdd58e1461009e57806301ffc9a7146100c4578063095bcdb6146100e7578063426a8493146100fa578063558a72971461010d575b5f5ffd5b6100b16100ac366004610809565b6101d5565b6040519081526020015b60405180910390f35b6100d76100d2366004610831565b6101fd565b60405190151581526020016100bb565b6100d76100f536600461085f565b610221565b6100d761010836600461085f565b610238565b6100d761011b36600461088f565b610245565b6100b161012e3660046108c8565b6001600160a01b039283165f9081526002602090815260408083209490951682529283528381209181529152205490565b6100d761016d366004610902565b6001600160a01b039182165f90815260016020908152604080832093909416825291909152205460ff1690565b6101ad6101a8366004610933565b61025a565b6040516100bb919061094a565b6101ad6102f9565b6100d76101d036600461097f565b610389565b6001600160a01b0382165f908152602081815260408083208484529091529020545b92915050565b5f6001600160e01b0319821663041b104b60e31b14806101f757506101f7826103f2565b5f61022e33858585610426565b5060019392505050565b5f61022e3385858561048f565b5f61025133848461054e565b50600192915050565b5f818152600460205260409020805460609190610276906109be565b80601f01602080910402602001604051908101604052809291908181526020018280546102a2906109be565b80156102ed5780601f106102c4576101008083540402835291602001916102ed565b820191905f5260205f20905b8154815290600101906020018083116102d057829003601f168201915b50505050509050919050565b606060038054610308906109be565b80601f0160208091040260200160405190810160405280929190818152602001828054610334906109be565b801561037f5780601f106103565761010080835404028352916020019161037f565b820191905f5260205f20905b81548152906001019060200180831161036257829003601f168201915b5050505050905090565b5f336001600160a01b03861681148015906103c957506001600160a01b038087165f9081526001602090815260408083209385168352929052205460ff16155b156103da576103da8682868661060c565b6103e686868686610426565b50600195945050505050565b5f6001600160e01b03198216630f632fb360e01b14806101f757506301ffc9a760e01b6001600160e01b03198316146101f7565b6001600160a01b038416610454576040516301486a4160e71b81525f60048201526024015b60405180910390fd5b6001600160a01b03831661047d57604051630b8bbd6160e41b81525f600482015260240161044b565b610489848484846106bc565b50505050565b6001600160a01b0384166104b85760405163198ecd5360e31b81525f600482015260240161044b565b6001600160a01b0383166104e157604051636f65f46560e01b81525f600482015260240161044b565b6001600160a01b038481165f8181526002602090815260408083209488168084529482528083208784528252918290208590559051848152859392917fb3fd5071835887567a0671151121894ddccc2842f1d10bedad13e0d17cace9a7910160405180910390a450505050565b6001600160a01b0383166105775760405163198ecd5360e31b81525f600482015260240161044b565b6001600160a01b0382166105a057604051636f65f46560e01b81525f600482015260240161044b565b6001600160a01b038381165f81815260016020908152604080832094871680845294825291829020805460ff191686151590811790915591519182527fceb576d9f15e4e200fdb5096d64d5dfd667e16def20c1eefd14256d8e3faa267910160405180910390a3505050565b6001600160a01b038481165f9081526002602090815260408083209387168352928152828220858352905220545f198110156106b5578181101561068357604051632c51fead60e11b81526001600160a01b038516600482015260248101829052604481018390526064810184905260840161044b565b6001600160a01b038086165f908152600260209081526040808320938816835292815282822086835290522082820390555b5050505050565b336001600160a01b03851615610755576001600160a01b0385165f908152602081815260408083208684529091529020548281101561072e576040516302c6d3fb60e61b81526001600160a01b038716600482015260248101829052604481018490526064810185905260840161044b565b6001600160a01b0386165f9081526020818152604080832087845290915290209083900390555b6001600160a01b0384161561079a576001600160a01b0384165f90815260208181526040808320868452909152812080548492906107949084906109f6565b90915550505b604080516001600160a01b03838116825260208201859052859281881692918916917f1b3d7edb2e9c0b0e7c525b20aaaef0f5940d2ed71663c7d39266ecafac728859910160405180910390a45050505050565b80356001600160a01b0381168114610804575f5ffd5b919050565b5f5f6040838503121561081a575f5ffd5b610823836107ee565b946020939093013593505050565b5f60208284031215610841575f5ffd5b81356001600160e01b031981168114610858575f5ffd5b9392505050565b5f5f5f60608486031215610871575f5ffd5b61087a846107ee565b95602085013595506040909401359392505050565b5f5f604083850312156108a0575f5ffd5b6108a9836107ee565b9150602083013580151581146108bd575f5ffd5b809150509250929050565b5f5f5f606084860312156108da575f5ffd5b6108e3846107ee565b92506108f1602085016107ee565b929592945050506040919091013590565b5f5f60408385031215610913575f5ffd5b61091c836107ee565b915061092a602084016107ee565b90509250929050565b5f60208284031215610943575f5ffd5b5035919050565b602081525f82518060208401528060208501604085015e5f604082850101526040601f19601f83011684010191505092915050565b5f5f5f5f60808587031215610992575f5ffd5b61099b856107ee565b93506109a9602086016107ee565b93969395505050506040820135916060013590565b600181811c908216806109d257607f821691505b6020821081036109f057634e487b7160e01b5f52602260045260245ffd5b50919050565b808201808211156101f757634e487b7160e01b5f52601160045260245ffdfea26469706673582212208bd17bf09dc650ce7cea3cac69d0717b4d366e4f5fb26fa23d81375ad9521f1d64736f6c63430008230033", "linkReferences": {}, "deployedLinkReferences": {} } diff --git a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/ERC6909Metadata.json b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/ERC6909Metadata.json similarity index 57% rename from dependencies/@openzeppelin-contracts-5.5.0/build/contracts/ERC6909Metadata.json rename to dependencies/@openzeppelin-contracts-5.7.0/build/contracts/ERC6909Metadata.json index f1032d5..10c614a 100644 --- a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/ERC6909Metadata.json +++ b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/ERC6909Metadata.json @@ -519,8 +519,8 @@ "type": "function" } ], - "bytecode": "0x6080604052348015600e575f5ffd5b50610a068061001c5f395ff3fe608060405234801561000f575f5ffd5b50600436106100a4575f3560e01c8063426a84931161006e578063426a84931461015f5780634e41a1fb14610172578063558a729714610185578063598af9e714610198578063b6363cf2146101d7578063fe99049a14610212575f5ffd5b8062ad800c146100a8578062fdd58e146100d157806301ffc9a7146100f2578063095bcdb6146101155780633f47e66214610128575b5f5ffd5b6100bb6100b63660046107a9565b610225565b6040516100c891906107c0565b60405180910390f35b6100e46100df366004610810565b6102c4565b6040519081526020016100c8565b610105610100366004610838565b6102ec565b60405190151581526020016100c8565b610105610123366004610866565b610320565b61014d6101363660046107a9565b5f9081526003602052604090206002015460ff1690565b60405160ff90911681526020016100c8565b61010561016d366004610866565b610337565b6100bb6101803660046107a9565b610344565b610105610193366004610896565b610363565b6100e46101a63660046108cf565b6001600160a01b039283165f9081526002602090815260408083209490951682529283528381209181529152205490565b6101056101e5366004610909565b6001600160a01b039182165f90815260016020908152604080832093909416825291909152205460ff1690565b61010561022036600461093a565b610378565b5f81815260036020526040902080546060919061024190610979565b80601f016020809104026020016040519081016040528092919081815260200182805461026d90610979565b80156102b85780601f1061028f576101008083540402835291602001916102b8565b820191905f5260205f20905b81548152906001019060200180831161029b57829003601f168201915b50505050509050919050565b6001600160a01b0382165f908152602081815260408083208484529091529020545b92915050565b5f6001600160e01b03198216630f632fb360e01b14806102e657506301ffc9a760e01b6001600160e01b03198316146102e6565b5f61032d338585856103e1565b5060019392505050565b5f61032d3385858561044a565b5f81815260036020526040902060010180546060919061024190610979565b5f61036f338484610509565b50600192915050565b5f336001600160a01b03861681148015906103b857506001600160a01b038087165f9081526001602090815260408083209385168352929052205460ff16155b156103c9576103c9868286866105c7565b6103d5868686866103e1565b50600195945050505050565b6001600160a01b03841661040f576040516301486a4160e71b81525f60048201526024015b60405180910390fd5b6001600160a01b03831661043857604051630b8bbd6160e41b81525f6004820152602401610406565b61044484848484610677565b50505050565b6001600160a01b0384166104735760405163198ecd5360e31b81525f6004820152602401610406565b6001600160a01b03831661049c57604051636f65f46560e01b81525f6004820152602401610406565b6001600160a01b038481165f8181526002602090815260408083209488168084529482528083208784528252918290208590559051848152859392917fb3fd5071835887567a0671151121894ddccc2842f1d10bedad13e0d17cace9a7910160405180910390a450505050565b6001600160a01b0383166105325760405163198ecd5360e31b81525f6004820152602401610406565b6001600160a01b03821661055b57604051636f65f46560e01b81525f6004820152602401610406565b6001600160a01b038381165f81815260016020908152604080832094871680845294825291829020805460ff191686151590811790915591519182527fceb576d9f15e4e200fdb5096d64d5dfd667e16def20c1eefd14256d8e3faa267910160405180910390a3505050565b6001600160a01b038481165f9081526002602090815260408083209387168352928152828220858352905220545f19811015610670578181101561063e57604051632c51fead60e11b81526001600160a01b0385166004820152602481018290526044810183905260648101849052608401610406565b6001600160a01b038086165f908152600260209081526040808320938816835292815282822086835290522082820390555b5050505050565b336001600160a01b03851615610710576001600160a01b0385165f90815260208181526040808320868452909152902054828110156106e9576040516302c6d3fb60e61b81526001600160a01b0387166004820152602481018290526044810184905260648101859052608401610406565b6001600160a01b0386165f9081526020818152604080832087845290915290209083900390555b6001600160a01b03841615610755576001600160a01b0384165f908152602081815260408083208684529091528120805484929061074f9084906109b1565b90915550505b604080516001600160a01b03838116825260208201859052859281881692918916917f1b3d7edb2e9c0b0e7c525b20aaaef0f5940d2ed71663c7d39266ecafac728859910160405180910390a45050505050565b5f602082840312156107b9575f5ffd5b5035919050565b602081525f82518060208401528060208501604085015e5f604082850101526040601f19601f83011684010191505092915050565b80356001600160a01b038116811461080b575f5ffd5b919050565b5f5f60408385031215610821575f5ffd5b61082a836107f5565b946020939093013593505050565b5f60208284031215610848575f5ffd5b81356001600160e01b03198116811461085f575f5ffd5b9392505050565b5f5f5f60608486031215610878575f5ffd5b610881846107f5565b95602085013595506040909401359392505050565b5f5f604083850312156108a7575f5ffd5b6108b0836107f5565b9150602083013580151581146108c4575f5ffd5b809150509250929050565b5f5f5f606084860312156108e1575f5ffd5b6108ea846107f5565b92506108f8602085016107f5565b929592945050506040919091013590565b5f5f6040838503121561091a575f5ffd5b610923836107f5565b9150610931602084016107f5565b90509250929050565b5f5f5f5f6080858703121561094d575f5ffd5b610956856107f5565b9350610964602086016107f5565b93969395505050506040820135916060013590565b600181811c9082168061098d57607f821691505b6020821081036109ab57634e487b7160e01b5f52602260045260245ffd5b50919050565b808201808211156102e657634e487b7160e01b5f52601160045260245ffdfea264697066735822122050bca54e2dc772839a9678bebb61b7bb082f7ba4d2d7dae7aa49e9533c1249f364736f6c634300081b0033", - "deployedBytecode": "0x608060405234801561000f575f5ffd5b50600436106100a4575f3560e01c8063426a84931161006e578063426a84931461015f5780634e41a1fb14610172578063558a729714610185578063598af9e714610198578063b6363cf2146101d7578063fe99049a14610212575f5ffd5b8062ad800c146100a8578062fdd58e146100d157806301ffc9a7146100f2578063095bcdb6146101155780633f47e66214610128575b5f5ffd5b6100bb6100b63660046107a9565b610225565b6040516100c891906107c0565b60405180910390f35b6100e46100df366004610810565b6102c4565b6040519081526020016100c8565b610105610100366004610838565b6102ec565b60405190151581526020016100c8565b610105610123366004610866565b610320565b61014d6101363660046107a9565b5f9081526003602052604090206002015460ff1690565b60405160ff90911681526020016100c8565b61010561016d366004610866565b610337565b6100bb6101803660046107a9565b610344565b610105610193366004610896565b610363565b6100e46101a63660046108cf565b6001600160a01b039283165f9081526002602090815260408083209490951682529283528381209181529152205490565b6101056101e5366004610909565b6001600160a01b039182165f90815260016020908152604080832093909416825291909152205460ff1690565b61010561022036600461093a565b610378565b5f81815260036020526040902080546060919061024190610979565b80601f016020809104026020016040519081016040528092919081815260200182805461026d90610979565b80156102b85780601f1061028f576101008083540402835291602001916102b8565b820191905f5260205f20905b81548152906001019060200180831161029b57829003601f168201915b50505050509050919050565b6001600160a01b0382165f908152602081815260408083208484529091529020545b92915050565b5f6001600160e01b03198216630f632fb360e01b14806102e657506301ffc9a760e01b6001600160e01b03198316146102e6565b5f61032d338585856103e1565b5060019392505050565b5f61032d3385858561044a565b5f81815260036020526040902060010180546060919061024190610979565b5f61036f338484610509565b50600192915050565b5f336001600160a01b03861681148015906103b857506001600160a01b038087165f9081526001602090815260408083209385168352929052205460ff16155b156103c9576103c9868286866105c7565b6103d5868686866103e1565b50600195945050505050565b6001600160a01b03841661040f576040516301486a4160e71b81525f60048201526024015b60405180910390fd5b6001600160a01b03831661043857604051630b8bbd6160e41b81525f6004820152602401610406565b61044484848484610677565b50505050565b6001600160a01b0384166104735760405163198ecd5360e31b81525f6004820152602401610406565b6001600160a01b03831661049c57604051636f65f46560e01b81525f6004820152602401610406565b6001600160a01b038481165f8181526002602090815260408083209488168084529482528083208784528252918290208590559051848152859392917fb3fd5071835887567a0671151121894ddccc2842f1d10bedad13e0d17cace9a7910160405180910390a450505050565b6001600160a01b0383166105325760405163198ecd5360e31b81525f6004820152602401610406565b6001600160a01b03821661055b57604051636f65f46560e01b81525f6004820152602401610406565b6001600160a01b038381165f81815260016020908152604080832094871680845294825291829020805460ff191686151590811790915591519182527fceb576d9f15e4e200fdb5096d64d5dfd667e16def20c1eefd14256d8e3faa267910160405180910390a3505050565b6001600160a01b038481165f9081526002602090815260408083209387168352928152828220858352905220545f19811015610670578181101561063e57604051632c51fead60e11b81526001600160a01b0385166004820152602481018290526044810183905260648101849052608401610406565b6001600160a01b038086165f908152600260209081526040808320938816835292815282822086835290522082820390555b5050505050565b336001600160a01b03851615610710576001600160a01b0385165f90815260208181526040808320868452909152902054828110156106e9576040516302c6d3fb60e61b81526001600160a01b0387166004820152602481018290526044810184905260648101859052608401610406565b6001600160a01b0386165f9081526020818152604080832087845290915290209083900390555b6001600160a01b03841615610755576001600160a01b0384165f908152602081815260408083208684529091528120805484929061074f9084906109b1565b90915550505b604080516001600160a01b03838116825260208201859052859281881692918916917f1b3d7edb2e9c0b0e7c525b20aaaef0f5940d2ed71663c7d39266ecafac728859910160405180910390a45050505050565b5f602082840312156107b9575f5ffd5b5035919050565b602081525f82518060208401528060208501604085015e5f604082850101526040601f19601f83011684010191505092915050565b80356001600160a01b038116811461080b575f5ffd5b919050565b5f5f60408385031215610821575f5ffd5b61082a836107f5565b946020939093013593505050565b5f60208284031215610848575f5ffd5b81356001600160e01b03198116811461085f575f5ffd5b9392505050565b5f5f5f60608486031215610878575f5ffd5b610881846107f5565b95602085013595506040909401359392505050565b5f5f604083850312156108a7575f5ffd5b6108b0836107f5565b9150602083013580151581146108c4575f5ffd5b809150509250929050565b5f5f5f606084860312156108e1575f5ffd5b6108ea846107f5565b92506108f8602085016107f5565b929592945050506040919091013590565b5f5f6040838503121561091a575f5ffd5b610923836107f5565b9150610931602084016107f5565b90509250929050565b5f5f5f5f6080858703121561094d575f5ffd5b610956856107f5565b9350610964602086016107f5565b93969395505050506040820135916060013590565b600181811c9082168061098d57607f821691505b6020821081036109ab57634e487b7160e01b5f52602260045260245ffd5b50919050565b808201808211156102e657634e487b7160e01b5f52601160045260245ffdfea264697066735822122050bca54e2dc772839a9678bebb61b7bb082f7ba4d2d7dae7aa49e9533c1249f364736f6c634300081b0033", + "bytecode": "0x6080604052348015600e575f5ffd5b50610a2a8061001c5f395ff3fe608060405234801561000f575f5ffd5b50600436106100a4575f3560e01c8063426a84931161006e578063426a84931461015f5780634e41a1fb14610172578063558a729714610185578063598af9e714610198578063b6363cf2146101d7578063fe99049a14610212575f5ffd5b8062ad800c146100a8578062fdd58e146100d157806301ffc9a7146100f2578063095bcdb6146101155780633f47e66214610128575b5f5ffd5b6100bb6100b63660046107cd565b610225565b6040516100c891906107e4565b60405180910390f35b6100e46100df366004610834565b6102c4565b6040519081526020016100c8565b61010561010036600461085c565b6102ec565b60405190151581526020016100c8565b61010561012336600461088a565b610310565b61014d6101363660046107cd565b5f9081526003602052604090206002015460ff1690565b60405160ff90911681526020016100c8565b61010561016d36600461088a565b610327565b6100bb6101803660046107cd565b610334565b6101056101933660046108ba565b610353565b6100e46101a63660046108f3565b6001600160a01b039283165f9081526002602090815260408083209490951682529283528381209181529152205490565b6101056101e536600461092d565b6001600160a01b039182165f90815260016020908152604080832093909416825291909152205460ff1690565b61010561022036600461095e565b610368565b5f8181526003602052604090208054606091906102419061099d565b80601f016020809104026020016040519081016040528092919081815260200182805461026d9061099d565b80156102b85780601f1061028f576101008083540402835291602001916102b8565b820191905f5260205f20905b81548152906001019060200180831161029b57829003601f168201915b50505050509050919050565b6001600160a01b0382165f908152602081815260408083208484529091529020545b92915050565b5f6001600160e01b031982166371abc79560e01b14806102e657506102e6826103d1565b5f61031d33858585610405565b5060019392505050565b5f61031d3385858561046e565b5f8181526003602052604090206001018054606091906102419061099d565b5f61035f33848461052d565b50600192915050565b5f336001600160a01b03861681148015906103a857506001600160a01b038087165f9081526001602090815260408083209385168352929052205460ff16155b156103b9576103b9868286866105eb565b6103c586868686610405565b50600195945050505050565b5f6001600160e01b03198216630f632fb360e01b14806102e657506301ffc9a760e01b6001600160e01b03198316146102e6565b6001600160a01b038416610433576040516301486a4160e71b81525f60048201526024015b60405180910390fd5b6001600160a01b03831661045c57604051630b8bbd6160e41b81525f600482015260240161042a565b6104688484848461069b565b50505050565b6001600160a01b0384166104975760405163198ecd5360e31b81525f600482015260240161042a565b6001600160a01b0383166104c057604051636f65f46560e01b81525f600482015260240161042a565b6001600160a01b038481165f8181526002602090815260408083209488168084529482528083208784528252918290208590559051848152859392917fb3fd5071835887567a0671151121894ddccc2842f1d10bedad13e0d17cace9a7910160405180910390a450505050565b6001600160a01b0383166105565760405163198ecd5360e31b81525f600482015260240161042a565b6001600160a01b03821661057f57604051636f65f46560e01b81525f600482015260240161042a565b6001600160a01b038381165f81815260016020908152604080832094871680845294825291829020805460ff191686151590811790915591519182527fceb576d9f15e4e200fdb5096d64d5dfd667e16def20c1eefd14256d8e3faa267910160405180910390a3505050565b6001600160a01b038481165f9081526002602090815260408083209387168352928152828220858352905220545f19811015610694578181101561066257604051632c51fead60e11b81526001600160a01b038516600482015260248101829052604481018390526064810184905260840161042a565b6001600160a01b038086165f908152600260209081526040808320938816835292815282822086835290522082820390555b5050505050565b336001600160a01b03851615610734576001600160a01b0385165f908152602081815260408083208684529091529020548281101561070d576040516302c6d3fb60e61b81526001600160a01b038716600482015260248101829052604481018490526064810185905260840161042a565b6001600160a01b0386165f9081526020818152604080832087845290915290209083900390555b6001600160a01b03841615610779576001600160a01b0384165f90815260208181526040808320868452909152812080548492906107739084906109d5565b90915550505b604080516001600160a01b03838116825260208201859052859281881692918916917f1b3d7edb2e9c0b0e7c525b20aaaef0f5940d2ed71663c7d39266ecafac728859910160405180910390a45050505050565b5f602082840312156107dd575f5ffd5b5035919050565b602081525f82518060208401528060208501604085015e5f604082850101526040601f19601f83011684010191505092915050565b80356001600160a01b038116811461082f575f5ffd5b919050565b5f5f60408385031215610845575f5ffd5b61084e83610819565b946020939093013593505050565b5f6020828403121561086c575f5ffd5b81356001600160e01b031981168114610883575f5ffd5b9392505050565b5f5f5f6060848603121561089c575f5ffd5b6108a584610819565b95602085013595506040909401359392505050565b5f5f604083850312156108cb575f5ffd5b6108d483610819565b9150602083013580151581146108e8575f5ffd5b809150509250929050565b5f5f5f60608486031215610905575f5ffd5b61090e84610819565b925061091c60208501610819565b929592945050506040919091013590565b5f5f6040838503121561093e575f5ffd5b61094783610819565b915061095560208401610819565b90509250929050565b5f5f5f5f60808587031215610971575f5ffd5b61097a85610819565b935061098860208601610819565b93969395505050506040820135916060013590565b600181811c908216806109b157607f821691505b6020821081036109cf57634e487b7160e01b5f52602260045260245ffd5b50919050565b808201808211156102e657634e487b7160e01b5f52601160045260245ffdfea264697066735822122044f1807dd57913464c11c333e3434d3a97460055d91306e41aae58c960de3a5964736f6c63430008230033", + "deployedBytecode": "0x608060405234801561000f575f5ffd5b50600436106100a4575f3560e01c8063426a84931161006e578063426a84931461015f5780634e41a1fb14610172578063558a729714610185578063598af9e714610198578063b6363cf2146101d7578063fe99049a14610212575f5ffd5b8062ad800c146100a8578062fdd58e146100d157806301ffc9a7146100f2578063095bcdb6146101155780633f47e66214610128575b5f5ffd5b6100bb6100b63660046107cd565b610225565b6040516100c891906107e4565b60405180910390f35b6100e46100df366004610834565b6102c4565b6040519081526020016100c8565b61010561010036600461085c565b6102ec565b60405190151581526020016100c8565b61010561012336600461088a565b610310565b61014d6101363660046107cd565b5f9081526003602052604090206002015460ff1690565b60405160ff90911681526020016100c8565b61010561016d36600461088a565b610327565b6100bb6101803660046107cd565b610334565b6101056101933660046108ba565b610353565b6100e46101a63660046108f3565b6001600160a01b039283165f9081526002602090815260408083209490951682529283528381209181529152205490565b6101056101e536600461092d565b6001600160a01b039182165f90815260016020908152604080832093909416825291909152205460ff1690565b61010561022036600461095e565b610368565b5f8181526003602052604090208054606091906102419061099d565b80601f016020809104026020016040519081016040528092919081815260200182805461026d9061099d565b80156102b85780601f1061028f576101008083540402835291602001916102b8565b820191905f5260205f20905b81548152906001019060200180831161029b57829003601f168201915b50505050509050919050565b6001600160a01b0382165f908152602081815260408083208484529091529020545b92915050565b5f6001600160e01b031982166371abc79560e01b14806102e657506102e6826103d1565b5f61031d33858585610405565b5060019392505050565b5f61031d3385858561046e565b5f8181526003602052604090206001018054606091906102419061099d565b5f61035f33848461052d565b50600192915050565b5f336001600160a01b03861681148015906103a857506001600160a01b038087165f9081526001602090815260408083209385168352929052205460ff16155b156103b9576103b9868286866105eb565b6103c586868686610405565b50600195945050505050565b5f6001600160e01b03198216630f632fb360e01b14806102e657506301ffc9a760e01b6001600160e01b03198316146102e6565b6001600160a01b038416610433576040516301486a4160e71b81525f60048201526024015b60405180910390fd5b6001600160a01b03831661045c57604051630b8bbd6160e41b81525f600482015260240161042a565b6104688484848461069b565b50505050565b6001600160a01b0384166104975760405163198ecd5360e31b81525f600482015260240161042a565b6001600160a01b0383166104c057604051636f65f46560e01b81525f600482015260240161042a565b6001600160a01b038481165f8181526002602090815260408083209488168084529482528083208784528252918290208590559051848152859392917fb3fd5071835887567a0671151121894ddccc2842f1d10bedad13e0d17cace9a7910160405180910390a450505050565b6001600160a01b0383166105565760405163198ecd5360e31b81525f600482015260240161042a565b6001600160a01b03821661057f57604051636f65f46560e01b81525f600482015260240161042a565b6001600160a01b038381165f81815260016020908152604080832094871680845294825291829020805460ff191686151590811790915591519182527fceb576d9f15e4e200fdb5096d64d5dfd667e16def20c1eefd14256d8e3faa267910160405180910390a3505050565b6001600160a01b038481165f9081526002602090815260408083209387168352928152828220858352905220545f19811015610694578181101561066257604051632c51fead60e11b81526001600160a01b038516600482015260248101829052604481018390526064810184905260840161042a565b6001600160a01b038086165f908152600260209081526040808320938816835292815282822086835290522082820390555b5050505050565b336001600160a01b03851615610734576001600160a01b0385165f908152602081815260408083208684529091529020548281101561070d576040516302c6d3fb60e61b81526001600160a01b038716600482015260248101829052604481018490526064810185905260840161042a565b6001600160a01b0386165f9081526020818152604080832087845290915290209083900390555b6001600160a01b03841615610779576001600160a01b0384165f90815260208181526040808320868452909152812080548492906107739084906109d5565b90915550505b604080516001600160a01b03838116825260208201859052859281881692918916917f1b3d7edb2e9c0b0e7c525b20aaaef0f5940d2ed71663c7d39266ecafac728859910160405180910390a45050505050565b5f602082840312156107dd575f5ffd5b5035919050565b602081525f82518060208401528060208501604085015e5f604082850101526040601f19601f83011684010191505092915050565b80356001600160a01b038116811461082f575f5ffd5b919050565b5f5f60408385031215610845575f5ffd5b61084e83610819565b946020939093013593505050565b5f6020828403121561086c575f5ffd5b81356001600160e01b031981168114610883575f5ffd5b9392505050565b5f5f5f6060848603121561089c575f5ffd5b6108a584610819565b95602085013595506040909401359392505050565b5f5f604083850312156108cb575f5ffd5b6108d483610819565b9150602083013580151581146108e8575f5ffd5b809150509250929050565b5f5f5f60608486031215610905575f5ffd5b61090e84610819565b925061091c60208501610819565b929592945050506040919091013590565b5f5f6040838503121561093e575f5ffd5b61094783610819565b915061095560208401610819565b90509250929050565b5f5f5f5f60808587031215610971575f5ffd5b61097a85610819565b935061098860208601610819565b93969395505050506040820135916060013590565b600181811c908216806109b157607f821691505b6020821081036109cf57634e487b7160e01b5f52602260045260245ffd5b50919050565b808201808211156102e657634e487b7160e01b5f52601160045260245ffdfea264697066735822122044f1807dd57913464c11c333e3434d3a97460055d91306e41aae58c960de3a5964736f6c63430008230033", "linkReferences": {}, "deployedLinkReferences": {} } diff --git a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/ERC6909TokenSupply.json b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/ERC6909TokenSupply.json similarity index 53% rename from dependencies/@openzeppelin-contracts-5.5.0/build/contracts/ERC6909TokenSupply.json rename to dependencies/@openzeppelin-contracts-5.7.0/build/contracts/ERC6909TokenSupply.json index e4fc499..6eb5d7a 100644 --- a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/ERC6909TokenSupply.json +++ b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/ERC6909TokenSupply.json @@ -424,8 +424,8 @@ "type": "function" } ], - "bytecode": "0x6080604052348015600e575f5ffd5b506108dc8061001c5f395ff3fe608060405234801561000f575f5ffd5b506004361061008f575f3560e01c8063558a729711610063578063558a729714610102578063598af9e714610115578063b6363cf214610154578063bd85b0391461018f578063fe99049a146101ae575f5ffd5b8062fdd58e1461009357806301ffc9a7146100b9578063095bcdb6146100dc578063426a8493146100ef575b5f5ffd5b6100a66100a1366004610707565b6101c1565b6040519081526020015b60405180910390f35b6100cc6100c736600461072f565b6101e9565b60405190151581526020016100b0565b6100cc6100ea36600461075d565b61021d565b6100cc6100fd36600461075d565b610234565b6100cc61011036600461078d565b610241565b6100a66101233660046107c6565b6001600160a01b039283165f9081526002602090815260408083209490951682529283528381209181529152205490565b6100cc610162366004610800565b6001600160a01b039182165f90815260016020908152604080832093909416825291909152205460ff1690565b6100a661019d366004610831565b5f9081526003602052604090205490565b6100cc6101bc366004610848565b610256565b6001600160a01b0382165f908152602081815260408083208484529091529020545b92915050565b5f6001600160e01b03198216630f632fb360e01b14806101e357506301ffc9a760e01b6001600160e01b03198316146101e3565b5f61022a338585856102bf565b5060019392505050565b5f61022a33858585610328565b5f61024d3384846103e7565b50600192915050565b5f336001600160a01b038616811480159061029657506001600160a01b038087165f9081526001602090815260408083209385168352929052205460ff16155b156102a7576102a7868286866104a5565b6102b3868686866102bf565b50600195945050505050565b6001600160a01b0384166102ed576040516301486a4160e71b81525f60048201526024015b60405180910390fd5b6001600160a01b03831661031657604051630b8bbd6160e41b81525f60048201526024016102e4565b61032284848484610555565b50505050565b6001600160a01b0384166103515760405163198ecd5360e31b81525f60048201526024016102e4565b6001600160a01b03831661037a57604051636f65f46560e01b81525f60048201526024016102e4565b6001600160a01b038481165f8181526002602090815260408083209488168084529482528083208784528252918290208590559051848152859392917fb3fd5071835887567a0671151121894ddccc2842f1d10bedad13e0d17cace9a7910160405180910390a450505050565b6001600160a01b0383166104105760405163198ecd5360e31b81525f60048201526024016102e4565b6001600160a01b03821661043957604051636f65f46560e01b81525f60048201526024016102e4565b6001600160a01b038381165f81815260016020908152604080832094871680845294825291829020805460ff191686151590811790915591519182527fceb576d9f15e4e200fdb5096d64d5dfd667e16def20c1eefd14256d8e3faa267910160405180910390a3505050565b6001600160a01b038481165f9081526002602090815260408083209387168352928152828220858352905220545f1981101561054e578181101561051c57604051632c51fead60e11b81526001600160a01b03851660048201526024810182905260448101839052606481018490526084016102e4565b6001600160a01b038086165f908152600260209081526040808320938816835292815282822086835290522082820390555b5050505050565b610561848484846105ba565b6001600160a01b038416610592575f828152600360205260408120805483929061058c908490610887565b90915550505b6001600160a01b038316610322575f8281526003602052604090208054829003905550505050565b336001600160a01b03851615610653576001600160a01b0385165f908152602081815260408083208684529091529020548281101561062c576040516302c6d3fb60e61b81526001600160a01b03871660048201526024810182905260448101849052606481018590526084016102e4565b6001600160a01b0386165f9081526020818152604080832087845290915290209083900390555b6001600160a01b03841615610698576001600160a01b0384165f9081526020818152604080832086845290915281208054849290610692908490610887565b90915550505b604080516001600160a01b03838116825260208201859052859281881692918916917f1b3d7edb2e9c0b0e7c525b20aaaef0f5940d2ed71663c7d39266ecafac728859910160405180910390a45050505050565b80356001600160a01b0381168114610702575f5ffd5b919050565b5f5f60408385031215610718575f5ffd5b610721836106ec565b946020939093013593505050565b5f6020828403121561073f575f5ffd5b81356001600160e01b031981168114610756575f5ffd5b9392505050565b5f5f5f6060848603121561076f575f5ffd5b610778846106ec565b95602085013595506040909401359392505050565b5f5f6040838503121561079e575f5ffd5b6107a7836106ec565b9150602083013580151581146107bb575f5ffd5b809150509250929050565b5f5f5f606084860312156107d8575f5ffd5b6107e1846106ec565b92506107ef602085016106ec565b929592945050506040919091013590565b5f5f60408385031215610811575f5ffd5b61081a836106ec565b9150610828602084016106ec565b90509250929050565b5f60208284031215610841575f5ffd5b5035919050565b5f5f5f5f6080858703121561085b575f5ffd5b610864856106ec565b9350610872602086016106ec565b93969395505050506040820135916060013590565b808201808211156101e357634e487b7160e01b5f52601160045260245ffdfea2646970667358221220499fa08f925af6ff8269e72361d5a67580c571a6208d3335790bab5a7b00837d64736f6c634300081b0033", - "deployedBytecode": "0x608060405234801561000f575f5ffd5b506004361061008f575f3560e01c8063558a729711610063578063558a729714610102578063598af9e714610115578063b6363cf214610154578063bd85b0391461018f578063fe99049a146101ae575f5ffd5b8062fdd58e1461009357806301ffc9a7146100b9578063095bcdb6146100dc578063426a8493146100ef575b5f5ffd5b6100a66100a1366004610707565b6101c1565b6040519081526020015b60405180910390f35b6100cc6100c736600461072f565b6101e9565b60405190151581526020016100b0565b6100cc6100ea36600461075d565b61021d565b6100cc6100fd36600461075d565b610234565b6100cc61011036600461078d565b610241565b6100a66101233660046107c6565b6001600160a01b039283165f9081526002602090815260408083209490951682529283528381209181529152205490565b6100cc610162366004610800565b6001600160a01b039182165f90815260016020908152604080832093909416825291909152205460ff1690565b6100a661019d366004610831565b5f9081526003602052604090205490565b6100cc6101bc366004610848565b610256565b6001600160a01b0382165f908152602081815260408083208484529091529020545b92915050565b5f6001600160e01b03198216630f632fb360e01b14806101e357506301ffc9a760e01b6001600160e01b03198316146101e3565b5f61022a338585856102bf565b5060019392505050565b5f61022a33858585610328565b5f61024d3384846103e7565b50600192915050565b5f336001600160a01b038616811480159061029657506001600160a01b038087165f9081526001602090815260408083209385168352929052205460ff16155b156102a7576102a7868286866104a5565b6102b3868686866102bf565b50600195945050505050565b6001600160a01b0384166102ed576040516301486a4160e71b81525f60048201526024015b60405180910390fd5b6001600160a01b03831661031657604051630b8bbd6160e41b81525f60048201526024016102e4565b61032284848484610555565b50505050565b6001600160a01b0384166103515760405163198ecd5360e31b81525f60048201526024016102e4565b6001600160a01b03831661037a57604051636f65f46560e01b81525f60048201526024016102e4565b6001600160a01b038481165f8181526002602090815260408083209488168084529482528083208784528252918290208590559051848152859392917fb3fd5071835887567a0671151121894ddccc2842f1d10bedad13e0d17cace9a7910160405180910390a450505050565b6001600160a01b0383166104105760405163198ecd5360e31b81525f60048201526024016102e4565b6001600160a01b03821661043957604051636f65f46560e01b81525f60048201526024016102e4565b6001600160a01b038381165f81815260016020908152604080832094871680845294825291829020805460ff191686151590811790915591519182527fceb576d9f15e4e200fdb5096d64d5dfd667e16def20c1eefd14256d8e3faa267910160405180910390a3505050565b6001600160a01b038481165f9081526002602090815260408083209387168352928152828220858352905220545f1981101561054e578181101561051c57604051632c51fead60e11b81526001600160a01b03851660048201526024810182905260448101839052606481018490526084016102e4565b6001600160a01b038086165f908152600260209081526040808320938816835292815282822086835290522082820390555b5050505050565b610561848484846105ba565b6001600160a01b038416610592575f828152600360205260408120805483929061058c908490610887565b90915550505b6001600160a01b038316610322575f8281526003602052604090208054829003905550505050565b336001600160a01b03851615610653576001600160a01b0385165f908152602081815260408083208684529091529020548281101561062c576040516302c6d3fb60e61b81526001600160a01b03871660048201526024810182905260448101849052606481018590526084016102e4565b6001600160a01b0386165f9081526020818152604080832087845290915290209083900390555b6001600160a01b03841615610698576001600160a01b0384165f9081526020818152604080832086845290915281208054849290610692908490610887565b90915550505b604080516001600160a01b03838116825260208201859052859281881692918916917f1b3d7edb2e9c0b0e7c525b20aaaef0f5940d2ed71663c7d39266ecafac728859910160405180910390a45050505050565b80356001600160a01b0381168114610702575f5ffd5b919050565b5f5f60408385031215610718575f5ffd5b610721836106ec565b946020939093013593505050565b5f6020828403121561073f575f5ffd5b81356001600160e01b031981168114610756575f5ffd5b9392505050565b5f5f5f6060848603121561076f575f5ffd5b610778846106ec565b95602085013595506040909401359392505050565b5f5f6040838503121561079e575f5ffd5b6107a7836106ec565b9150602083013580151581146107bb575f5ffd5b809150509250929050565b5f5f5f606084860312156107d8575f5ffd5b6107e1846106ec565b92506107ef602085016106ec565b929592945050506040919091013590565b5f5f60408385031215610811575f5ffd5b61081a836106ec565b9150610828602084016106ec565b90509250929050565b5f60208284031215610841575f5ffd5b5035919050565b5f5f5f5f6080858703121561085b575f5ffd5b610864856106ec565b9350610872602086016106ec565b93969395505050506040820135916060013590565b808201808211156101e357634e487b7160e01b5f52601160045260245ffdfea2646970667358221220499fa08f925af6ff8269e72361d5a67580c571a6208d3335790bab5a7b00837d64736f6c634300081b0033", + "bytecode": "0x6080604052348015600e575f5ffd5b506109008061001c5f395ff3fe608060405234801561000f575f5ffd5b506004361061008f575f3560e01c8063558a729711610063578063558a729714610102578063598af9e714610115578063b6363cf214610154578063bd85b0391461018f578063fe99049a146101ae575f5ffd5b8062fdd58e1461009357806301ffc9a7146100b9578063095bcdb6146100dc578063426a8493146100ef575b5f5ffd5b6100a66100a136600461072b565b6101c1565b6040519081526020015b60405180910390f35b6100cc6100c7366004610753565b6101e9565b60405190151581526020016100b0565b6100cc6100ea366004610781565b61020d565b6100cc6100fd366004610781565b610224565b6100cc6101103660046107b1565b610231565b6100a66101233660046107ea565b6001600160a01b039283165f9081526002602090815260408083209490951682529283528381209181529152205490565b6100cc610162366004610824565b6001600160a01b039182165f90815260016020908152604080832093909416825291909152205460ff1690565b6100a661019d366004610855565b5f9081526003602052604090205490565b6100cc6101bc36600461086c565b610246565b6001600160a01b0382165f908152602081815260408083208484529091529020545b92915050565b5f6001600160e01b0319821663bd85b03960e01b14806101e357506101e3826102af565b5f61021a338585856102e3565b5060019392505050565b5f61021a3385858561034c565b5f61023d33848461040b565b50600192915050565b5f336001600160a01b038616811480159061028657506001600160a01b038087165f9081526001602090815260408083209385168352929052205460ff16155b1561029757610297868286866104c9565b6102a3868686866102e3565b50600195945050505050565b5f6001600160e01b03198216630f632fb360e01b14806101e357506301ffc9a760e01b6001600160e01b03198316146101e3565b6001600160a01b038416610311576040516301486a4160e71b81525f60048201526024015b60405180910390fd5b6001600160a01b03831661033a57604051630b8bbd6160e41b81525f6004820152602401610308565b61034684848484610579565b50505050565b6001600160a01b0384166103755760405163198ecd5360e31b81525f6004820152602401610308565b6001600160a01b03831661039e57604051636f65f46560e01b81525f6004820152602401610308565b6001600160a01b038481165f8181526002602090815260408083209488168084529482528083208784528252918290208590559051848152859392917fb3fd5071835887567a0671151121894ddccc2842f1d10bedad13e0d17cace9a7910160405180910390a450505050565b6001600160a01b0383166104345760405163198ecd5360e31b81525f6004820152602401610308565b6001600160a01b03821661045d57604051636f65f46560e01b81525f6004820152602401610308565b6001600160a01b038381165f81815260016020908152604080832094871680845294825291829020805460ff191686151590811790915591519182527fceb576d9f15e4e200fdb5096d64d5dfd667e16def20c1eefd14256d8e3faa267910160405180910390a3505050565b6001600160a01b038481165f9081526002602090815260408083209387168352928152828220858352905220545f19811015610572578181101561054057604051632c51fead60e11b81526001600160a01b0385166004820152602481018290526044810183905260648101849052608401610308565b6001600160a01b038086165f908152600260209081526040808320938816835292815282822086835290522082820390555b5050505050565b610585848484846105de565b6001600160a01b0384166105b6575f82815260036020526040812080548392906105b09084906108ab565b90915550505b6001600160a01b038316610346575f8281526003602052604090208054829003905550505050565b336001600160a01b03851615610677576001600160a01b0385165f9081526020818152604080832086845290915290205482811015610650576040516302c6d3fb60e61b81526001600160a01b0387166004820152602481018290526044810184905260648101859052608401610308565b6001600160a01b0386165f9081526020818152604080832087845290915290209083900390555b6001600160a01b038416156106bc576001600160a01b0384165f90815260208181526040808320868452909152812080548492906106b69084906108ab565b90915550505b604080516001600160a01b03838116825260208201859052859281881692918916917f1b3d7edb2e9c0b0e7c525b20aaaef0f5940d2ed71663c7d39266ecafac728859910160405180910390a45050505050565b80356001600160a01b0381168114610726575f5ffd5b919050565b5f5f6040838503121561073c575f5ffd5b61074583610710565b946020939093013593505050565b5f60208284031215610763575f5ffd5b81356001600160e01b03198116811461077a575f5ffd5b9392505050565b5f5f5f60608486031215610793575f5ffd5b61079c84610710565b95602085013595506040909401359392505050565b5f5f604083850312156107c2575f5ffd5b6107cb83610710565b9150602083013580151581146107df575f5ffd5b809150509250929050565b5f5f5f606084860312156107fc575f5ffd5b61080584610710565b925061081360208501610710565b929592945050506040919091013590565b5f5f60408385031215610835575f5ffd5b61083e83610710565b915061084c60208401610710565b90509250929050565b5f60208284031215610865575f5ffd5b5035919050565b5f5f5f5f6080858703121561087f575f5ffd5b61088885610710565b935061089660208601610710565b93969395505050506040820135916060013590565b808201808211156101e357634e487b7160e01b5f52601160045260245ffdfea2646970667358221220ba368f0810a163f0638dc5105d47b495ada4bc1e14079a65c70fe7a67361d16464736f6c63430008230033", + "deployedBytecode": "0x608060405234801561000f575f5ffd5b506004361061008f575f3560e01c8063558a729711610063578063558a729714610102578063598af9e714610115578063b6363cf214610154578063bd85b0391461018f578063fe99049a146101ae575f5ffd5b8062fdd58e1461009357806301ffc9a7146100b9578063095bcdb6146100dc578063426a8493146100ef575b5f5ffd5b6100a66100a136600461072b565b6101c1565b6040519081526020015b60405180910390f35b6100cc6100c7366004610753565b6101e9565b60405190151581526020016100b0565b6100cc6100ea366004610781565b61020d565b6100cc6100fd366004610781565b610224565b6100cc6101103660046107b1565b610231565b6100a66101233660046107ea565b6001600160a01b039283165f9081526002602090815260408083209490951682529283528381209181529152205490565b6100cc610162366004610824565b6001600160a01b039182165f90815260016020908152604080832093909416825291909152205460ff1690565b6100a661019d366004610855565b5f9081526003602052604090205490565b6100cc6101bc36600461086c565b610246565b6001600160a01b0382165f908152602081815260408083208484529091529020545b92915050565b5f6001600160e01b0319821663bd85b03960e01b14806101e357506101e3826102af565b5f61021a338585856102e3565b5060019392505050565b5f61021a3385858561034c565b5f61023d33848461040b565b50600192915050565b5f336001600160a01b038616811480159061028657506001600160a01b038087165f9081526001602090815260408083209385168352929052205460ff16155b1561029757610297868286866104c9565b6102a3868686866102e3565b50600195945050505050565b5f6001600160e01b03198216630f632fb360e01b14806101e357506301ffc9a760e01b6001600160e01b03198316146101e3565b6001600160a01b038416610311576040516301486a4160e71b81525f60048201526024015b60405180910390fd5b6001600160a01b03831661033a57604051630b8bbd6160e41b81525f6004820152602401610308565b61034684848484610579565b50505050565b6001600160a01b0384166103755760405163198ecd5360e31b81525f6004820152602401610308565b6001600160a01b03831661039e57604051636f65f46560e01b81525f6004820152602401610308565b6001600160a01b038481165f8181526002602090815260408083209488168084529482528083208784528252918290208590559051848152859392917fb3fd5071835887567a0671151121894ddccc2842f1d10bedad13e0d17cace9a7910160405180910390a450505050565b6001600160a01b0383166104345760405163198ecd5360e31b81525f6004820152602401610308565b6001600160a01b03821661045d57604051636f65f46560e01b81525f6004820152602401610308565b6001600160a01b038381165f81815260016020908152604080832094871680845294825291829020805460ff191686151590811790915591519182527fceb576d9f15e4e200fdb5096d64d5dfd667e16def20c1eefd14256d8e3faa267910160405180910390a3505050565b6001600160a01b038481165f9081526002602090815260408083209387168352928152828220858352905220545f19811015610572578181101561054057604051632c51fead60e11b81526001600160a01b0385166004820152602481018290526044810183905260648101849052608401610308565b6001600160a01b038086165f908152600260209081526040808320938816835292815282822086835290522082820390555b5050505050565b610585848484846105de565b6001600160a01b0384166105b6575f82815260036020526040812080548392906105b09084906108ab565b90915550505b6001600160a01b038316610346575f8281526003602052604090208054829003905550505050565b336001600160a01b03851615610677576001600160a01b0385165f9081526020818152604080832086845290915290205482811015610650576040516302c6d3fb60e61b81526001600160a01b0387166004820152602481018290526044810184905260648101859052608401610308565b6001600160a01b0386165f9081526020818152604080832087845290915290209083900390555b6001600160a01b038416156106bc576001600160a01b0384165f90815260208181526040808320868452909152812080548492906106b69084906108ab565b90915550505b604080516001600160a01b03838116825260208201859052859281881692918916917f1b3d7edb2e9c0b0e7c525b20aaaef0f5940d2ed71663c7d39266ecafac728859910160405180910390a45050505050565b80356001600160a01b0381168114610726575f5ffd5b919050565b5f5f6040838503121561073c575f5ffd5b61074583610710565b946020939093013593505050565b5f60208284031215610763575f5ffd5b81356001600160e01b03198116811461077a575f5ffd5b9392505050565b5f5f5f60608486031215610793575f5ffd5b61079c84610710565b95602085013595506040909401359392505050565b5f5f604083850312156107c2575f5ffd5b6107cb83610710565b9150602083013580151581146107df575f5ffd5b809150509250929050565b5f5f5f606084860312156107fc575f5ffd5b61080584610710565b925061081360208501610710565b929592945050506040919091013590565b5f5f60408385031215610835575f5ffd5b61083e83610710565b915061084c60208401610710565b90509250929050565b5f60208284031215610865575f5ffd5b5035919050565b5f5f5f5f6080858703121561087f575f5ffd5b61088885610710565b935061089660208601610710565b93969395505050506040820135916060013590565b808201808211156101e357634e487b7160e01b5f52601160045260245ffdfea2646970667358221220ba368f0810a163f0638dc5105d47b495ada4bc1e14079a65c70fe7a67361d16464736f6c63430008230033", "linkReferences": {}, "deployedLinkReferences": {} } diff --git a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/ERC721.json b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/ERC721.json similarity index 100% rename from dependencies/@openzeppelin-contracts-5.5.0/build/contracts/ERC721.json rename to dependencies/@openzeppelin-contracts-5.7.0/build/contracts/ERC721.json diff --git a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/ERC721Burnable.json b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/ERC721Burnable.json similarity index 100% rename from dependencies/@openzeppelin-contracts-5.5.0/build/contracts/ERC721Burnable.json rename to dependencies/@openzeppelin-contracts-5.7.0/build/contracts/ERC721Burnable.json diff --git a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/ERC721Consecutive.json b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/ERC721Consecutive.json similarity index 100% rename from dependencies/@openzeppelin-contracts-5.5.0/build/contracts/ERC721Consecutive.json rename to dependencies/@openzeppelin-contracts-5.7.0/build/contracts/ERC721Consecutive.json diff --git a/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/ERC721Crosschain.json b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/ERC721Crosschain.json new file mode 100644 index 0000000..f53f6a7 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/ERC721Crosschain.json @@ -0,0 +1,671 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "ERC721Crosschain", + "sourceName": "contracts/token/ERC721/extensions/ERC721Crosschain.sol", + "abi": [ + { + "inputs": [], + "name": "CrosschainNonFungibleEmptyAddress", + "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": "gateway", + "type": "address" + }, + { + "internalType": "bytes", + "name": "sender", + "type": "bytes" + } + ], + "name": "ERC7786RecipientUnauthorizedGateway", + "type": "error" + }, + { + "inputs": [], + "name": "InteroperableAddressEmptyReferenceAndAddress", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "name": "InteroperableAddressParsingError", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "chain", + "type": "bytes" + } + ], + "name": "LinkAlreadyRegistered", + "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": "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": "bytes32", + "name": "receiveId", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "from", + "type": "bytes" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "CrosschainNonFungibleTransferReceived", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "sendId", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "to", + "type": "bytes" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "CrosschainNonFungibleTransferSent", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "gateway", + "type": "address" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "counterpart", + "type": "bytes" + } + ], + "name": "LinkRegistered", + "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": "from", + "type": "address" + }, + { + "internalType": "bytes", + "name": "to", + "type": "bytes" + }, + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "crosschainTransferFrom", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "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": "bytes", + "name": "chain", + "type": "bytes" + } + ], + "name": "getLink", + "outputs": [ + { + "internalType": "address", + "name": "gateway", + "type": "address" + }, + { + "internalType": "bytes", + "name": "counterpart", + "type": "bytes" + } + ], + "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": "bytes32", + "name": "receiveId", + "type": "bytes32" + }, + { + "internalType": "bytes", + "name": "sender", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "payload", + "type": "bytes" + } + ], + "name": "receiveMessage", + "outputs": [ + { + "internalType": "bytes4", + "name": "", + "type": "bytes4" + } + ], + "stateMutability": "payable", + "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.5.0/build/contracts/ERC721Enumerable.json b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/ERC721Enumerable.json similarity index 100% rename from dependencies/@openzeppelin-contracts-5.5.0/build/contracts/ERC721Enumerable.json rename to dependencies/@openzeppelin-contracts-5.7.0/build/contracts/ERC721Enumerable.json diff --git a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/ERC721Holder.json b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/ERC721Holder.json similarity index 100% rename from dependencies/@openzeppelin-contracts-5.5.0/build/contracts/ERC721Holder.json rename to dependencies/@openzeppelin-contracts-5.7.0/build/contracts/ERC721Holder.json diff --git a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/ERC721Pausable.json b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/ERC721Pausable.json similarity index 100% rename from dependencies/@openzeppelin-contracts-5.5.0/build/contracts/ERC721Pausable.json rename to dependencies/@openzeppelin-contracts-5.7.0/build/contracts/ERC721Pausable.json diff --git a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/ERC721Royalty.json b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/ERC721Royalty.json similarity index 100% rename from dependencies/@openzeppelin-contracts-5.5.0/build/contracts/ERC721Royalty.json rename to dependencies/@openzeppelin-contracts-5.7.0/build/contracts/ERC721Royalty.json diff --git a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/ERC721URIStorage.json b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/ERC721URIStorage.json similarity index 100% rename from dependencies/@openzeppelin-contracts-5.5.0/build/contracts/ERC721URIStorage.json rename to dependencies/@openzeppelin-contracts-5.7.0/build/contracts/ERC721URIStorage.json diff --git a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/ERC721Utils.json b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/ERC721Utils.json similarity index 67% rename from dependencies/@openzeppelin-contracts-5.5.0/build/contracts/ERC721Utils.json rename to dependencies/@openzeppelin-contracts-5.7.0/build/contracts/ERC721Utils.json index 83dd28b..60ce3c8 100644 --- a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/ERC721Utils.json +++ b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/ERC721Utils.json @@ -3,8 +3,8 @@ "contractName": "ERC721Utils", "sourceName": "contracts/token/ERC721/utils/ERC721Utils.sol", "abi": [], - "bytecode": "0x60556032600b8282823980515f1a607314602657634e487b7160e01b5f525f60045260245ffd5b305f52607381538281f3fe730000000000000000000000000000000000000000301460806040525f5ffdfea26469706673582212201557df3c69dfb02f69d5afb579a0c4bbeca20fd748a30b6ae0ed5a09368ed9d364736f6c634300081b0033", - "deployedBytecode": "0x730000000000000000000000000000000000000000301460806040525f5ffdfea26469706673582212201557df3c69dfb02f69d5afb579a0c4bbeca20fd748a30b6ae0ed5a09368ed9d364736f6c634300081b0033", + "bytecode": "0x60556032600b8282823980515f1a607314602657634e487b7160e01b5f525f60045260245ffd5b305f52607381538281f3fe730000000000000000000000000000000000000000301460806040525f5ffdfea2646970667358221220112c2cde058bec6460c80a3663791caf2e82125aad07db554b0ce7fdb39be72464736f6c63430008230033", + "deployedBytecode": "0x730000000000000000000000000000000000000000301460806040525f5ffdfea2646970667358221220112c2cde058bec6460c80a3663791caf2e82125aad07db554b0ce7fdb39be72464736f6c63430008230033", "linkReferences": {}, "deployedLinkReferences": {} } diff --git a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/ERC721Votes.json b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/ERC721Votes.json similarity index 100% rename from dependencies/@openzeppelin-contracts-5.5.0/build/contracts/ERC721Votes.json rename to dependencies/@openzeppelin-contracts-5.7.0/build/contracts/ERC721Votes.json diff --git a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/ERC721Wrapper.json b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/ERC721Wrapper.json similarity index 100% rename from dependencies/@openzeppelin-contracts-5.5.0/build/contracts/ERC721Wrapper.json rename to dependencies/@openzeppelin-contracts-5.7.0/build/contracts/ERC721Wrapper.json diff --git a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/ERC7579Utils.json b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/ERC7579Utils.json similarity index 92% rename from dependencies/@openzeppelin-contracts-5.5.0/build/contracts/ERC7579Utils.json rename to dependencies/@openzeppelin-contracts-5.7.0/build/contracts/ERC7579Utils.json index d5d061a..c41dc92 100644 --- a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/ERC7579Utils.json +++ b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/ERC7579Utils.json @@ -109,8 +109,8 @@ "type": "event" } ], - "bytecode": "0x60556032600b8282823980515f1a607314602657634e487b7160e01b5f525f60045260245ffd5b305f52607381538281f3fe730000000000000000000000000000000000000000301460806040525f5ffdfea2646970667358221220b6489c625ec149879b291d8cf13e83dc09795030566d8856e7f701f773dc879264736f6c634300081b0033", - "deployedBytecode": "0x730000000000000000000000000000000000000000301460806040525f5ffdfea2646970667358221220b6489c625ec149879b291d8cf13e83dc09795030566d8856e7f701f773dc879264736f6c634300081b0033", + "bytecode": "0x60556032600b8282823980515f1a607314602657634e487b7160e01b5f525f60045260245ffd5b305f52607381538281f3fe730000000000000000000000000000000000000000301460806040525f5ffdfea2646970667358221220cdaae177293ef0231e18842a4705fc2a5bd7de8ad68b0fbb7a1b42916c773dc764736f6c63430008230033", + "deployedBytecode": "0x730000000000000000000000000000000000000000301460806040525f5ffdfea2646970667358221220cdaae177293ef0231e18842a4705fc2a5bd7de8ad68b0fbb7a1b42916c773dc764736f6c63430008230033", "linkReferences": {}, "deployedLinkReferences": {} } diff --git a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/ERC7739.json b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/ERC7739.json similarity index 100% rename from dependencies/@openzeppelin-contracts-5.5.0/build/contracts/ERC7739.json rename to dependencies/@openzeppelin-contracts-5.7.0/build/contracts/ERC7739.json diff --git a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/ERC7739Utils.json b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/ERC7739Utils.json similarity index 67% rename from dependencies/@openzeppelin-contracts-5.5.0/build/contracts/ERC7739Utils.json rename to dependencies/@openzeppelin-contracts-5.7.0/build/contracts/ERC7739Utils.json index 373f593..58c23b9 100644 --- a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/ERC7739Utils.json +++ b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/ERC7739Utils.json @@ -3,8 +3,8 @@ "contractName": "ERC7739Utils", "sourceName": "contracts/utils/cryptography/draft-ERC7739Utils.sol", "abi": [], - "bytecode": "0x60556032600b8282823980515f1a607314602657634e487b7160e01b5f525f60045260245ffd5b305f52607381538281f3fe730000000000000000000000000000000000000000301460806040525f5ffdfea26469706673582212205e7f0c6f2b8e1274cb8a4c7e3611fa286cf702d38e087cf53d012ec1fe1d60f164736f6c634300081b0033", - "deployedBytecode": "0x730000000000000000000000000000000000000000301460806040525f5ffdfea26469706673582212205e7f0c6f2b8e1274cb8a4c7e3611fa286cf702d38e087cf53d012ec1fe1d60f164736f6c634300081b0033", + "bytecode": "0x60556032600b8282823980515f1a607314602657634e487b7160e01b5f525f60045260245ffd5b305f52607381538281f3fe730000000000000000000000000000000000000000301460806040525f5ffdfea2646970667358221220828516e478bc72b0bf9182804f1c1a383c93cdcb05f7a5e2a60cc2ed0b216b7c64736f6c63430008230033", + "deployedBytecode": "0x730000000000000000000000000000000000000000301460806040525f5ffdfea2646970667358221220828516e478bc72b0bf9182804f1c1a383c93cdcb05f7a5e2a60cc2ed0b216b7c64736f6c63430008230033", "linkReferences": {}, "deployedLinkReferences": {} } diff --git a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/ERC7786Recipient.json b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/ERC7786Recipient.json similarity index 77% rename from dependencies/@openzeppelin-contracts-5.5.0/build/contracts/ERC7786Recipient.json rename to dependencies/@openzeppelin-contracts-5.7.0/build/contracts/ERC7786Recipient.json index a861639..47b05cb 100644 --- a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/ERC7786Recipient.json +++ b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/ERC7786Recipient.json @@ -3,22 +3,6 @@ "contractName": "ERC7786Recipient", "sourceName": "contracts/crosschain/ERC7786Recipient.sol", "abi": [ - { - "inputs": [ - { - "internalType": "address", - "name": "gateway", - "type": "address" - }, - { - "internalType": "bytes32", - "name": "receiveId", - "type": "bytes32" - } - ], - "name": "ERC7786RecipientMessageAlreadyProcessed", - "type": "error" - }, { "inputs": [ { diff --git a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/ERC7821.json b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/ERC7821.json similarity index 100% rename from dependencies/@openzeppelin-contracts-5.5.0/build/contracts/ERC7821.json rename to dependencies/@openzeppelin-contracts-5.7.0/build/contracts/ERC7821.json diff --git a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/ERC7913P256Verifier.json b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/ERC7913P256Verifier.json similarity index 98% rename from dependencies/@openzeppelin-contracts-5.5.0/build/contracts/ERC7913P256Verifier.json rename to dependencies/@openzeppelin-contracts-5.7.0/build/contracts/ERC7913P256Verifier.json index ee24c43..7c4defb 100644 --- a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/ERC7913P256Verifier.json +++ b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/ERC7913P256Verifier.json @@ -33,8 +33,8 @@ "type": "function" } ], - "bytecode": "0x6080604052348015600e575f5ffd5b50610c0e8061001c5f395ff3fe608060405234801561000f575f5ffd5b5060043610610029575f3560e01c8063024ad3181461002d575b5f5ffd5b61004061003b366004610ac8565b61005d565b6040516001600160e01b0319909116815260200160405180910390f35b5f60408514801561006f575060408210155b15610104575f610082602082888a610b41565b61008b91610b68565b90505f61009c60406020898b610b41565b6100a591610b68565b90505f6100b56020828789610b41565b6100be91610b68565b90505f6100cf60406020888a610b41565b6100d891610b68565b90506100e78883838787610118565b156100ff575062495a6360e31b935061010f92505050565b505050505b506001600160e01b03195b95945050505050565b5f5f5f6101288888888888610151565b91509150806101435761013e888888888861022c565b610145565b815b98975050505050505050565b5f5f61015d86866102dc565b1580610170575061016e8484610338565b155b1561018057505f90506001610222565b61018d878787878761039c565b1561019d57506001905080610222565b61020c7fbb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023600560017fa71af64de5126a4a4e02b7922d66ce9415ce88a4c9d25514d91082c8725ac9577f5d47723c8fbe580bb369fec9c2665d8e30a435b9932645482e7c9f11e872296b61039c565b1561021c57505f90506001610222565b505f9050805b9550959350505050565b5f61023785856102dc565b158061024a57506102488383610338565b155b1561025657505f61010f565b5f61026184846103dc565b90505f61027b865f516020610bb95f395f51905f526105cf565b90505f5f516020610bb95f395f51905f52828a0990505f5f516020610bb95f395f51905f52838a0990505f6102b18584846105de565b509050896102cc5f516020610bb95f395f51905f5283610b85565b149b9a5050505050505050505050565b5f82158015906102f857505f516020610bb95f395f51905f5283105b801561030357508115155b801561032f57507f7fffffff800000007fffffffffffffffde737d56d38bcf4279dce5617e3192a88211155b90505b92915050565b5f600160601b63ffffffff60c01b031980838409817f5ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2604b8387856003600160601b0363ffffffff60c01b0319878b8c0908090894821191909310169190921416919050565b5f6040518681528560208201528460408201528360608201528260808201525f5f5260205f60a0836101005afa6103cf57fe5b50505f5195945050505050565b6103e4610a3c565b60405180606001604052805f81526020015f81526020015f815250815f6010811061041157610411610ba4565b6020020181905250604051806060016040528084815260200183815260200160018152508160016010811061044857610448610ba4565b602002018190525060405180606001604052807f6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c29681526020017f4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f581526020016001815250816004601081106104bf576104bf610ba4565b60200201526104d58160015b6020020151610702565b60408201526104e58160046104cb565b6101008201526020810151610502908260025b602002015161075e565b606082015261051b8160015b60200201518260046104f8565b60a082015261052b81600261050e565b60c082015261053b81600361050e565b60e08201526105548160015b60200201518260086104f8565b610120820152610565816002610547565b610140820152610576816003610547565b610160820152610587816004610547565b6101808201526105a18160015b602002015182600c6104f8565b6101a08201526105b2816002610594565b6101c08201526105c3816003610594565b6101e082015292915050565b5f61032f8360028403846107bc565b5f80808080805b60808110156106e6578115610619576105ff8484846107dd565b919550935091506106118484846107dd565b919550935091505b600c60fc89901c1660fe88901c1789816010811061063957610639610ba4565b602002015160400151156106d257825f036106a85789816010811061066057610660610ba4565b6020020151518a826010811061067857610678610ba4565b6020020151602001518b836010811061069357610693610ba4565b602002015160400151919650945092506106d2565b6106ca8a82601081106106bd576106bd610ba4565b6020020151868686610860565b919650945092505b50600297881b979690961b956001016105e5565b506106f283838361098c565b945094505050505b935093915050565b61072360405180606001604052805f81526020015f81526020015f81525090565b5f5f5f61073c855f0151866020015187604001516107dd565b6040805160608101825293845260208401929092529082015295945050505050565b61077f60405180606001604052805f81526020015f81526020015f81525090565b5f5f5f61079986865f015187602001518860400151610860565b604080516060810182529384526020840192909252908201529695505050505050565b5f5f5f6107ca8686866109d9565b915091508161010f5761010f6012610a2b565b5f5f5f600160601b63ffffffff60c01b031980868709818687098283848384096003600160601b0363ffffffff60c01b03190984858c8d096003090890508283838b09600409838482600209850385848509089650838485858609600809850385868a880385088509089550505050808186880960020991505093509350939050565b5f5f5f600160601b63ffffffff60c01b0319604088015181818209828388858a8b090960208c0151098381850385868686098c090884858a8b098d51098581870387868f09089350811584151680156108c057600181146109065761097b565b868586098788898386096002098903898a848a098b038b88890908089a5087888983890987098903898a8e8c038c8689090887090899505086878c88098609975061097b565b8c8c8c898283098a8283098b8c8d8384096003600160601b0363ffffffff60c01b0319098d8e8889096003090890508b8c83870960040994508b8c866002098d038d838409089e508b8c8384096008098c0391508b8f8d03860894508b828d878409089d505050898a8284096002099a505050505b505050505050509450945094915050565b5f5f825f0361099f57505f9050806106fa565b600160601b63ffffffff60c01b03195f6109b985836105cf565b905081818209828189099450828383830988099350505050935093915050565b5f5f825f036109ec57505f9050806106fa565b60405160208152602080820152602060408201528560608201528460808201528360a082015260205f60c08360055afa9250505f519050935093915050565b634e487b715f52806020526024601cfd5b6040518061020001604052806010905b610a6d60405180606001604052805f81526020015f81526020015f81525090565b815260200190600190039081610a4c5790505090565b5f5f83601f840112610a93575f5ffd5b50813567ffffffffffffffff811115610aaa575f5ffd5b602083019150836020828501011115610ac1575f5ffd5b9250929050565b5f5f5f5f5f60608688031215610adc575f5ffd5b853567ffffffffffffffff811115610af2575f5ffd5b610afe88828901610a83565b90965094505060208601359250604086013567ffffffffffffffff811115610b24575f5ffd5b610b3088828901610a83565b969995985093965092949392505050565b5f5f85851115610b4f575f5ffd5b83861115610b5b575f5ffd5b5050820193919092039150565b80356020831015610332575f19602084900360031b1b1692915050565b5f82610b9f57634e487b7160e01b5f52601260045260245ffd5b500690565b634e487b7160e01b5f52603260045260245ffdfeffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551a264697066735822122089715cc56ff1d5e825d810d4836e76401e3772c5467c5c47fe27e2e2b6a72e1e64736f6c634300081b0033", - "deployedBytecode": "0x608060405234801561000f575f5ffd5b5060043610610029575f3560e01c8063024ad3181461002d575b5f5ffd5b61004061003b366004610ac8565b61005d565b6040516001600160e01b0319909116815260200160405180910390f35b5f60408514801561006f575060408210155b15610104575f610082602082888a610b41565b61008b91610b68565b90505f61009c60406020898b610b41565b6100a591610b68565b90505f6100b56020828789610b41565b6100be91610b68565b90505f6100cf60406020888a610b41565b6100d891610b68565b90506100e78883838787610118565b156100ff575062495a6360e31b935061010f92505050565b505050505b506001600160e01b03195b95945050505050565b5f5f5f6101288888888888610151565b91509150806101435761013e888888888861022c565b610145565b815b98975050505050505050565b5f5f61015d86866102dc565b1580610170575061016e8484610338565b155b1561018057505f90506001610222565b61018d878787878761039c565b1561019d57506001905080610222565b61020c7fbb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023600560017fa71af64de5126a4a4e02b7922d66ce9415ce88a4c9d25514d91082c8725ac9577f5d47723c8fbe580bb369fec9c2665d8e30a435b9932645482e7c9f11e872296b61039c565b1561021c57505f90506001610222565b505f9050805b9550959350505050565b5f61023785856102dc565b158061024a57506102488383610338565b155b1561025657505f61010f565b5f61026184846103dc565b90505f61027b865f516020610bb95f395f51905f526105cf565b90505f5f516020610bb95f395f51905f52828a0990505f5f516020610bb95f395f51905f52838a0990505f6102b18584846105de565b509050896102cc5f516020610bb95f395f51905f5283610b85565b149b9a5050505050505050505050565b5f82158015906102f857505f516020610bb95f395f51905f5283105b801561030357508115155b801561032f57507f7fffffff800000007fffffffffffffffde737d56d38bcf4279dce5617e3192a88211155b90505b92915050565b5f600160601b63ffffffff60c01b031980838409817f5ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2604b8387856003600160601b0363ffffffff60c01b0319878b8c0908090894821191909310169190921416919050565b5f6040518681528560208201528460408201528360608201528260808201525f5f5260205f60a0836101005afa6103cf57fe5b50505f5195945050505050565b6103e4610a3c565b60405180606001604052805f81526020015f81526020015f815250815f6010811061041157610411610ba4565b6020020181905250604051806060016040528084815260200183815260200160018152508160016010811061044857610448610ba4565b602002018190525060405180606001604052807f6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c29681526020017f4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f581526020016001815250816004601081106104bf576104bf610ba4565b60200201526104d58160015b6020020151610702565b60408201526104e58160046104cb565b6101008201526020810151610502908260025b602002015161075e565b606082015261051b8160015b60200201518260046104f8565b60a082015261052b81600261050e565b60c082015261053b81600361050e565b60e08201526105548160015b60200201518260086104f8565b610120820152610565816002610547565b610140820152610576816003610547565b610160820152610587816004610547565b6101808201526105a18160015b602002015182600c6104f8565b6101a08201526105b2816002610594565b6101c08201526105c3816003610594565b6101e082015292915050565b5f61032f8360028403846107bc565b5f80808080805b60808110156106e6578115610619576105ff8484846107dd565b919550935091506106118484846107dd565b919550935091505b600c60fc89901c1660fe88901c1789816010811061063957610639610ba4565b602002015160400151156106d257825f036106a85789816010811061066057610660610ba4565b6020020151518a826010811061067857610678610ba4565b6020020151602001518b836010811061069357610693610ba4565b602002015160400151919650945092506106d2565b6106ca8a82601081106106bd576106bd610ba4565b6020020151868686610860565b919650945092505b50600297881b979690961b956001016105e5565b506106f283838361098c565b945094505050505b935093915050565b61072360405180606001604052805f81526020015f81526020015f81525090565b5f5f5f61073c855f0151866020015187604001516107dd565b6040805160608101825293845260208401929092529082015295945050505050565b61077f60405180606001604052805f81526020015f81526020015f81525090565b5f5f5f61079986865f015187602001518860400151610860565b604080516060810182529384526020840192909252908201529695505050505050565b5f5f5f6107ca8686866109d9565b915091508161010f5761010f6012610a2b565b5f5f5f600160601b63ffffffff60c01b031980868709818687098283848384096003600160601b0363ffffffff60c01b03190984858c8d096003090890508283838b09600409838482600209850385848509089650838485858609600809850385868a880385088509089550505050808186880960020991505093509350939050565b5f5f5f600160601b63ffffffff60c01b0319604088015181818209828388858a8b090960208c0151098381850385868686098c090884858a8b098d51098581870387868f09089350811584151680156108c057600181146109065761097b565b868586098788898386096002098903898a848a098b038b88890908089a5087888983890987098903898a8e8c038c8689090887090899505086878c88098609975061097b565b8c8c8c898283098a8283098b8c8d8384096003600160601b0363ffffffff60c01b0319098d8e8889096003090890508b8c83870960040994508b8c866002098d038d838409089e508b8c8384096008098c0391508b8f8d03860894508b828d878409089d505050898a8284096002099a505050505b505050505050509450945094915050565b5f5f825f0361099f57505f9050806106fa565b600160601b63ffffffff60c01b03195f6109b985836105cf565b905081818209828189099450828383830988099350505050935093915050565b5f5f825f036109ec57505f9050806106fa565b60405160208152602080820152602060408201528560608201528460808201528360a082015260205f60c08360055afa9250505f519050935093915050565b634e487b715f52806020526024601cfd5b6040518061020001604052806010905b610a6d60405180606001604052805f81526020015f81526020015f81525090565b815260200190600190039081610a4c5790505090565b5f5f83601f840112610a93575f5ffd5b50813567ffffffffffffffff811115610aaa575f5ffd5b602083019150836020828501011115610ac1575f5ffd5b9250929050565b5f5f5f5f5f60608688031215610adc575f5ffd5b853567ffffffffffffffff811115610af2575f5ffd5b610afe88828901610a83565b90965094505060208601359250604086013567ffffffffffffffff811115610b24575f5ffd5b610b3088828901610a83565b969995985093965092949392505050565b5f5f85851115610b4f575f5ffd5b83861115610b5b575f5ffd5b5050820193919092039150565b80356020831015610332575f19602084900360031b1b1692915050565b5f82610b9f57634e487b7160e01b5f52601260045260245ffd5b500690565b634e487b7160e01b5f52603260045260245ffdfeffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551a264697066735822122089715cc56ff1d5e825d810d4836e76401e3772c5467c5c47fe27e2e2b6a72e1e64736f6c634300081b0033", + "bytecode": "0x6080604052348015600e575f5ffd5b50610c0e8061001c5f395ff3fe608060405234801561000f575f5ffd5b5060043610610029575f3560e01c8063024ad3181461002d575b5f5ffd5b61004061003b366004610ac8565b61005d565b6040516001600160e01b0319909116815260200160405180910390f35b5f60408514801561006f575060408210155b15610104575f610082602082888a610b41565b61008b91610b68565b90505f61009c60406020898b610b41565b6100a591610b68565b90505f6100b56020828789610b41565b6100be91610b68565b90505f6100cf60406020888a610b41565b6100d891610b68565b90506100e78883838787610118565b156100ff575062495a6360e31b935061010f92505050565b505050505b506001600160e01b03195b95945050505050565b5f5f5f6101288888888888610151565b91509150806101435761013e888888888861022c565b610145565b815b98975050505050505050565b5f5f61015d86866102dc565b1580610170575061016e8484610338565b155b1561018057505f90506001610222565b61018d878787878761039c565b1561019d57506001905080610222565b61020c7fbb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023600560017fa71af64de5126a4a4e02b7922d66ce9415ce88a4c9d25514d91082c8725ac9577f5d47723c8fbe580bb369fec9c2665d8e30a435b9932645482e7c9f11e872296b61039c565b1561021c57505f90506001610222565b505f9050805b9550959350505050565b5f61023785856102dc565b158061024a57506102488383610338565b155b1561025657505f61010f565b5f61026184846103dc565b90505f61027b865f516020610bb95f395f51905f526105cf565b90505f5f516020610bb95f395f51905f52828a0990505f5f516020610bb95f395f51905f52838a0990505f6102b18584846105de565b509050896102cc5f516020610bb95f395f51905f5283610b85565b149b9a5050505050505050505050565b5f82158015906102f857505f516020610bb95f395f51905f5283105b801561030357508115155b801561032f57507f7fffffff800000007fffffffffffffffde737d56d38bcf4279dce5617e3192a88211155b90505b92915050565b5f600160601b63ffffffff60c01b031980838409817f5ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2604b8387856003600160601b0363ffffffff60c01b0319878b8c0908090894821191909310169190921416919050565b5f6040518681528560208201528460408201528360608201528260808201525f5f5260205f60a0836101005afa6103cf57fe5b50505f5195945050505050565b6103e4610a3c565b60405180606001604052805f81526020015f81526020015f815250815f6010811061041157610411610ba4565b6020020181905250604051806060016040528084815260200183815260200160018152508160016010811061044857610448610ba4565b602002018190525060405180606001604052807f6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c29681526020017f4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f581526020016001815250816004601081106104bf576104bf610ba4565b60200201526104d58160015b6020020151610702565b60408201526104e58160046104cb565b6101008201526020810151610502908260025b602002015161075e565b606082015261051b8160015b60200201518260046104f8565b60a082015261052b81600261050e565b60c082015261053b81600361050e565b60e08201526105548160015b60200201518260086104f8565b610120820152610565816002610547565b610140820152610576816003610547565b610160820152610587816004610547565b6101808201526105a18160015b602002015182600c6104f8565b6101a08201526105b2816002610594565b6101c08201526105c3816003610594565b6101e082015292915050565b5f61032f8360028403846107bc565b5f80808080805b60808110156106e6578115610619576105ff8484846107dd565b919550935091506106118484846107dd565b919550935091505b600c60fc89901c1660fe88901c1789816010811061063957610639610ba4565b602002015160400151156106d257825f036106a85789816010811061066057610660610ba4565b6020020151518a826010811061067857610678610ba4565b6020020151602001518b836010811061069357610693610ba4565b602002015160400151919650945092506106d2565b6106ca8a82601081106106bd576106bd610ba4565b6020020151868686610860565b919650945092505b50600297881b979690961b956001016105e5565b506106f283838361098c565b945094505050505b935093915050565b61072360405180606001604052805f81526020015f81526020015f81525090565b5f5f5f61073c855f0151866020015187604001516107dd565b6040805160608101825293845260208401929092529082015295945050505050565b61077f60405180606001604052805f81526020015f81526020015f81525090565b5f5f5f61079986865f015187602001518860400151610860565b604080516060810182529384526020840192909252908201529695505050505050565b5f5f5f6107ca8686866109d9565b915091508161010f5761010f6012610a2b565b5f5f5f600160601b63ffffffff60c01b031980868709818687098283848384096003600160601b0363ffffffff60c01b03190984858c8d096003090890508283838b09600409838482600209850385848509089650838485858609600809850385868a880385088509089550505050808186880960020991505093509350939050565b5f5f5f600160601b63ffffffff60c01b0319604088015181818209828388858a8b090960208c0151098381850385868686098c090884858a8b098d51098581870387868f09089350811584151680156108c057600181146109065761097b565b868586098788898386096002098903898a848a098b038b88890908089a5087888983890987098903898a8e8c038c8689090887090899505086878c88098609975061097b565b8c8c8c898283098a8283098b8c8d8384096003600160601b0363ffffffff60c01b0319098d8e8889096003090890508b8c83870960040994508b8c866002098d038d838409089e508b8c8384096008098c0391508b8f8d03860894508b828d878409089d505050898a8284096002099a505050505b505050505050509450945094915050565b5f5f825f0361099f57505f9050806106fa565b600160601b63ffffffff60c01b03195f6109b985836105cf565b905081818209828189099450828383830988099350505050935093915050565b5f5f825f036109ec57505f9050806106fa565b60405160208152602080820152602060408201528560608201528460808201528360a082015260205f60c08360055afa9250505f519050935093915050565b634e487b715f52806020526024601cfd5b6040518061020001604052806010905b610a6d60405180606001604052805f81526020015f81526020015f81525090565b815260200190600190039081610a4c5790505090565b5f5f83601f840112610a93575f5ffd5b50813567ffffffffffffffff811115610aaa575f5ffd5b602083019150836020828501011115610ac1575f5ffd5b9250929050565b5f5f5f5f5f60608688031215610adc575f5ffd5b853567ffffffffffffffff811115610af2575f5ffd5b610afe88828901610a83565b90965094505060208601359250604086013567ffffffffffffffff811115610b24575f5ffd5b610b3088828901610a83565b969995985093965092949392505050565b5f5f85851115610b4f575f5ffd5b83861115610b5b575f5ffd5b5050820193919092039150565b80356020831015610332575f19602084900360031b1b1692915050565b5f82610b9f57634e487b7160e01b5f52601260045260245ffd5b500690565b634e487b7160e01b5f52603260045260245ffdfeffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551a2646970667358221220f0d427537440c9e5604f119660515b3697ad6d7e99d269210fcd8e06c8108d3564736f6c63430008230033", + "deployedBytecode": "0x608060405234801561000f575f5ffd5b5060043610610029575f3560e01c8063024ad3181461002d575b5f5ffd5b61004061003b366004610ac8565b61005d565b6040516001600160e01b0319909116815260200160405180910390f35b5f60408514801561006f575060408210155b15610104575f610082602082888a610b41565b61008b91610b68565b90505f61009c60406020898b610b41565b6100a591610b68565b90505f6100b56020828789610b41565b6100be91610b68565b90505f6100cf60406020888a610b41565b6100d891610b68565b90506100e78883838787610118565b156100ff575062495a6360e31b935061010f92505050565b505050505b506001600160e01b03195b95945050505050565b5f5f5f6101288888888888610151565b91509150806101435761013e888888888861022c565b610145565b815b98975050505050505050565b5f5f61015d86866102dc565b1580610170575061016e8484610338565b155b1561018057505f90506001610222565b61018d878787878761039c565b1561019d57506001905080610222565b61020c7fbb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023600560017fa71af64de5126a4a4e02b7922d66ce9415ce88a4c9d25514d91082c8725ac9577f5d47723c8fbe580bb369fec9c2665d8e30a435b9932645482e7c9f11e872296b61039c565b1561021c57505f90506001610222565b505f9050805b9550959350505050565b5f61023785856102dc565b158061024a57506102488383610338565b155b1561025657505f61010f565b5f61026184846103dc565b90505f61027b865f516020610bb95f395f51905f526105cf565b90505f5f516020610bb95f395f51905f52828a0990505f5f516020610bb95f395f51905f52838a0990505f6102b18584846105de565b509050896102cc5f516020610bb95f395f51905f5283610b85565b149b9a5050505050505050505050565b5f82158015906102f857505f516020610bb95f395f51905f5283105b801561030357508115155b801561032f57507f7fffffff800000007fffffffffffffffde737d56d38bcf4279dce5617e3192a88211155b90505b92915050565b5f600160601b63ffffffff60c01b031980838409817f5ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2604b8387856003600160601b0363ffffffff60c01b0319878b8c0908090894821191909310169190921416919050565b5f6040518681528560208201528460408201528360608201528260808201525f5f5260205f60a0836101005afa6103cf57fe5b50505f5195945050505050565b6103e4610a3c565b60405180606001604052805f81526020015f81526020015f815250815f6010811061041157610411610ba4565b6020020181905250604051806060016040528084815260200183815260200160018152508160016010811061044857610448610ba4565b602002018190525060405180606001604052807f6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c29681526020017f4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f581526020016001815250816004601081106104bf576104bf610ba4565b60200201526104d58160015b6020020151610702565b60408201526104e58160046104cb565b6101008201526020810151610502908260025b602002015161075e565b606082015261051b8160015b60200201518260046104f8565b60a082015261052b81600261050e565b60c082015261053b81600361050e565b60e08201526105548160015b60200201518260086104f8565b610120820152610565816002610547565b610140820152610576816003610547565b610160820152610587816004610547565b6101808201526105a18160015b602002015182600c6104f8565b6101a08201526105b2816002610594565b6101c08201526105c3816003610594565b6101e082015292915050565b5f61032f8360028403846107bc565b5f80808080805b60808110156106e6578115610619576105ff8484846107dd565b919550935091506106118484846107dd565b919550935091505b600c60fc89901c1660fe88901c1789816010811061063957610639610ba4565b602002015160400151156106d257825f036106a85789816010811061066057610660610ba4565b6020020151518a826010811061067857610678610ba4565b6020020151602001518b836010811061069357610693610ba4565b602002015160400151919650945092506106d2565b6106ca8a82601081106106bd576106bd610ba4565b6020020151868686610860565b919650945092505b50600297881b979690961b956001016105e5565b506106f283838361098c565b945094505050505b935093915050565b61072360405180606001604052805f81526020015f81526020015f81525090565b5f5f5f61073c855f0151866020015187604001516107dd565b6040805160608101825293845260208401929092529082015295945050505050565b61077f60405180606001604052805f81526020015f81526020015f81525090565b5f5f5f61079986865f015187602001518860400151610860565b604080516060810182529384526020840192909252908201529695505050505050565b5f5f5f6107ca8686866109d9565b915091508161010f5761010f6012610a2b565b5f5f5f600160601b63ffffffff60c01b031980868709818687098283848384096003600160601b0363ffffffff60c01b03190984858c8d096003090890508283838b09600409838482600209850385848509089650838485858609600809850385868a880385088509089550505050808186880960020991505093509350939050565b5f5f5f600160601b63ffffffff60c01b0319604088015181818209828388858a8b090960208c0151098381850385868686098c090884858a8b098d51098581870387868f09089350811584151680156108c057600181146109065761097b565b868586098788898386096002098903898a848a098b038b88890908089a5087888983890987098903898a8e8c038c8689090887090899505086878c88098609975061097b565b8c8c8c898283098a8283098b8c8d8384096003600160601b0363ffffffff60c01b0319098d8e8889096003090890508b8c83870960040994508b8c866002098d038d838409089e508b8c8384096008098c0391508b8f8d03860894508b828d878409089d505050898a8284096002099a505050505b505050505050509450945094915050565b5f5f825f0361099f57505f9050806106fa565b600160601b63ffffffff60c01b03195f6109b985836105cf565b905081818209828189099450828383830988099350505050935093915050565b5f5f825f036109ec57505f9050806106fa565b60405160208152602080820152602060408201528560608201528460808201528360a082015260205f60c08360055afa9250505f519050935093915050565b634e487b715f52806020526024601cfd5b6040518061020001604052806010905b610a6d60405180606001604052805f81526020015f81526020015f81525090565b815260200190600190039081610a4c5790505090565b5f5f83601f840112610a93575f5ffd5b50813567ffffffffffffffff811115610aaa575f5ffd5b602083019150836020828501011115610ac1575f5ffd5b9250929050565b5f5f5f5f5f60608688031215610adc575f5ffd5b853567ffffffffffffffff811115610af2575f5ffd5b610afe88828901610a83565b90965094505060208601359250604086013567ffffffffffffffff811115610b24575f5ffd5b610b3088828901610a83565b969995985093965092949392505050565b5f5f85851115610b4f575f5ffd5b83861115610b5b575f5ffd5b5050820193919092039150565b80356020831015610332575f19602084900360031b1b1692915050565b5f82610b9f57634e487b7160e01b5f52601260045260245ffd5b500690565b634e487b7160e01b5f52603260045260245ffdfeffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551a2646970667358221220f0d427537440c9e5604f119660515b3697ad6d7e99d269210fcd8e06c8108d3564736f6c63430008230033", "linkReferences": {}, "deployedLinkReferences": {} } diff --git a/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/ERC7913RSAVerifier.json b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/ERC7913RSAVerifier.json new file mode 100644 index 0000000..2b0ecf0 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.7.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": "0x6080604052348015600e575f5ffd5b506106e58061001c5f395ff3fe608060405234801561000f575f5ffd5b5060043610610029575f3560e01c8063024ad3181461002d575b5f5ffd5b61004061003b36600461048c565b61005d565b6040516001600160e01b0319909116815260200160405180910390f35b5f808061006c878901896105a4565b915091506100cd8660405160200161008691815260200190565b60408051601f198184030181526020601f8901819004810284018101909252878352919088908890819084018382808284375f920191909152508792508691506100f39050565b6100df576001600160e01b03196100e7565b62495a6360e31b5b98975050505050505050565b5f61014d6002866040516101079190610620565b602060405180830381855afa158015610122573d5f5f3e3d5ffd5b5050506040513d601f19601f82011682018060405250810190610145919061062b565b858585610158565b90505b949350505050565b80515f9061010081108061016d575084518114155b1561017b575f915050610150565b5f5b818110156101f2575f6101938260208503610352565b90505f6101a38883016020015190565b90505f6101b38784016020015190565b9050808210156101c5575050506101f2565b808211806101d557506020850383145b156101e7575f95505050505050610150565b50505060200161017d565b505f5f610200878787610366565b9150915081610214575f9350505050610150565b5f5f5f6102278460328803016020015190565b6001600160f81b031916603160f81b0361026c5750720181898068304b0432400b281820100828002160651b91506bffffffffffffffffffffffff19905060346102c7565b600f1986850101516001600160f81b031916602f60f81b036102b95750700181798058304b0432400b28182010082160751b91506dffffffffffffffffffffffffffff19905060326102c7565b5f9650505050505050610150565b80860360025b8181101561030557602081870101516001600160f81b0319908116146102fd575f98505050505050505050610150565b6001016102cd565b5060208501516001600160f01b031916600160f01b1480156103345750826103308683016020015190565b1684145b80156103425750868501518c145b9c9b505050505050505050505050565b5f8282188284100282185b90505b92915050565b5f6060610372836103dd565b1561038d575050604080515f808252602082019092526103d5565b8251855185516040516103ac92919084908a908a908a90602001610642565b604051602081830303815290604052915060208201818184518360055afa828452910160405291505b935093915050565b5f80805b835181101561043d5780602085010151915061040f8160206104039190610685565b85518103908111150290565b61041a906008610698565b82901c1561042b57505f9392505050565b610436602082610685565b90506103e1565b5060019392505050565b5f5f83601f840112610457575f5ffd5b50813567ffffffffffffffff81111561046e575f5ffd5b602083019150836020828501011115610485575f5ffd5b9250929050565b5f5f5f5f5f606086880312156104a0575f5ffd5b853567ffffffffffffffff8111156104b6575f5ffd5b6104c288828901610447565b90965094505060208601359250604086013567ffffffffffffffff8111156104e8575f5ffd5b6104f488828901610447565b969995985093965092949392505050565b634e487b7160e01b5f52604160045260245ffd5b5f82601f830112610528575f5ffd5b813567ffffffffffffffff81111561054257610542610505565b604051601f8201601f19908116603f0116810167ffffffffffffffff8111828210171561057157610571610505565b604052818152838201602001851015610588575f5ffd5b816020850160208301375f918101602001919091529392505050565b5f5f604083850312156105b5575f5ffd5b823567ffffffffffffffff8111156105cb575f5ffd5b6105d785828601610519565b925050602083013567ffffffffffffffff8111156105f3575f5ffd5b6105ff85828601610519565b9150509250929050565b5f81518060208401855e5f93019283525090919050565b5f61035d8284610609565b5f6020828403121561063b575f5ffd5b5051919050565b8681528560208201528460408201525f6100e761066b6106656060850188610609565b86610609565b84610609565b634e487b7160e01b5f52601160045260245ffd5b8082018082111561036057610360610671565b80820281158282048414176103605761036061067156fea26469706673582212202f73fe3bc5a82b0c702502ebee8b285fbbf551f70769e45d52f948f9e0480c7364736f6c63430008230033", + "deployedBytecode": "0x608060405234801561000f575f5ffd5b5060043610610029575f3560e01c8063024ad3181461002d575b5f5ffd5b61004061003b36600461048c565b61005d565b6040516001600160e01b0319909116815260200160405180910390f35b5f808061006c878901896105a4565b915091506100cd8660405160200161008691815260200190565b60408051601f198184030181526020601f8901819004810284018101909252878352919088908890819084018382808284375f920191909152508792508691506100f39050565b6100df576001600160e01b03196100e7565b62495a6360e31b5b98975050505050505050565b5f61014d6002866040516101079190610620565b602060405180830381855afa158015610122573d5f5f3e3d5ffd5b5050506040513d601f19601f82011682018060405250810190610145919061062b565b858585610158565b90505b949350505050565b80515f9061010081108061016d575084518114155b1561017b575f915050610150565b5f5b818110156101f2575f6101938260208503610352565b90505f6101a38883016020015190565b90505f6101b38784016020015190565b9050808210156101c5575050506101f2565b808211806101d557506020850383145b156101e7575f95505050505050610150565b50505060200161017d565b505f5f610200878787610366565b9150915081610214575f9350505050610150565b5f5f5f6102278460328803016020015190565b6001600160f81b031916603160f81b0361026c5750720181898068304b0432400b281820100828002160651b91506bffffffffffffffffffffffff19905060346102c7565b600f1986850101516001600160f81b031916602f60f81b036102b95750700181798058304b0432400b28182010082160751b91506dffffffffffffffffffffffffffff19905060326102c7565b5f9650505050505050610150565b80860360025b8181101561030557602081870101516001600160f81b0319908116146102fd575f98505050505050505050610150565b6001016102cd565b5060208501516001600160f01b031916600160f01b1480156103345750826103308683016020015190565b1684145b80156103425750868501518c145b9c9b505050505050505050505050565b5f8282188284100282185b90505b92915050565b5f6060610372836103dd565b1561038d575050604080515f808252602082019092526103d5565b8251855185516040516103ac92919084908a908a908a90602001610642565b604051602081830303815290604052915060208201818184518360055afa828452910160405291505b935093915050565b5f80805b835181101561043d5780602085010151915061040f8160206104039190610685565b85518103908111150290565b61041a906008610698565b82901c1561042b57505f9392505050565b610436602082610685565b90506103e1565b5060019392505050565b5f5f83601f840112610457575f5ffd5b50813567ffffffffffffffff81111561046e575f5ffd5b602083019150836020828501011115610485575f5ffd5b9250929050565b5f5f5f5f5f606086880312156104a0575f5ffd5b853567ffffffffffffffff8111156104b6575f5ffd5b6104c288828901610447565b90965094505060208601359250604086013567ffffffffffffffff8111156104e8575f5ffd5b6104f488828901610447565b969995985093965092949392505050565b634e487b7160e01b5f52604160045260245ffd5b5f82601f830112610528575f5ffd5b813567ffffffffffffffff81111561054257610542610505565b604051601f8201601f19908116603f0116810167ffffffffffffffff8111828210171561057157610571610505565b604052818152838201602001851015610588575f5ffd5b816020850160208301375f918101602001919091529392505050565b5f5f604083850312156105b5575f5ffd5b823567ffffffffffffffff8111156105cb575f5ffd5b6105d785828601610519565b925050602083013567ffffffffffffffff8111156105f3575f5ffd5b6105ff85828601610519565b9150509250929050565b5f81518060208401855e5f93019283525090919050565b5f61035d8284610609565b5f6020828403121561063b575f5ffd5b5051919050565b8681528560208201528460408201525f6100e761066b6106656060850188610609565b86610609565b84610609565b634e487b7160e01b5f52601160045260245ffd5b8082018082111561036057610360610671565b80820281158282048414176103605761036061067156fea26469706673582212202f73fe3bc5a82b0c702502ebee8b285fbbf551f70769e45d52f948f9e0480c7364736f6c63430008230033", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/ERC7913WebAuthnVerifier.json b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/ERC7913WebAuthnVerifier.json new file mode 100644 index 0000000..1d613c5 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/ERC7913WebAuthnVerifier.json @@ -0,0 +1,40 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "ERC7913WebAuthnVerifier", + "sourceName": "contracts/utils/cryptography/verifiers/ERC7913WebAuthnVerifier.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": "0x6080604052348015600e575f5ffd5b506114168061001c5f395ff3fe608060405234801561000f575f5ffd5b5060043610610029575f3560e01c8063024ad3181461002d575b5f5ffd5b61004061003b36600461107d565b61005d565b6040516001600160e01b0319909116815260200160405180910390f35b5f5f3661006a858561010d565b9150915081801561007b5750604087145b80156100e557506100e58660405160200161009891815260200190565b604051602081830303815290604052826100b1906111c4565b6100be60205f8c8e61125a565b6100c791611281565b6100d5604060208d8f61125a565b6100de91611281565b600161020a565b6100f7576001600160e01b03196100ff565b62495a6360e31b5b925050505b95945050505050565b5f8260c0831015610120575f9150610203565b5f61012e846080818861125a565b61013791611281565b90505f6101478560a0818961125a565b61015091611281565b90508161015e6020876112b2565b10806101735750806101716020876112b2565b105b15610182575f93505050610203565b5f61018f8684818a61125a565b61019891611281565b90505f6101a78784818b61125a565b6101b091611281565b90508160206101bf868a6112b2565b6101c991906112b2565b10806101e957508060206101dd858a6112b2565b6101e791906112b2565b105b156101fa575f955050505050610203565b60019550505050505b9250929050565b5f602485608001515111801561026657506102668560a0015186606001518181016020015191516014909101106affffffffffffffffffffff199190911674113a3cb832911d113bb2b130baba34371733b2ba1160591b141690565b801561028057506102808560a00151866040015188610405565b80156102b257506102b285608001516020815181106102a1576102a16112c5565b0160200151600160f81b9081161490565b80156102ec57508115806102ec57506102ec85608001516020815181106102db576102db6112c5565b0160200151600160fa1b9081161490565b80156103215750610321856080015160208151811061030d5761030d6112c5565b01602001516001600160f81b031916610453565b80156103fb57506103fb6002866080015160028860a0015160405161034691906112f0565b602060405180830381855afa158015610361573d5f5f3e3d5ffd5b5050506040513d601f19601f8201168201806040525081019061038491906112fb565b604051602001610395929190611312565b60408051601f19818403018152908290526103af916112f0565b602060405180830381855afa1580156103ca573d5f5f3e3d5ffd5b5050506040513d601f19601f820116820180604052508101906103ed91906112fb565b865160208801518787610472565b9695505050505050565b5f5f610410836104a8565b604051602001610420919061132a565b60405160208183030381529060405290505f61044786866104428886516104b5565b6104cd565b90506103fb818361054e565b5f600160fb1b828116148061046c5750600160fc1b8216155b92915050565b5f5f5f6104828888888888610560565b915091508061049d57610498888888888861063b565b6100ff565b509695505050505050565b606061046c8260016106eb565b5f828201838110159081025f19808218830218610104565b60606104da82855161086a565b91506104e6838361086a565b92505f6104f384846112b2565b67ffffffffffffffff81111561050b5761050b6110f6565b6040519080825280601f01601f191660200182016040528015610535576020820181803683370190505b509050838303846020870101602083015e949350505050565b5f6105598383610879565b9392505050565b5f5f61056c868661089d565b158061057f575061057d84846108f4565b155b1561058f57505f90506001610631565b61059c8787878787610958565b156105ac57506001905080610631565b61061b7fbb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023600560017fa71af64de5126a4a4e02b7922d66ce9415ce88a4c9d25514d91082c8725ac9577f5d47723c8fbe580bb369fec9c2665d8e30a435b9932645482e7c9f11e872296b610958565b1561062b57505f90506001610631565b505f9050805b9550959350505050565b5f610646858561089d565b1580610659575061065783836108f4565b155b1561066557505f610104565b5f6106708484610998565b90505f61068a865f5160206113c15f395f51905f52610b8b565b90505f5f5160206113c15f395f51905f52828a0990505f5f5160206113c15f395f51905f52838a0990505f6106c0858484610b9a565b509050896106db5f5160206113c15f395f51905f5283611370565b149b9a5050505050505050505050565b606082515f03610709575060408051602081019091525f815261046c565b5f826107395760038451600261071f9190611383565b6107299190611396565b6107349060046113a9565b61075e565b60038451600461074991906113a9565b610754906002611383565b61075e9190611396565b905060405191507f4142434445464748494a4b4c4d4e4f505152535455565758595a616263646566601f5261067083027f6768696a6b6c6d6e6f707172737475767778797a303132333435363738392b2f18603f526020820181810185865187016020810180515f82525b8284101561081c576003840193508351603f8160121c16518753600187019650603f81600c1c16518753600187019650603f8160061c16518753600187019650603f8116518753506001860195506107c9565b90525085905061085d5760038651066001811461084057600281146108535761085b565b603d6001840353603d600284035361085b565b603d60018403535b505b9183525060405292915050565b5f828218828410028218610559565b5f815183511480156105595750508051602091820120825192909101919091201490565b5f82158015906108b957505f5160206113c15f395f51905f5283105b80156108c457508115155b80156105595750507f7fffffff800000007fffffffffffffffde737d56d38bcf4279dce5617e3192a81015919050565b5f600160601b63ffffffff60c01b031980838409817f5ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2604b8387856003600160601b0363ffffffff60c01b0319878b8c0908090894821191909310169190921416919050565b5f6040518681528560208201528460408201528360608201528260808201525f5f5260205f60a0836101005afa61098b57fe5b50505f5195945050505050565b6109a0610ff8565b60405180606001604052805f81526020015f81526020015f815250815f601081106109cd576109cd6112c5565b60200201819052506040518060600160405280848152602001838152602001600181525081600160108110610a0457610a046112c5565b602002018190525060405180606001604052807f6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c29681526020017f4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f58152602001600181525081600460108110610a7b57610a7b6112c5565b6020020152610a918160015b6020020151610cbe565b6040820152610aa1816004610a87565b6101008201526020810151610abe908260025b6020020151610d1a565b6060820152610ad78160015b6020020151826004610ab4565b60a0820152610ae7816002610aca565b60c0820152610af7816003610aca565b60e0820152610b108160015b6020020151826008610ab4565b610120820152610b21816002610b03565b610140820152610b32816003610b03565b610160820152610b43816004610b03565b610180820152610b5d8160015b602002015182600c610ab4565b6101a0820152610b6e816002610b50565b6101c0820152610b7f816003610b50565b6101e082015292915050565b5f610559836002840384610d78565b5f80808080805b6080811015610ca2578115610bd557610bbb848484610d99565b91955093509150610bcd848484610d99565b919550935091505b600c60fc89901c1660fe88901c17898160108110610bf557610bf56112c5565b60200201516040015115610c8e57825f03610c6457898160108110610c1c57610c1c6112c5565b6020020151518a8260108110610c3457610c346112c5565b6020020151602001518b8360108110610c4f57610c4f6112c5565b60200201516040015191965094509250610c8e565b610c868a8260108110610c7957610c796112c5565b6020020151868686610e1c565b919650945092505b50600297881b979690961b95600101610ba1565b50610cae838383610f48565b945094505050505b935093915050565b610cdf60405180606001604052805f81526020015f81526020015f81525090565b5f5f5f610cf8855f015186602001518760400151610d99565b6040805160608101825293845260208401929092529082015295945050505050565b610d3b60405180606001604052805f81526020015f81526020015f81525090565b5f5f5f610d5586865f015187602001518860400151610e1c565b604080516060810182529384526020840192909252908201529695505050505050565b5f5f5f610d86868686610f95565b9150915081610104576101046012610fe7565b5f5f5f600160601b63ffffffff60c01b031980868709818687098283848384096003600160601b0363ffffffff60c01b03190984858c8d096003090890508283838b09600409838482600209850385848509089650838485858609600809850385868a880385088509089550505050808186880960020991505093509350939050565b5f5f5f600160601b63ffffffff60c01b0319604088015181818209828388858a8b090960208c0151098381850385868686098c090884858a8b098d51098581870387868f0908935081158415168015610e7c5760018114610ec257610f37565b868586098788898386096002098903898a848a098b038b88890908089a5087888983890987098903898a8e8c038c8689090887090899505086878c880986099750610f37565b8c8c8c898283098a8283098b8c8d8384096003600160601b0363ffffffff60c01b0319098d8e8889096003090890508b8c83870960040994508b8c866002098d038d838409089e508b8c8384096008098c0391508b8f8d03860894508b828d878409089d505050898a8284096002099a505050505b505050505050509450945094915050565b5f5f825f03610f5b57505f905080610cb6565b600160601b63ffffffff60c01b03195f610f758583610b8b565b905081818209828189099450828383830988099350505050935093915050565b5f5f825f03610fa857505f905080610cb6565b60405160208152602080820152602060408201528560608201528460808201528360a082015260205f60c08360055afa9250505f519050935093915050565b634e487b715f52806020526024601cfd5b6040518061020001604052806010905b61102960405180606001604052805f81526020015f81526020015f81525090565b8152602001906001900390816110085790505090565b5f5f83601f84011261104f575f5ffd5b50813567ffffffffffffffff811115611066575f5ffd5b602083019150836020828501011115610203575f5ffd5b5f5f5f5f5f60608688031215611091575f5ffd5b853567ffffffffffffffff8111156110a7575f5ffd5b6110b38882890161103f565b90965094505060208601359250604086013567ffffffffffffffff8111156110d9575f5ffd5b6110e58882890161103f565b969995985093965092949392505050565b634e487b7160e01b5f52604160045260245ffd5b60405160c0810167ffffffffffffffff8111828210171561112d5761112d6110f6565b60405290565b5f82601f830112611142575f5ffd5b8135602083015f5f67ffffffffffffffff841115611162576111626110f6565b50604051601f19601f85018116603f0116810181811067ffffffffffffffff82111715611191576111916110f6565b6040528381529050808284018710156111a8575f5ffd5b838360208301375f602085830101528094505050505092915050565b5f60c082360312156111d4575f5ffd5b6111dc61110a565b82358152602080840135908201526040808401359082015260608084013590820152608083013567ffffffffffffffff811115611217575f5ffd5b61122336828601611133565b60808301525060a083013567ffffffffffffffff811115611242575f5ffd5b61124e36828601611133565b60a08301525092915050565b5f5f85851115611268575f5ffd5b83861115611274575f5ffd5b5050820193919092039150565b8035602083101561046c575f19602084900360031b1b1692915050565b634e487b7160e01b5f52601160045260245ffd5b8181038181111561046c5761046c61129e565b634e487b7160e01b5f52603260045260245ffd5b5f81518060208401855e5f93019283525090919050565b5f61055982846112d9565b5f6020828403121561130b575f5ffd5b5051919050565b5f61131d82856112d9565b9283525050602001919050565b6c1131b430b63632b733b2911d1160991b81525f61134b600d8301846112d9565b601160f91b81526001019392505050565b634e487b7160e01b5f52601260045260245ffd5b5f8261137e5761137e61135c565b500690565b8082018082111561046c5761046c61129e565b5f826113a4576113a461135c565b500490565b808202811582820484141761046c5761046c61129e56feffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551a264697066735822122064491a0a497372a5293902621caac328cc1f8b916318fe630388fd8e8e99955864736f6c63430008230033", + "deployedBytecode": "0x608060405234801561000f575f5ffd5b5060043610610029575f3560e01c8063024ad3181461002d575b5f5ffd5b61004061003b36600461107d565b61005d565b6040516001600160e01b0319909116815260200160405180910390f35b5f5f3661006a858561010d565b9150915081801561007b5750604087145b80156100e557506100e58660405160200161009891815260200190565b604051602081830303815290604052826100b1906111c4565b6100be60205f8c8e61125a565b6100c791611281565b6100d5604060208d8f61125a565b6100de91611281565b600161020a565b6100f7576001600160e01b03196100ff565b62495a6360e31b5b925050505b95945050505050565b5f8260c0831015610120575f9150610203565b5f61012e846080818861125a565b61013791611281565b90505f6101478560a0818961125a565b61015091611281565b90508161015e6020876112b2565b10806101735750806101716020876112b2565b105b15610182575f93505050610203565b5f61018f8684818a61125a565b61019891611281565b90505f6101a78784818b61125a565b6101b091611281565b90508160206101bf868a6112b2565b6101c991906112b2565b10806101e957508060206101dd858a6112b2565b6101e791906112b2565b105b156101fa575f955050505050610203565b60019550505050505b9250929050565b5f602485608001515111801561026657506102668560a0015186606001518181016020015191516014909101106affffffffffffffffffffff199190911674113a3cb832911d113bb2b130baba34371733b2ba1160591b141690565b801561028057506102808560a00151866040015188610405565b80156102b257506102b285608001516020815181106102a1576102a16112c5565b0160200151600160f81b9081161490565b80156102ec57508115806102ec57506102ec85608001516020815181106102db576102db6112c5565b0160200151600160fa1b9081161490565b80156103215750610321856080015160208151811061030d5761030d6112c5565b01602001516001600160f81b031916610453565b80156103fb57506103fb6002866080015160028860a0015160405161034691906112f0565b602060405180830381855afa158015610361573d5f5f3e3d5ffd5b5050506040513d601f19601f8201168201806040525081019061038491906112fb565b604051602001610395929190611312565b60408051601f19818403018152908290526103af916112f0565b602060405180830381855afa1580156103ca573d5f5f3e3d5ffd5b5050506040513d601f19601f820116820180604052508101906103ed91906112fb565b865160208801518787610472565b9695505050505050565b5f5f610410836104a8565b604051602001610420919061132a565b60405160208183030381529060405290505f61044786866104428886516104b5565b6104cd565b90506103fb818361054e565b5f600160fb1b828116148061046c5750600160fc1b8216155b92915050565b5f5f5f6104828888888888610560565b915091508061049d57610498888888888861063b565b6100ff565b509695505050505050565b606061046c8260016106eb565b5f828201838110159081025f19808218830218610104565b60606104da82855161086a565b91506104e6838361086a565b92505f6104f384846112b2565b67ffffffffffffffff81111561050b5761050b6110f6565b6040519080825280601f01601f191660200182016040528015610535576020820181803683370190505b509050838303846020870101602083015e949350505050565b5f6105598383610879565b9392505050565b5f5f61056c868661089d565b158061057f575061057d84846108f4565b155b1561058f57505f90506001610631565b61059c8787878787610958565b156105ac57506001905080610631565b61061b7fbb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023600560017fa71af64de5126a4a4e02b7922d66ce9415ce88a4c9d25514d91082c8725ac9577f5d47723c8fbe580bb369fec9c2665d8e30a435b9932645482e7c9f11e872296b610958565b1561062b57505f90506001610631565b505f9050805b9550959350505050565b5f610646858561089d565b1580610659575061065783836108f4565b155b1561066557505f610104565b5f6106708484610998565b90505f61068a865f5160206113c15f395f51905f52610b8b565b90505f5f5160206113c15f395f51905f52828a0990505f5f5160206113c15f395f51905f52838a0990505f6106c0858484610b9a565b509050896106db5f5160206113c15f395f51905f5283611370565b149b9a5050505050505050505050565b606082515f03610709575060408051602081019091525f815261046c565b5f826107395760038451600261071f9190611383565b6107299190611396565b6107349060046113a9565b61075e565b60038451600461074991906113a9565b610754906002611383565b61075e9190611396565b905060405191507f4142434445464748494a4b4c4d4e4f505152535455565758595a616263646566601f5261067083027f6768696a6b6c6d6e6f707172737475767778797a303132333435363738392b2f18603f526020820181810185865187016020810180515f82525b8284101561081c576003840193508351603f8160121c16518753600187019650603f81600c1c16518753600187019650603f8160061c16518753600187019650603f8116518753506001860195506107c9565b90525085905061085d5760038651066001811461084057600281146108535761085b565b603d6001840353603d600284035361085b565b603d60018403535b505b9183525060405292915050565b5f828218828410028218610559565b5f815183511480156105595750508051602091820120825192909101919091201490565b5f82158015906108b957505f5160206113c15f395f51905f5283105b80156108c457508115155b80156105595750507f7fffffff800000007fffffffffffffffde737d56d38bcf4279dce5617e3192a81015919050565b5f600160601b63ffffffff60c01b031980838409817f5ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2604b8387856003600160601b0363ffffffff60c01b0319878b8c0908090894821191909310169190921416919050565b5f6040518681528560208201528460408201528360608201528260808201525f5f5260205f60a0836101005afa61098b57fe5b50505f5195945050505050565b6109a0610ff8565b60405180606001604052805f81526020015f81526020015f815250815f601081106109cd576109cd6112c5565b60200201819052506040518060600160405280848152602001838152602001600181525081600160108110610a0457610a046112c5565b602002018190525060405180606001604052807f6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c29681526020017f4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f58152602001600181525081600460108110610a7b57610a7b6112c5565b6020020152610a918160015b6020020151610cbe565b6040820152610aa1816004610a87565b6101008201526020810151610abe908260025b6020020151610d1a565b6060820152610ad78160015b6020020151826004610ab4565b60a0820152610ae7816002610aca565b60c0820152610af7816003610aca565b60e0820152610b108160015b6020020151826008610ab4565b610120820152610b21816002610b03565b610140820152610b32816003610b03565b610160820152610b43816004610b03565b610180820152610b5d8160015b602002015182600c610ab4565b6101a0820152610b6e816002610b50565b6101c0820152610b7f816003610b50565b6101e082015292915050565b5f610559836002840384610d78565b5f80808080805b6080811015610ca2578115610bd557610bbb848484610d99565b91955093509150610bcd848484610d99565b919550935091505b600c60fc89901c1660fe88901c17898160108110610bf557610bf56112c5565b60200201516040015115610c8e57825f03610c6457898160108110610c1c57610c1c6112c5565b6020020151518a8260108110610c3457610c346112c5565b6020020151602001518b8360108110610c4f57610c4f6112c5565b60200201516040015191965094509250610c8e565b610c868a8260108110610c7957610c796112c5565b6020020151868686610e1c565b919650945092505b50600297881b979690961b95600101610ba1565b50610cae838383610f48565b945094505050505b935093915050565b610cdf60405180606001604052805f81526020015f81526020015f81525090565b5f5f5f610cf8855f015186602001518760400151610d99565b6040805160608101825293845260208401929092529082015295945050505050565b610d3b60405180606001604052805f81526020015f81526020015f81525090565b5f5f5f610d5586865f015187602001518860400151610e1c565b604080516060810182529384526020840192909252908201529695505050505050565b5f5f5f610d86868686610f95565b9150915081610104576101046012610fe7565b5f5f5f600160601b63ffffffff60c01b031980868709818687098283848384096003600160601b0363ffffffff60c01b03190984858c8d096003090890508283838b09600409838482600209850385848509089650838485858609600809850385868a880385088509089550505050808186880960020991505093509350939050565b5f5f5f600160601b63ffffffff60c01b0319604088015181818209828388858a8b090960208c0151098381850385868686098c090884858a8b098d51098581870387868f0908935081158415168015610e7c5760018114610ec257610f37565b868586098788898386096002098903898a848a098b038b88890908089a5087888983890987098903898a8e8c038c8689090887090899505086878c880986099750610f37565b8c8c8c898283098a8283098b8c8d8384096003600160601b0363ffffffff60c01b0319098d8e8889096003090890508b8c83870960040994508b8c866002098d038d838409089e508b8c8384096008098c0391508b8f8d03860894508b828d878409089d505050898a8284096002099a505050505b505050505050509450945094915050565b5f5f825f03610f5b57505f905080610cb6565b600160601b63ffffffff60c01b03195f610f758583610b8b565b905081818209828189099450828383830988099350505050935093915050565b5f5f825f03610fa857505f905080610cb6565b60405160208152602080820152602060408201528560608201528460808201528360a082015260205f60c08360055afa9250505f519050935093915050565b634e487b715f52806020526024601cfd5b6040518061020001604052806010905b61102960405180606001604052805f81526020015f81526020015f81525090565b8152602001906001900390816110085790505090565b5f5f83601f84011261104f575f5ffd5b50813567ffffffffffffffff811115611066575f5ffd5b602083019150836020828501011115610203575f5ffd5b5f5f5f5f5f60608688031215611091575f5ffd5b853567ffffffffffffffff8111156110a7575f5ffd5b6110b38882890161103f565b90965094505060208601359250604086013567ffffffffffffffff8111156110d9575f5ffd5b6110e58882890161103f565b969995985093965092949392505050565b634e487b7160e01b5f52604160045260245ffd5b60405160c0810167ffffffffffffffff8111828210171561112d5761112d6110f6565b60405290565b5f82601f830112611142575f5ffd5b8135602083015f5f67ffffffffffffffff841115611162576111626110f6565b50604051601f19601f85018116603f0116810181811067ffffffffffffffff82111715611191576111916110f6565b6040528381529050808284018710156111a8575f5ffd5b838360208301375f602085830101528094505050505092915050565b5f60c082360312156111d4575f5ffd5b6111dc61110a565b82358152602080840135908201526040808401359082015260608084013590820152608083013567ffffffffffffffff811115611217575f5ffd5b61122336828601611133565b60808301525060a083013567ffffffffffffffff811115611242575f5ffd5b61124e36828601611133565b60a08301525092915050565b5f5f85851115611268575f5ffd5b83861115611274575f5ffd5b5050820193919092039150565b8035602083101561046c575f19602084900360031b1b1692915050565b634e487b7160e01b5f52601160045260245ffd5b8181038181111561046c5761046c61129e565b634e487b7160e01b5f52603260045260245ffd5b5f81518060208401855e5f93019283525090919050565b5f61055982846112d9565b5f6020828403121561130b575f5ffd5b5051919050565b5f61131d82856112d9565b9283525050602001919050565b6c1131b430b63632b733b2911d1160991b81525f61134b600d8301846112d9565b601160f91b81526001019392505050565b634e487b7160e01b5f52601260045260245ffd5b5f8261137e5761137e61135c565b500690565b8082018082111561046c5761046c61129e565b5f826113a4576113a461135c565b500490565b808202811582820484141761046c5761046c61129e56feffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551a264697066735822122064491a0a497372a5293902621caac328cc1f8b916318fe630388fd8e8e99955864736f6c63430008230033", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/EnumerableMap.json b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/EnumerableMap.json similarity index 79% rename from dependencies/@openzeppelin-contracts-5.5.0/build/contracts/EnumerableMap.json rename to dependencies/@openzeppelin-contracts-5.7.0/build/contracts/EnumerableMap.json index 253736a..b42d5ea 100644 --- a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/EnumerableMap.json +++ b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/EnumerableMap.json @@ -26,8 +26,8 @@ "type": "error" } ], - "bytecode": "0x60556032600b8282823980515f1a607314602657634e487b7160e01b5f525f60045260245ffd5b305f52607381538281f3fe730000000000000000000000000000000000000000301460806040525f5ffdfea2646970667358221220e51f9ce701f7126212cecc0ee3fab4e627cb81305d2f70f98888f475ba19a32c64736f6c634300081b0033", - "deployedBytecode": "0x730000000000000000000000000000000000000000301460806040525f5ffdfea2646970667358221220e51f9ce701f7126212cecc0ee3fab4e627cb81305d2f70f98888f475ba19a32c64736f6c634300081b0033", + "bytecode": "0x60556032600b8282823980515f1a607314602657634e487b7160e01b5f525f60045260245ffd5b305f52607381538281f3fe730000000000000000000000000000000000000000301460806040525f5ffdfea264697066735822122035cb58fa02f1f40e90ea259d34652501535f7852b2eb882c51895cfdadcb5a7664736f6c63430008230033", + "deployedBytecode": "0x730000000000000000000000000000000000000000301460806040525f5ffdfea264697066735822122035cb58fa02f1f40e90ea259d34652501535f7852b2eb882c51895cfdadcb5a7664736f6c63430008230033", "linkReferences": {}, "deployedLinkReferences": {} } diff --git a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/EnumerableSet.json b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/EnumerableSet.json similarity index 67% rename from dependencies/@openzeppelin-contracts-5.5.0/build/contracts/EnumerableSet.json rename to dependencies/@openzeppelin-contracts-5.7.0/build/contracts/EnumerableSet.json index 12eb0b3..e71a5e6 100644 --- a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/EnumerableSet.json +++ b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/EnumerableSet.json @@ -3,8 +3,8 @@ "contractName": "EnumerableSet", "sourceName": "contracts/utils/structs/EnumerableSet.sol", "abi": [], - "bytecode": "0x60556032600b8282823980515f1a607314602657634e487b7160e01b5f525f60045260245ffd5b305f52607381538281f3fe730000000000000000000000000000000000000000301460806040525f5ffdfea2646970667358221220713f6214bf727f4aef6183e263ed1bf31f0d396c5827f929808e0c456d1a220d64736f6c634300081b0033", - "deployedBytecode": "0x730000000000000000000000000000000000000000301460806040525f5ffdfea2646970667358221220713f6214bf727f4aef6183e263ed1bf31f0d396c5827f929808e0c456d1a220d64736f6c634300081b0033", + "bytecode": "0x60556032600b8282823980515f1a607314602657634e487b7160e01b5f525f60045260245ffd5b305f52607381538281f3fe730000000000000000000000000000000000000000301460806040525f5ffdfea2646970667358221220b1737f00e1437da0c626d2bc8086e4588517caf76ef998c73a9f5f916c277b5064736f6c63430008230033", + "deployedBytecode": "0x730000000000000000000000000000000000000000301460806040525f5ffdfea2646970667358221220b1737f00e1437da0c626d2bc8086e4588517caf76ef998c73a9f5f916c277b5064736f6c63430008230033", "linkReferences": {}, "deployedLinkReferences": {} } diff --git a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/Errors.json b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/Errors.json similarity index 83% rename from dependencies/@openzeppelin-contracts-5.5.0/build/contracts/Errors.json rename to dependencies/@openzeppelin-contracts-5.7.0/build/contracts/Errors.json index 01567b4..3f9f316 100644 --- a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/Errors.json +++ b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/Errors.json @@ -41,8 +41,8 @@ "type": "error" } ], - "bytecode": "0x60556032600b8282823980515f1a607314602657634e487b7160e01b5f525f60045260245ffd5b305f52607381538281f3fe730000000000000000000000000000000000000000301460806040525f5ffdfea26469706673582212203674537990f67e9f6c04733daf526fbb00a8b67fab7890e388d422b34bcefe7e64736f6c634300081b0033", - "deployedBytecode": "0x730000000000000000000000000000000000000000301460806040525f5ffdfea26469706673582212203674537990f67e9f6c04733daf526fbb00a8b67fab7890e388d422b34bcefe7e64736f6c634300081b0033", + "bytecode": "0x60556032600b8282823980515f1a607314602657634e487b7160e01b5f525f60045260245ffd5b305f52607381538281f3fe730000000000000000000000000000000000000000301460806040525f5ffdfea264697066735822122091c8fc69292dd391b1a4b1896f3e57b0a04670a9a972803a50cf0c62b9bf9edc64736f6c63430008230033", + "deployedBytecode": "0x730000000000000000000000000000000000000000301460806040525f5ffdfea264697066735822122091c8fc69292dd391b1a4b1896f3e57b0a04670a9a972803a50cf0c62b9bf9edc64736f6c63430008230033", "linkReferences": {}, "deployedLinkReferences": {} } diff --git a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/Governor.json b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/Governor.json similarity index 99% rename from dependencies/@openzeppelin-contracts-5.5.0/build/contracts/Governor.json rename to dependencies/@openzeppelin-contracts-5.7.0/build/contracts/Governor.json index 0925fc7..b9b0de9 100644 --- a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/Governor.json +++ b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/Governor.json @@ -123,28 +123,34 @@ { "inputs": [ { - "internalType": "uint256", - "name": "proposalId", - "type": "uint256" + "internalType": "address", + "name": "account", + "type": "address" } ], - "name": "GovernorNotQueuedProposal", + "name": "GovernorOnlyExecutor", "type": "error" }, { "inputs": [ { - "internalType": "address", - "name": "account", - "type": "address" + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" } ], - "name": "GovernorOnlyExecutor", + "name": "GovernorProposalQueueingFailed", "type": "error" }, { - "inputs": [], - "name": "GovernorQueueNotImplemented", + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + } + ], + "name": "GovernorProposalQueueingNotRequired", "type": "error" }, { diff --git a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/GovernorCountingFractional.json b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/GovernorCountingFractional.json similarity index 99% rename from dependencies/@openzeppelin-contracts-5.5.0/build/contracts/GovernorCountingFractional.json rename to dependencies/@openzeppelin-contracts-5.7.0/build/contracts/GovernorCountingFractional.json index b1f0de3..d38eeb6 100644 --- a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/GovernorCountingFractional.json +++ b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/GovernorCountingFractional.json @@ -144,28 +144,34 @@ { "inputs": [ { - "internalType": "uint256", - "name": "proposalId", - "type": "uint256" + "internalType": "address", + "name": "account", + "type": "address" } ], - "name": "GovernorNotQueuedProposal", + "name": "GovernorOnlyExecutor", "type": "error" }, { "inputs": [ { - "internalType": "address", - "name": "account", - "type": "address" + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" } ], - "name": "GovernorOnlyExecutor", + "name": "GovernorProposalQueueingFailed", "type": "error" }, { - "inputs": [], - "name": "GovernorQueueNotImplemented", + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + } + ], + "name": "GovernorProposalQueueingNotRequired", "type": "error" }, { diff --git a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/GovernorCountingOverridable.json b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/GovernorCountingOverridable.json similarity index 99% rename from dependencies/@openzeppelin-contracts-5.5.0/build/contracts/GovernorCountingOverridable.json rename to dependencies/@openzeppelin-contracts-5.7.0/build/contracts/GovernorCountingOverridable.json index 56c0e83..1420075 100644 --- a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/GovernorCountingOverridable.json +++ b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/GovernorCountingOverridable.json @@ -3,6 +3,11 @@ "contractName": "GovernorCountingOverridable", "sourceName": "contracts/governance/extensions/GovernorCountingOverridable.sol", "abi": [ + { + "inputs": [], + "name": "ERC6372InconsistentClock", + "type": "error" + }, { "inputs": [], "name": "FailedCall", @@ -134,28 +139,34 @@ { "inputs": [ { - "internalType": "uint256", - "name": "proposalId", - "type": "uint256" + "internalType": "address", + "name": "account", + "type": "address" } ], - "name": "GovernorNotQueuedProposal", + "name": "GovernorOnlyExecutor", "type": "error" }, { "inputs": [ { - "internalType": "address", - "name": "account", - "type": "address" + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" } ], - "name": "GovernorOnlyExecutor", + "name": "GovernorProposalQueueingFailed", "type": "error" }, { - "inputs": [], - "name": "GovernorQueueNotImplemented", + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + } + ], + "name": "GovernorProposalQueueingNotRequired", "type": "error" }, { diff --git a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/GovernorCountingSimple.json b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/GovernorCountingSimple.json similarity index 99% rename from dependencies/@openzeppelin-contracts-5.5.0/build/contracts/GovernorCountingSimple.json rename to dependencies/@openzeppelin-contracts-5.7.0/build/contracts/GovernorCountingSimple.json index f5c5c2f..85ae79e 100644 --- a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/GovernorCountingSimple.json +++ b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/GovernorCountingSimple.json @@ -123,28 +123,34 @@ { "inputs": [ { - "internalType": "uint256", - "name": "proposalId", - "type": "uint256" + "internalType": "address", + "name": "account", + "type": "address" } ], - "name": "GovernorNotQueuedProposal", + "name": "GovernorOnlyExecutor", "type": "error" }, { "inputs": [ { - "internalType": "address", - "name": "account", - "type": "address" + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" } ], - "name": "GovernorOnlyExecutor", + "name": "GovernorProposalQueueingFailed", "type": "error" }, { - "inputs": [], - "name": "GovernorQueueNotImplemented", + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + } + ], + "name": "GovernorProposalQueueingNotRequired", "type": "error" }, { diff --git a/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/GovernorCrosschain.json b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/GovernorCrosschain.json new file mode 100644 index 0000000..cf5337c --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/GovernorCrosschain.json @@ -0,0 +1,1406 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "GovernorCrosschain", + "sourceName": "contracts/governance/extensions/GovernorCrosschain.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": "address", + "name": "account", + "type": "address" + } + ], + "name": "GovernorOnlyExecutor", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + } + ], + "name": "GovernorProposalQueueingFailed", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + } + ], + "name": "GovernorProposalQueueingNotRequired", + "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": "address", + "name": "gateway", + "type": "address" + }, + { + "internalType": "bytes", + "name": "executor", + "type": "bytes" + }, + { + "internalType": "Mode", + "name": "mode", + "type": "bytes32" + }, + { + "internalType": "bytes", + "name": "executionCalldata", + "type": "bytes" + } + ], + "name": "relayCrosschain", + "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.5.0/build/contracts/GovernorNoncesKeyed.json b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/GovernorNoncesKeyed.json similarity index 99% rename from dependencies/@openzeppelin-contracts-5.5.0/build/contracts/GovernorNoncesKeyed.json rename to dependencies/@openzeppelin-contracts-5.7.0/build/contracts/GovernorNoncesKeyed.json index 82ca96e..6ae1fee 100644 --- a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/GovernorNoncesKeyed.json +++ b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/GovernorNoncesKeyed.json @@ -123,28 +123,34 @@ { "inputs": [ { - "internalType": "uint256", - "name": "proposalId", - "type": "uint256" + "internalType": "address", + "name": "account", + "type": "address" } ], - "name": "GovernorNotQueuedProposal", + "name": "GovernorOnlyExecutor", "type": "error" }, { "inputs": [ { - "internalType": "address", - "name": "account", - "type": "address" + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" } ], - "name": "GovernorOnlyExecutor", + "name": "GovernorProposalQueueingFailed", "type": "error" }, { - "inputs": [], - "name": "GovernorQueueNotImplemented", + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + } + ], + "name": "GovernorProposalQueueingNotRequired", "type": "error" }, { diff --git a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/GovernorPreventLateQuorum.json b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/GovernorPreventLateQuorum.json similarity index 97% rename from dependencies/@openzeppelin-contracts-5.5.0/build/contracts/GovernorPreventLateQuorum.json rename to dependencies/@openzeppelin-contracts-5.7.0/build/contracts/GovernorPreventLateQuorum.json index 1cbb4fd..1176738 100644 --- a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/GovernorPreventLateQuorum.json +++ b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/GovernorPreventLateQuorum.json @@ -120,31 +120,53 @@ "name": "GovernorNonexistentProposal", "type": "error" }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "GovernorOnlyExecutor", + "type": "error" + }, { "inputs": [ { "internalType": "uint256", - "name": "proposalId", + "name": "newVoteExtension", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "maxVoteExtension", "type": "uint256" } ], - "name": "GovernorNotQueuedProposal", + "name": "GovernorPreventLateQuorumVoteExtensionTooLarge", "type": "error" }, { "inputs": [ { - "internalType": "address", - "name": "account", - "type": "address" + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" } ], - "name": "GovernorOnlyExecutor", + "name": "GovernorProposalQueueingFailed", "type": "error" }, { - "inputs": [], - "name": "GovernorQueueNotImplemented", + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + } + ], + "name": "GovernorProposalQueueingNotRequired", "type": "error" }, { diff --git a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/GovernorProposalGuardian.json b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/GovernorProposalGuardian.json similarity index 99% rename from dependencies/@openzeppelin-contracts-5.5.0/build/contracts/GovernorProposalGuardian.json rename to dependencies/@openzeppelin-contracts-5.7.0/build/contracts/GovernorProposalGuardian.json index 153b1e0..0e4ec9e 100644 --- a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/GovernorProposalGuardian.json +++ b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/GovernorProposalGuardian.json @@ -123,28 +123,34 @@ { "inputs": [ { - "internalType": "uint256", - "name": "proposalId", - "type": "uint256" + "internalType": "address", + "name": "account", + "type": "address" } ], - "name": "GovernorNotQueuedProposal", + "name": "GovernorOnlyExecutor", "type": "error" }, { "inputs": [ { - "internalType": "address", - "name": "account", - "type": "address" + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" } ], - "name": "GovernorOnlyExecutor", + "name": "GovernorProposalQueueingFailed", "type": "error" }, { - "inputs": [], - "name": "GovernorQueueNotImplemented", + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + } + ], + "name": "GovernorProposalQueueingNotRequired", "type": "error" }, { diff --git a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/GovernorSequentialProposalId.json b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/GovernorSequentialProposalId.json similarity index 99% rename from dependencies/@openzeppelin-contracts-5.5.0/build/contracts/GovernorSequentialProposalId.json rename to dependencies/@openzeppelin-contracts-5.7.0/build/contracts/GovernorSequentialProposalId.json index 85ca25a..1addadc 100644 --- a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/GovernorSequentialProposalId.json +++ b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/GovernorSequentialProposalId.json @@ -128,28 +128,34 @@ { "inputs": [ { - "internalType": "uint256", - "name": "proposalId", - "type": "uint256" + "internalType": "address", + "name": "account", + "type": "address" } ], - "name": "GovernorNotQueuedProposal", + "name": "GovernorOnlyExecutor", "type": "error" }, { "inputs": [ { - "internalType": "address", - "name": "account", - "type": "address" + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" } ], - "name": "GovernorOnlyExecutor", + "name": "GovernorProposalQueueingFailed", "type": "error" }, { - "inputs": [], - "name": "GovernorQueueNotImplemented", + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + } + ], + "name": "GovernorProposalQueueingNotRequired", "type": "error" }, { diff --git a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/GovernorSettings.json b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/GovernorSettings.json similarity index 99% rename from dependencies/@openzeppelin-contracts-5.5.0/build/contracts/GovernorSettings.json rename to dependencies/@openzeppelin-contracts-5.7.0/build/contracts/GovernorSettings.json index 9c5068b..d56641f 100644 --- a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/GovernorSettings.json +++ b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/GovernorSettings.json @@ -123,28 +123,34 @@ { "inputs": [ { - "internalType": "uint256", - "name": "proposalId", - "type": "uint256" + "internalType": "address", + "name": "account", + "type": "address" } ], - "name": "GovernorNotQueuedProposal", + "name": "GovernorOnlyExecutor", "type": "error" }, { "inputs": [ { - "internalType": "address", - "name": "account", - "type": "address" + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" } ], - "name": "GovernorOnlyExecutor", + "name": "GovernorProposalQueueingFailed", "type": "error" }, { - "inputs": [], - "name": "GovernorQueueNotImplemented", + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + } + ], + "name": "GovernorProposalQueueingNotRequired", "type": "error" }, { diff --git a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/GovernorStorage.json b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/GovernorStorage.json similarity index 99% rename from dependencies/@openzeppelin-contracts-5.5.0/build/contracts/GovernorStorage.json rename to dependencies/@openzeppelin-contracts-5.7.0/build/contracts/GovernorStorage.json index 2c229dd..1798e09 100644 --- a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/GovernorStorage.json +++ b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/GovernorStorage.json @@ -123,28 +123,34 @@ { "inputs": [ { - "internalType": "uint256", - "name": "proposalId", - "type": "uint256" + "internalType": "address", + "name": "account", + "type": "address" } ], - "name": "GovernorNotQueuedProposal", + "name": "GovernorOnlyExecutor", "type": "error" }, { "inputs": [ { - "internalType": "address", - "name": "account", - "type": "address" + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" } ], - "name": "GovernorOnlyExecutor", + "name": "GovernorProposalQueueingFailed", "type": "error" }, { - "inputs": [], - "name": "GovernorQueueNotImplemented", + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + } + ], + "name": "GovernorProposalQueueingNotRequired", "type": "error" }, { diff --git a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/GovernorSuperQuorum.json b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/GovernorSuperQuorum.json similarity index 99% rename from dependencies/@openzeppelin-contracts-5.5.0/build/contracts/GovernorSuperQuorum.json rename to dependencies/@openzeppelin-contracts-5.7.0/build/contracts/GovernorSuperQuorum.json index dfa180b..38fa460 100644 --- a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/GovernorSuperQuorum.json +++ b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/GovernorSuperQuorum.json @@ -123,28 +123,34 @@ { "inputs": [ { - "internalType": "uint256", - "name": "proposalId", - "type": "uint256" + "internalType": "address", + "name": "account", + "type": "address" } ], - "name": "GovernorNotQueuedProposal", + "name": "GovernorOnlyExecutor", "type": "error" }, { "inputs": [ { - "internalType": "address", - "name": "account", - "type": "address" + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" } ], - "name": "GovernorOnlyExecutor", + "name": "GovernorProposalQueueingFailed", "type": "error" }, { - "inputs": [], - "name": "GovernorQueueNotImplemented", + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + } + ], + "name": "GovernorProposalQueueingNotRequired", "type": "error" }, { diff --git a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/GovernorTimelockAccess.json b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/GovernorTimelockAccess.json similarity index 99% rename from dependencies/@openzeppelin-contracts-5.5.0/build/contracts/GovernorTimelockAccess.json rename to dependencies/@openzeppelin-contracts-5.7.0/build/contracts/GovernorTimelockAccess.json index a67165c..2418b65 100644 --- a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/GovernorTimelockAccess.json +++ b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/GovernorTimelockAccess.json @@ -149,28 +149,34 @@ { "inputs": [ { - "internalType": "uint256", - "name": "proposalId", - "type": "uint256" + "internalType": "address", + "name": "account", + "type": "address" } ], - "name": "GovernorNotQueuedProposal", + "name": "GovernorOnlyExecutor", "type": "error" }, { "inputs": [ { - "internalType": "address", - "name": "account", - "type": "address" + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" } ], - "name": "GovernorOnlyExecutor", + "name": "GovernorProposalQueueingFailed", "type": "error" }, { - "inputs": [], - "name": "GovernorQueueNotImplemented", + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + } + ], + "name": "GovernorProposalQueueingNotRequired", "type": "error" }, { diff --git a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/GovernorTimelockCompound.json b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/GovernorTimelockCompound.json similarity index 99% rename from dependencies/@openzeppelin-contracts-5.5.0/build/contracts/GovernorTimelockCompound.json rename to dependencies/@openzeppelin-contracts-5.7.0/build/contracts/GovernorTimelockCompound.json index 01eb92e..ae1350f 100644 --- a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/GovernorTimelockCompound.json +++ b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/GovernorTimelockCompound.json @@ -123,28 +123,34 @@ { "inputs": [ { - "internalType": "uint256", - "name": "proposalId", - "type": "uint256" + "internalType": "address", + "name": "account", + "type": "address" } ], - "name": "GovernorNotQueuedProposal", + "name": "GovernorOnlyExecutor", "type": "error" }, { "inputs": [ { - "internalType": "address", - "name": "account", - "type": "address" + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" } ], - "name": "GovernorOnlyExecutor", + "name": "GovernorProposalQueueingFailed", "type": "error" }, { - "inputs": [], - "name": "GovernorQueueNotImplemented", + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + } + ], + "name": "GovernorProposalQueueingNotRequired", "type": "error" }, { diff --git a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/GovernorTimelockControl.json b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/GovernorTimelockControl.json similarity index 99% rename from dependencies/@openzeppelin-contracts-5.5.0/build/contracts/GovernorTimelockControl.json rename to dependencies/@openzeppelin-contracts-5.7.0/build/contracts/GovernorTimelockControl.json index 4014f0a..e4ad7b3 100644 --- a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/GovernorTimelockControl.json +++ b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/GovernorTimelockControl.json @@ -123,28 +123,34 @@ { "inputs": [ { - "internalType": "uint256", - "name": "proposalId", - "type": "uint256" + "internalType": "address", + "name": "account", + "type": "address" } ], - "name": "GovernorNotQueuedProposal", + "name": "GovernorOnlyExecutor", "type": "error" }, { "inputs": [ { - "internalType": "address", - "name": "account", - "type": "address" + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" } ], - "name": "GovernorOnlyExecutor", + "name": "GovernorProposalQueueingFailed", "type": "error" }, { - "inputs": [], - "name": "GovernorQueueNotImplemented", + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + } + ], + "name": "GovernorProposalQueueingNotRequired", "type": "error" }, { diff --git a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/GovernorVotes.json b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/GovernorVotes.json similarity index 98% rename from dependencies/@openzeppelin-contracts-5.5.0/build/contracts/GovernorVotes.json rename to dependencies/@openzeppelin-contracts-5.7.0/build/contracts/GovernorVotes.json index 02b7c87..e5165ac 100644 --- a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/GovernorVotes.json +++ b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/GovernorVotes.json @@ -3,6 +3,11 @@ "contractName": "GovernorVotes", "sourceName": "contracts/governance/extensions/GovernorVotes.sol", "abi": [ + { + "inputs": [], + "name": "ERC6372InconsistentClock", + "type": "error" + }, { "inputs": [], "name": "FailedCall", @@ -123,28 +128,34 @@ { "inputs": [ { - "internalType": "uint256", - "name": "proposalId", - "type": "uint256" + "internalType": "address", + "name": "account", + "type": "address" } ], - "name": "GovernorNotQueuedProposal", + "name": "GovernorOnlyExecutor", "type": "error" }, { "inputs": [ { - "internalType": "address", - "name": "account", - "type": "address" + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" } ], - "name": "GovernorOnlyExecutor", + "name": "GovernorProposalQueueingFailed", "type": "error" }, { - "inputs": [], - "name": "GovernorQueueNotImplemented", + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + } + ], + "name": "GovernorProposalQueueingNotRequired", "type": "error" }, { diff --git a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/GovernorVotesQuorumFraction.json b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/GovernorVotesQuorumFraction.json similarity index 98% rename from dependencies/@openzeppelin-contracts-5.5.0/build/contracts/GovernorVotesQuorumFraction.json rename to dependencies/@openzeppelin-contracts-5.7.0/build/contracts/GovernorVotesQuorumFraction.json index 4d22170..ffa80c9 100644 --- a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/GovernorVotesQuorumFraction.json +++ b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/GovernorVotesQuorumFraction.json @@ -8,6 +8,11 @@ "name": "CheckpointUnorderedInsertion", "type": "error" }, + { + "inputs": [], + "name": "ERC6372InconsistentClock", + "type": "error" + }, { "inputs": [], "name": "FailedCall", @@ -144,28 +149,34 @@ { "inputs": [ { - "internalType": "uint256", - "name": "proposalId", - "type": "uint256" + "internalType": "address", + "name": "account", + "type": "address" } ], - "name": "GovernorNotQueuedProposal", + "name": "GovernorOnlyExecutor", "type": "error" }, { "inputs": [ { - "internalType": "address", - "name": "account", - "type": "address" + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" } ], - "name": "GovernorOnlyExecutor", + "name": "GovernorProposalQueueingFailed", "type": "error" }, { - "inputs": [], - "name": "GovernorQueueNotImplemented", + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + } + ], + "name": "GovernorProposalQueueingNotRequired", "type": "error" }, { diff --git a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/GovernorVotesSuperQuorumFraction.json b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/GovernorVotesSuperQuorumFraction.json similarity index 99% rename from dependencies/@openzeppelin-contracts-5.5.0/build/contracts/GovernorVotesSuperQuorumFraction.json rename to dependencies/@openzeppelin-contracts-5.7.0/build/contracts/GovernorVotesSuperQuorumFraction.json index e20bfea..73a42ba 100644 --- a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/GovernorVotesSuperQuorumFraction.json +++ b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/GovernorVotesSuperQuorumFraction.json @@ -8,6 +8,11 @@ "name": "CheckpointUnorderedInsertion", "type": "error" }, + { + "inputs": [], + "name": "ERC6372InconsistentClock", + "type": "error" + }, { "inputs": [], "name": "FailedCall", @@ -192,28 +197,34 @@ { "inputs": [ { - "internalType": "uint256", - "name": "proposalId", - "type": "uint256" + "internalType": "address", + "name": "account", + "type": "address" } ], - "name": "GovernorNotQueuedProposal", + "name": "GovernorOnlyExecutor", "type": "error" }, { "inputs": [ { - "internalType": "address", - "name": "account", - "type": "address" + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" } ], - "name": "GovernorOnlyExecutor", + "name": "GovernorProposalQueueingFailed", "type": "error" }, { - "inputs": [], - "name": "GovernorQueueNotImplemented", + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + } + ], + "name": "GovernorProposalQueueingNotRequired", "type": "error" }, { diff --git a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/Hashes.json b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/Hashes.json similarity index 66% rename from dependencies/@openzeppelin-contracts-5.5.0/build/contracts/Hashes.json rename to dependencies/@openzeppelin-contracts-5.7.0/build/contracts/Hashes.json index 9271985..f366d93 100644 --- a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/Hashes.json +++ b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/Hashes.json @@ -3,8 +3,8 @@ "contractName": "Hashes", "sourceName": "contracts/utils/cryptography/Hashes.sol", "abi": [], - "bytecode": "0x60556032600b8282823980515f1a607314602657634e487b7160e01b5f525f60045260245ffd5b305f52607381538281f3fe730000000000000000000000000000000000000000301460806040525f5ffdfea26469706673582212208d74f124b0b195abcc7e3d14f3f42d9043d1679b77161032c4fa3ebe20d5946a64736f6c634300081b0033", - "deployedBytecode": "0x730000000000000000000000000000000000000000301460806040525f5ffdfea26469706673582212208d74f124b0b195abcc7e3d14f3f42d9043d1679b77161032c4fa3ebe20d5946a64736f6c634300081b0033", + "bytecode": "0x60556032600b8282823980515f1a607314602657634e487b7160e01b5f525f60045260245ffd5b305f52607381538281f3fe730000000000000000000000000000000000000000301460806040525f5ffdfea2646970667358221220fc06b876ed1be24ba6e97cb546a06ccb06c6a69e4b84e8b5b6f6244cb70003ae64736f6c63430008230033", + "deployedBytecode": "0x730000000000000000000000000000000000000000301460806040525f5ffdfea2646970667358221220fc06b876ed1be24ba6e97cb546a06ccb06c6a69e4b84e8b5b6f6244cb70003ae64736f6c63430008230033", "linkReferences": {}, "deployedLinkReferences": {} } diff --git a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/Heap.json b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/Heap.json similarity index 66% rename from dependencies/@openzeppelin-contracts-5.5.0/build/contracts/Heap.json rename to dependencies/@openzeppelin-contracts-5.7.0/build/contracts/Heap.json index b08635a..c2ddc0c 100644 --- a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/Heap.json +++ b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/Heap.json @@ -3,8 +3,8 @@ "contractName": "Heap", "sourceName": "contracts/utils/structs/Heap.sol", "abi": [], - "bytecode": "0x60556032600b8282823980515f1a607314602657634e487b7160e01b5f525f60045260245ffd5b305f52607381538281f3fe730000000000000000000000000000000000000000301460806040525f5ffdfea2646970667358221220c873b9688da2450c7d920700f8d0737ea202ef6e2eff74bd57558e5b37b8311b64736f6c634300081b0033", - "deployedBytecode": "0x730000000000000000000000000000000000000000301460806040525f5ffdfea2646970667358221220c873b9688da2450c7d920700f8d0737ea202ef6e2eff74bd57558e5b37b8311b64736f6c634300081b0033", + "bytecode": "0x60556032600b8282823980515f1a607314602657634e487b7160e01b5f525f60045260245ffd5b305f52607381538281f3fe730000000000000000000000000000000000000000301460806040525f5ffdfea2646970667358221220c11a3df249511d15c5f98e13647ba65ea59414b79a5c4a05b92d9b9edba9f2c764736f6c63430008230033", + "deployedBytecode": "0x730000000000000000000000000000000000000000301460806040525f5ffdfea2646970667358221220c11a3df249511d15c5f98e13647ba65ea59414b79a5c4a05b92d9b9edba9f2c764736f6c63430008230033", "linkReferences": {}, "deployedLinkReferences": {} } diff --git a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/IAccessControl.json b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/IAccessControl.json similarity index 100% rename from dependencies/@openzeppelin-contracts-5.5.0/build/contracts/IAccessControl.json rename to dependencies/@openzeppelin-contracts-5.7.0/build/contracts/IAccessControl.json diff --git a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/IAccessControlDefaultAdminRules.json b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/IAccessControlDefaultAdminRules.json similarity index 100% rename from dependencies/@openzeppelin-contracts-5.5.0/build/contracts/IAccessControlDefaultAdminRules.json rename to dependencies/@openzeppelin-contracts-5.7.0/build/contracts/IAccessControlDefaultAdminRules.json diff --git a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/IAccessControlEnumerable.json b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/IAccessControlEnumerable.json similarity index 100% rename from dependencies/@openzeppelin-contracts-5.5.0/build/contracts/IAccessControlEnumerable.json rename to dependencies/@openzeppelin-contracts-5.7.0/build/contracts/IAccessControlEnumerable.json diff --git a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/IAccessManaged.json b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/IAccessManaged.json similarity index 100% rename from dependencies/@openzeppelin-contracts-5.5.0/build/contracts/IAccessManaged.json rename to dependencies/@openzeppelin-contracts-5.7.0/build/contracts/IAccessManaged.json diff --git a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/IAccessManager.json b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/IAccessManager.json similarity index 99% rename from dependencies/@openzeppelin-contracts-5.5.0/build/contracts/IAccessManager.json rename to dependencies/@openzeppelin-contracts-5.7.0/build/contracts/IAccessManager.json index e0d18f7..d7893b2 100644 --- a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/IAccessManager.json +++ b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/IAccessManager.json @@ -41,6 +41,17 @@ "name": "AccessManagerInvalidInitialAdmin", "type": "error" }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "selector", + "type": "bytes4" + } + ], + "name": "AccessManagerLockedFunction", + "type": "error" + }, { "inputs": [ { diff --git a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/IAccount.json b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/IAccount.json similarity index 97% rename from dependencies/@openzeppelin-contracts-5.5.0/build/contracts/IAccount.json rename to dependencies/@openzeppelin-contracts-5.7.0/build/contracts/IAccount.json index 7133e43..be1aac7 100644 --- a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/IAccount.json +++ b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/IAccount.json @@ -1,7 +1,7 @@ { "_format": "hh-sol-artifact-1", "contractName": "IAccount", - "sourceName": "contracts/interfaces/draft-IERC4337.sol", + "sourceName": "contracts/interfaces/IERC4337.sol", "abi": [ { "inputs": [ diff --git a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/IAccountExecute.json b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/IAccountExecute.json similarity index 96% rename from dependencies/@openzeppelin-contracts-5.5.0/build/contracts/IAccountExecute.json rename to dependencies/@openzeppelin-contracts-5.7.0/build/contracts/IAccountExecute.json index 750f602..dd7490d 100644 --- a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/IAccountExecute.json +++ b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/IAccountExecute.json @@ -1,7 +1,7 @@ { "_format": "hh-sol-artifact-1", "contractName": "IAccountExecute", - "sourceName": "contracts/interfaces/draft-IERC4337.sol", + "sourceName": "contracts/interfaces/IERC4337.sol", "abi": [ { "inputs": [ diff --git a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/IAggregator.json b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/IAggregator.json similarity index 98% rename from dependencies/@openzeppelin-contracts-5.5.0/build/contracts/IAggregator.json rename to dependencies/@openzeppelin-contracts-5.7.0/build/contracts/IAggregator.json index cc320ad..04ae415 100644 --- a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/IAggregator.json +++ b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/IAggregator.json @@ -1,7 +1,7 @@ { "_format": "hh-sol-artifact-1", "contractName": "IAggregator", - "sourceName": "contracts/interfaces/draft-IERC4337.sol", + "sourceName": "contracts/interfaces/IERC4337.sol", "abi": [ { "inputs": [ diff --git a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/IAuthority.json b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/IAuthority.json similarity index 100% rename from dependencies/@openzeppelin-contracts-5.5.0/build/contracts/IAuthority.json rename to dependencies/@openzeppelin-contracts-5.7.0/build/contracts/IAuthority.json diff --git a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/IBeacon.json b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/IBeacon.json similarity index 100% rename from dependencies/@openzeppelin-contracts-5.5.0/build/contracts/IBeacon.json rename to dependencies/@openzeppelin-contracts-5.7.0/build/contracts/IBeacon.json diff --git a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/ICompoundTimelock.json b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/ICompoundTimelock.json similarity index 100% rename from dependencies/@openzeppelin-contracts-5.5.0/build/contracts/ICompoundTimelock.json rename to dependencies/@openzeppelin-contracts-5.7.0/build/contracts/ICompoundTimelock.json diff --git a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/IERC1155.json b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/IERC1155.json similarity index 100% rename from dependencies/@openzeppelin-contracts-5.5.0/build/contracts/IERC1155.json rename to dependencies/@openzeppelin-contracts-5.7.0/build/contracts/IERC1155.json diff --git a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/IERC1155Errors.json b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/IERC1155Errors.json similarity index 100% rename from dependencies/@openzeppelin-contracts-5.5.0/build/contracts/IERC1155Errors.json rename to dependencies/@openzeppelin-contracts-5.7.0/build/contracts/IERC1155Errors.json diff --git a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/IERC1155MetadataURI.json b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/IERC1155MetadataURI.json similarity index 100% rename from dependencies/@openzeppelin-contracts-5.5.0/build/contracts/IERC1155MetadataURI.json rename to dependencies/@openzeppelin-contracts-5.7.0/build/contracts/IERC1155MetadataURI.json diff --git a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/IERC1155Receiver.json b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/IERC1155Receiver.json similarity index 100% rename from dependencies/@openzeppelin-contracts-5.5.0/build/contracts/IERC1155Receiver.json rename to dependencies/@openzeppelin-contracts-5.7.0/build/contracts/IERC1155Receiver.json diff --git a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/IERC1271.json b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/IERC1271.json similarity index 100% rename from dependencies/@openzeppelin-contracts-5.5.0/build/contracts/IERC1271.json rename to dependencies/@openzeppelin-contracts-5.7.0/build/contracts/IERC1271.json diff --git a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/IERC1363.json b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/IERC1363.json similarity index 100% rename from dependencies/@openzeppelin-contracts-5.5.0/build/contracts/IERC1363.json rename to dependencies/@openzeppelin-contracts-5.7.0/build/contracts/IERC1363.json diff --git a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/IERC1363Receiver.json b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/IERC1363Receiver.json similarity index 100% rename from dependencies/@openzeppelin-contracts-5.5.0/build/contracts/IERC1363Receiver.json rename to dependencies/@openzeppelin-contracts-5.7.0/build/contracts/IERC1363Receiver.json diff --git a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/IERC1363Spender.json b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/IERC1363Spender.json similarity index 100% rename from dependencies/@openzeppelin-contracts-5.5.0/build/contracts/IERC1363Spender.json rename to dependencies/@openzeppelin-contracts-5.7.0/build/contracts/IERC1363Spender.json diff --git a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/IERC165.json b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/IERC165.json similarity index 100% rename from dependencies/@openzeppelin-contracts-5.5.0/build/contracts/IERC165.json rename to dependencies/@openzeppelin-contracts-5.7.0/build/contracts/IERC165.json diff --git a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/IERC1820Implementer.json b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/IERC1820Implementer.json similarity index 100% rename from dependencies/@openzeppelin-contracts-5.5.0/build/contracts/IERC1820Implementer.json rename to dependencies/@openzeppelin-contracts-5.7.0/build/contracts/IERC1820Implementer.json diff --git a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/IERC1820Registry.json b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/IERC1820Registry.json similarity index 100% rename from dependencies/@openzeppelin-contracts-5.5.0/build/contracts/IERC1820Registry.json rename to dependencies/@openzeppelin-contracts-5.7.0/build/contracts/IERC1820Registry.json diff --git a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/IERC1822Proxiable.json b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/IERC1822Proxiable.json similarity index 100% rename from dependencies/@openzeppelin-contracts-5.5.0/build/contracts/IERC1822Proxiable.json rename to dependencies/@openzeppelin-contracts-5.7.0/build/contracts/IERC1822Proxiable.json diff --git a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/IERC1967.json b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/IERC1967.json similarity index 100% rename from dependencies/@openzeppelin-contracts-5.5.0/build/contracts/IERC1967.json rename to dependencies/@openzeppelin-contracts-5.7.0/build/contracts/IERC1967.json diff --git a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/IERC20.json b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/IERC20.json similarity index 100% rename from dependencies/@openzeppelin-contracts-5.5.0/build/contracts/IERC20.json rename to dependencies/@openzeppelin-contracts-5.7.0/build/contracts/IERC20.json diff --git a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/IERC20Errors.json b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/IERC20Errors.json similarity index 100% rename from dependencies/@openzeppelin-contracts-5.5.0/build/contracts/IERC20Errors.json rename to dependencies/@openzeppelin-contracts-5.7.0/build/contracts/IERC20Errors.json diff --git a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/IERC20Metadata.json b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/IERC20Metadata.json similarity index 100% rename from dependencies/@openzeppelin-contracts-5.5.0/build/contracts/IERC20Metadata.json rename to dependencies/@openzeppelin-contracts-5.7.0/build/contracts/IERC20Metadata.json diff --git a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/IERC20Permit.json b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/IERC20Permit.json similarity index 100% rename from dependencies/@openzeppelin-contracts-5.5.0/build/contracts/IERC20Permit.json rename to dependencies/@openzeppelin-contracts-5.7.0/build/contracts/IERC20Permit.json diff --git a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/IERC2309.json b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/IERC2309.json similarity index 100% rename from dependencies/@openzeppelin-contracts-5.5.0/build/contracts/IERC2309.json rename to dependencies/@openzeppelin-contracts-5.7.0/build/contracts/IERC2309.json diff --git a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/IERC2612.json b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/IERC2612.json similarity index 100% rename from dependencies/@openzeppelin-contracts-5.5.0/build/contracts/IERC2612.json rename to dependencies/@openzeppelin-contracts-5.7.0/build/contracts/IERC2612.json diff --git a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/IERC2981.json b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/IERC2981.json similarity index 100% rename from dependencies/@openzeppelin-contracts-5.5.0/build/contracts/IERC2981.json rename to dependencies/@openzeppelin-contracts-5.7.0/build/contracts/IERC2981.json diff --git a/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/IERC3009.json b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/IERC3009.json new file mode 100644 index 0000000..01b2325 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/IERC3009.json @@ -0,0 +1,160 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "IERC3009", + "sourceName": "contracts/interfaces/draft-IERC3009.sol", + "abi": [ + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "authorizer", + "type": "address" + }, + { + "indexed": true, + "internalType": "bytes32", + "name": "nonce", + "type": "bytes32" + } + ], + "name": "AuthorizationUsed", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "authorizer", + "type": "address" + }, + { + "internalType": "bytes32", + "name": "nonce", + "type": "bytes32" + } + ], + "name": "authorizationState", + "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": "value", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "validAfter", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "validBefore", + "type": "uint256" + }, + { + "internalType": "bytes32", + "name": "nonce", + "type": "bytes32" + }, + { + "internalType": "uint8", + "name": "v", + "type": "uint8" + }, + { + "internalType": "bytes32", + "name": "r", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "s", + "type": "bytes32" + } + ], + "name": "receiveWithAuthorization", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "validAfter", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "validBefore", + "type": "uint256" + }, + { + "internalType": "bytes32", + "name": "nonce", + "type": "bytes32" + }, + { + "internalType": "uint8", + "name": "v", + "type": "uint8" + }, + { + "internalType": "bytes32", + "name": "r", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "s", + "type": "bytes32" + } + ], + "name": "transferWithAuthorization", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } + ], + "bytecode": "0x", + "deployedBytecode": "0x", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/IERC3009Cancel.json b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/IERC3009Cancel.json new file mode 100644 index 0000000..f1a5e58 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/IERC3009Cancel.json @@ -0,0 +1,63 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "IERC3009Cancel", + "sourceName": "contracts/interfaces/draft-IERC3009.sol", + "abi": [ + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "authorizer", + "type": "address" + }, + { + "indexed": true, + "internalType": "bytes32", + "name": "nonce", + "type": "bytes32" + } + ], + "name": "AuthorizationCanceled", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "authorizer", + "type": "address" + }, + { + "internalType": "bytes32", + "name": "nonce", + "type": "bytes32" + }, + { + "internalType": "uint8", + "name": "v", + "type": "uint8" + }, + { + "internalType": "bytes32", + "name": "r", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "s", + "type": "bytes32" + } + ], + "name": "cancelAuthorization", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } + ], + "bytecode": "0x", + "deployedBytecode": "0x", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/IERC3156FlashBorrower.json b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/IERC3156FlashBorrower.json similarity index 100% rename from dependencies/@openzeppelin-contracts-5.5.0/build/contracts/IERC3156FlashBorrower.json rename to dependencies/@openzeppelin-contracts-5.7.0/build/contracts/IERC3156FlashBorrower.json diff --git a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/IERC3156FlashLender.json b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/IERC3156FlashLender.json similarity index 100% rename from dependencies/@openzeppelin-contracts-5.5.0/build/contracts/IERC3156FlashLender.json rename to dependencies/@openzeppelin-contracts-5.7.0/build/contracts/IERC3156FlashLender.json diff --git a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/IERC4626.json b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/IERC4626.json similarity index 100% rename from dependencies/@openzeppelin-contracts-5.5.0/build/contracts/IERC4626.json rename to dependencies/@openzeppelin-contracts-5.7.0/build/contracts/IERC4626.json diff --git a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/IERC4906.json b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/IERC4906.json similarity index 100% rename from dependencies/@openzeppelin-contracts-5.5.0/build/contracts/IERC4906.json rename to dependencies/@openzeppelin-contracts-5.7.0/build/contracts/IERC4906.json diff --git a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/IERC5267.json b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/IERC5267.json similarity index 100% rename from dependencies/@openzeppelin-contracts-5.5.0/build/contracts/IERC5267.json rename to dependencies/@openzeppelin-contracts-5.7.0/build/contracts/IERC5267.json diff --git a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/IERC5313.json b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/IERC5313.json similarity index 100% rename from dependencies/@openzeppelin-contracts-5.5.0/build/contracts/IERC5313.json rename to dependencies/@openzeppelin-contracts-5.7.0/build/contracts/IERC5313.json diff --git a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/IERC5805.json b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/IERC5805.json similarity index 100% rename from dependencies/@openzeppelin-contracts-5.5.0/build/contracts/IERC5805.json rename to dependencies/@openzeppelin-contracts-5.7.0/build/contracts/IERC5805.json diff --git a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/IERC6372.json b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/IERC6372.json similarity index 100% rename from dependencies/@openzeppelin-contracts-5.5.0/build/contracts/IERC6372.json rename to dependencies/@openzeppelin-contracts-5.7.0/build/contracts/IERC6372.json diff --git a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/IERC6909.json b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/IERC6909.json similarity index 100% rename from dependencies/@openzeppelin-contracts-5.5.0/build/contracts/IERC6909.json rename to dependencies/@openzeppelin-contracts-5.7.0/build/contracts/IERC6909.json diff --git a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/IERC6909ContentURI.json b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/IERC6909ContentURI.json similarity index 100% rename from dependencies/@openzeppelin-contracts-5.5.0/build/contracts/IERC6909ContentURI.json rename to dependencies/@openzeppelin-contracts-5.7.0/build/contracts/IERC6909ContentURI.json diff --git a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/IERC6909Metadata.json b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/IERC6909Metadata.json similarity index 100% rename from dependencies/@openzeppelin-contracts-5.5.0/build/contracts/IERC6909Metadata.json rename to dependencies/@openzeppelin-contracts-5.7.0/build/contracts/IERC6909Metadata.json diff --git a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/IERC6909TokenSupply.json b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/IERC6909TokenSupply.json similarity index 100% rename from dependencies/@openzeppelin-contracts-5.5.0/build/contracts/IERC6909TokenSupply.json rename to dependencies/@openzeppelin-contracts-5.7.0/build/contracts/IERC6909TokenSupply.json diff --git a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/IERC721.json b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/IERC721.json similarity index 100% rename from dependencies/@openzeppelin-contracts-5.5.0/build/contracts/IERC721.json rename to dependencies/@openzeppelin-contracts-5.7.0/build/contracts/IERC721.json diff --git a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/IERC721Enumerable.json b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/IERC721Enumerable.json similarity index 100% rename from dependencies/@openzeppelin-contracts-5.5.0/build/contracts/IERC721Enumerable.json rename to dependencies/@openzeppelin-contracts-5.7.0/build/contracts/IERC721Enumerable.json diff --git a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/IERC721Errors.json b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/IERC721Errors.json similarity index 100% rename from dependencies/@openzeppelin-contracts-5.5.0/build/contracts/IERC721Errors.json rename to dependencies/@openzeppelin-contracts-5.7.0/build/contracts/IERC721Errors.json diff --git a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/IERC721Metadata.json b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/IERC721Metadata.json similarity index 100% rename from dependencies/@openzeppelin-contracts-5.5.0/build/contracts/IERC721Metadata.json rename to dependencies/@openzeppelin-contracts-5.7.0/build/contracts/IERC721Metadata.json diff --git a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/IERC721Receiver.json b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/IERC721Receiver.json similarity index 100% rename from dependencies/@openzeppelin-contracts-5.5.0/build/contracts/IERC721Receiver.json rename to dependencies/@openzeppelin-contracts-5.7.0/build/contracts/IERC721Receiver.json diff --git a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/IERC7579AccountConfig.json b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/IERC7579AccountConfig.json similarity index 100% rename from dependencies/@openzeppelin-contracts-5.5.0/build/contracts/IERC7579AccountConfig.json rename to dependencies/@openzeppelin-contracts-5.7.0/build/contracts/IERC7579AccountConfig.json diff --git a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/IERC7579Execution.json b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/IERC7579Execution.json similarity index 100% rename from dependencies/@openzeppelin-contracts-5.5.0/build/contracts/IERC7579Execution.json rename to dependencies/@openzeppelin-contracts-5.7.0/build/contracts/IERC7579Execution.json diff --git a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/IERC7579Hook.json b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/IERC7579Hook.json similarity index 100% rename from dependencies/@openzeppelin-contracts-5.5.0/build/contracts/IERC7579Hook.json rename to dependencies/@openzeppelin-contracts-5.7.0/build/contracts/IERC7579Hook.json diff --git a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/IERC7579Module.json b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/IERC7579Module.json similarity index 100% rename from dependencies/@openzeppelin-contracts-5.5.0/build/contracts/IERC7579Module.json rename to dependencies/@openzeppelin-contracts-5.7.0/build/contracts/IERC7579Module.json diff --git a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/IERC7579ModuleConfig.json b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/IERC7579ModuleConfig.json similarity index 100% rename from dependencies/@openzeppelin-contracts-5.5.0/build/contracts/IERC7579ModuleConfig.json rename to dependencies/@openzeppelin-contracts-5.7.0/build/contracts/IERC7579ModuleConfig.json diff --git a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/IERC7579Validator.json b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/IERC7579Validator.json similarity index 100% rename from dependencies/@openzeppelin-contracts-5.5.0/build/contracts/IERC7579Validator.json rename to dependencies/@openzeppelin-contracts-5.7.0/build/contracts/IERC7579Validator.json diff --git a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/IERC7674.json b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/IERC7674.json similarity index 100% rename from dependencies/@openzeppelin-contracts-5.5.0/build/contracts/IERC7674.json rename to dependencies/@openzeppelin-contracts-5.7.0/build/contracts/IERC7674.json diff --git a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/IERC7751.json b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/IERC7751.json similarity index 100% rename from dependencies/@openzeppelin-contracts-5.5.0/build/contracts/IERC7751.json rename to dependencies/@openzeppelin-contracts-5.7.0/build/contracts/IERC7751.json diff --git a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/IERC777.json b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/IERC777.json similarity index 100% rename from dependencies/@openzeppelin-contracts-5.5.0/build/contracts/IERC777.json rename to dependencies/@openzeppelin-contracts-5.7.0/build/contracts/IERC777.json diff --git a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/IERC777Recipient.json b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/IERC777Recipient.json similarity index 100% rename from dependencies/@openzeppelin-contracts-5.5.0/build/contracts/IERC777Recipient.json rename to dependencies/@openzeppelin-contracts-5.7.0/build/contracts/IERC777Recipient.json diff --git a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/IERC777Sender.json b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/IERC777Sender.json similarity index 100% rename from dependencies/@openzeppelin-contracts-5.5.0/build/contracts/IERC777Sender.json rename to dependencies/@openzeppelin-contracts-5.7.0/build/contracts/IERC777Sender.json diff --git a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/IERC7786GatewaySource.json b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/IERC7786GatewaySource.json similarity index 100% rename from dependencies/@openzeppelin-contracts-5.5.0/build/contracts/IERC7786GatewaySource.json rename to dependencies/@openzeppelin-contracts-5.7.0/build/contracts/IERC7786GatewaySource.json diff --git a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/IERC7786Recipient.json b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/IERC7786Recipient.json similarity index 100% rename from dependencies/@openzeppelin-contracts-5.5.0/build/contracts/IERC7786Recipient.json rename to dependencies/@openzeppelin-contracts-5.7.0/build/contracts/IERC7786Recipient.json diff --git a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/IERC7802.json b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/IERC7802.json similarity index 100% rename from dependencies/@openzeppelin-contracts-5.5.0/build/contracts/IERC7802.json rename to dependencies/@openzeppelin-contracts-5.7.0/build/contracts/IERC7802.json diff --git a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/IERC7821.json b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/IERC7821.json similarity index 100% rename from dependencies/@openzeppelin-contracts-5.5.0/build/contracts/IERC7821.json rename to dependencies/@openzeppelin-contracts-5.7.0/build/contracts/IERC7821.json diff --git a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/IERC7913SignatureVerifier.json b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/IERC7913SignatureVerifier.json similarity index 100% rename from dependencies/@openzeppelin-contracts-5.5.0/build/contracts/IERC7913SignatureVerifier.json rename to dependencies/@openzeppelin-contracts-5.7.0/build/contracts/IERC7913SignatureVerifier.json diff --git a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/IEntryPoint.json b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/IEntryPoint.json similarity index 99% rename from dependencies/@openzeppelin-contracts-5.5.0/build/contracts/IEntryPoint.json rename to dependencies/@openzeppelin-contracts-5.7.0/build/contracts/IEntryPoint.json index 4842a20..8a249e3 100644 --- a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/IEntryPoint.json +++ b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/IEntryPoint.json @@ -1,7 +1,7 @@ { "_format": "hh-sol-artifact-1", "contractName": "IEntryPoint", - "sourceName": "contracts/interfaces/draft-IERC4337.sol", + "sourceName": "contracts/interfaces/IERC4337.sol", "abi": [ { "inputs": [ diff --git a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/IEntryPointExtra.json b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/IEntryPointExtra.json similarity index 96% rename from dependencies/@openzeppelin-contracts-5.5.0/build/contracts/IEntryPointExtra.json rename to dependencies/@openzeppelin-contracts-5.7.0/build/contracts/IEntryPointExtra.json index 82b273c..b3a7445 100644 --- a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/IEntryPointExtra.json +++ b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/IEntryPointExtra.json @@ -1,7 +1,7 @@ { "_format": "hh-sol-artifact-1", "contractName": "IEntryPointExtra", - "sourceName": "contracts/account/utils/draft-ERC4337Utils.sol", + "sourceName": "contracts/account/utils/ERC4337Utils.sol", "abi": [ { "inputs": [ diff --git a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/IEntryPointNonces.json b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/IEntryPointNonces.json similarity index 92% rename from dependencies/@openzeppelin-contracts-5.5.0/build/contracts/IEntryPointNonces.json rename to dependencies/@openzeppelin-contracts-5.7.0/build/contracts/IEntryPointNonces.json index 6a95c7e..503d999 100644 --- a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/IEntryPointNonces.json +++ b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/IEntryPointNonces.json @@ -1,7 +1,7 @@ { "_format": "hh-sol-artifact-1", "contractName": "IEntryPointNonces", - "sourceName": "contracts/interfaces/draft-IERC4337.sol", + "sourceName": "contracts/interfaces/IERC4337.sol", "abi": [ { "inputs": [ diff --git a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/IEntryPointStake.json b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/IEntryPointStake.json similarity index 97% rename from dependencies/@openzeppelin-contracts-5.5.0/build/contracts/IEntryPointStake.json rename to dependencies/@openzeppelin-contracts-5.7.0/build/contracts/IEntryPointStake.json index 13b3cdb..6e3b172 100644 --- a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/IEntryPointStake.json +++ b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/IEntryPointStake.json @@ -1,7 +1,7 @@ { "_format": "hh-sol-artifact-1", "contractName": "IEntryPointStake", - "sourceName": "contracts/interfaces/draft-IERC4337.sol", + "sourceName": "contracts/interfaces/IERC4337.sol", "abi": [ { "inputs": [ diff --git a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/IGovernor.json b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/IGovernor.json similarity index 98% rename from dependencies/@openzeppelin-contracts-5.5.0/build/contracts/IGovernor.json rename to dependencies/@openzeppelin-contracts-5.7.0/build/contracts/IGovernor.json index 2cb3978..d0d6e42 100644 --- a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/IGovernor.json +++ b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/IGovernor.json @@ -118,28 +118,34 @@ { "inputs": [ { - "internalType": "uint256", - "name": "proposalId", - "type": "uint256" + "internalType": "address", + "name": "account", + "type": "address" } ], - "name": "GovernorNotQueuedProposal", + "name": "GovernorOnlyExecutor", "type": "error" }, { "inputs": [ { - "internalType": "address", - "name": "account", - "type": "address" + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" } ], - "name": "GovernorOnlyExecutor", + "name": "GovernorProposalQueueingFailed", "type": "error" }, { - "inputs": [], - "name": "GovernorQueueNotImplemented", + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + } + ], + "name": "GovernorProposalQueueingNotRequired", "type": "error" }, { diff --git a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/IPaymaster.json b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/IPaymaster.json similarity index 97% rename from dependencies/@openzeppelin-contracts-5.5.0/build/contracts/IPaymaster.json rename to dependencies/@openzeppelin-contracts-5.7.0/build/contracts/IPaymaster.json index b3d046c..5dade85 100644 --- a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/IPaymaster.json +++ b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/IPaymaster.json @@ -1,7 +1,7 @@ { "_format": "hh-sol-artifact-1", "contractName": "IPaymaster", - "sourceName": "contracts/interfaces/draft-IERC4337.sol", + "sourceName": "contracts/interfaces/IERC4337.sol", "abi": [ { "inputs": [ diff --git a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/ITransparentUpgradeableProxy.json b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/ITransparentUpgradeableProxy.json similarity index 100% rename from dependencies/@openzeppelin-contracts-5.5.0/build/contracts/ITransparentUpgradeableProxy.json rename to dependencies/@openzeppelin-contracts-5.7.0/build/contracts/ITransparentUpgradeableProxy.json diff --git a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/IVotes.json b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/IVotes.json similarity index 100% rename from dependencies/@openzeppelin-contracts-5.5.0/build/contracts/IVotes.json rename to dependencies/@openzeppelin-contracts-5.7.0/build/contracts/IVotes.json diff --git a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/Initializable.json b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/Initializable.json similarity index 100% rename from dependencies/@openzeppelin-contracts-5.5.0/build/contracts/Initializable.json rename to dependencies/@openzeppelin-contracts-5.7.0/build/contracts/Initializable.json diff --git a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/InteroperableAddress.json b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/InteroperableAddress.json similarity index 78% rename from dependencies/@openzeppelin-contracts-5.5.0/build/contracts/InteroperableAddress.json rename to dependencies/@openzeppelin-contracts-5.7.0/build/contracts/InteroperableAddress.json index e9e4167..dca4550 100644 --- a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/InteroperableAddress.json +++ b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/InteroperableAddress.json @@ -20,8 +20,8 @@ "type": "error" } ], - "bytecode": "0x60556032600b8282823980515f1a607314602657634e487b7160e01b5f525f60045260245ffd5b305f52607381538281f3fe730000000000000000000000000000000000000000301460806040525f5ffdfea2646970667358221220e0ea2c9e69a2e9ae74e30fd61f6d00568ab96e96800611f692ac089ff02f3aaf64736f6c634300081b0033", - "deployedBytecode": "0x730000000000000000000000000000000000000000301460806040525f5ffdfea2646970667358221220e0ea2c9e69a2e9ae74e30fd61f6d00568ab96e96800611f692ac089ff02f3aaf64736f6c634300081b0033", + "bytecode": "0x60556032600b8282823980515f1a607314602657634e487b7160e01b5f525f60045260245ffd5b305f52607381538281f3fe730000000000000000000000000000000000000000301460806040525f5ffdfea26469706673582212209623ede1e43af67d8604aece632dd25ef1cec1761763a691fce26ca436fa556c64736f6c63430008230033", + "deployedBytecode": "0x730000000000000000000000000000000000000000301460806040525f5ffdfea26469706673582212209623ede1e43af67d8604aece632dd25ef1cec1761763a691fce26ca436fa556c64736f6c63430008230033", "linkReferences": {}, "deployedLinkReferences": {} } diff --git a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/LowLevelCall.json b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/LowLevelCall.json similarity index 66% rename from dependencies/@openzeppelin-contracts-5.5.0/build/contracts/LowLevelCall.json rename to dependencies/@openzeppelin-contracts-5.7.0/build/contracts/LowLevelCall.json index 07896a3..7dd2c08 100644 --- a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/LowLevelCall.json +++ b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/LowLevelCall.json @@ -3,8 +3,8 @@ "contractName": "LowLevelCall", "sourceName": "contracts/utils/LowLevelCall.sol", "abi": [], - "bytecode": "0x60556032600b8282823980515f1a607314602657634e487b7160e01b5f525f60045260245ffd5b305f52607381538281f3fe730000000000000000000000000000000000000000301460806040525f5ffdfea2646970667358221220ce14c1b8fa9ef8e044e2bca49830152348a55df8a23ed5ef19bad4d62c58afc464736f6c634300081b0033", - "deployedBytecode": "0x730000000000000000000000000000000000000000301460806040525f5ffdfea2646970667358221220ce14c1b8fa9ef8e044e2bca49830152348a55df8a23ed5ef19bad4d62c58afc464736f6c634300081b0033", + "bytecode": "0x60556032600b8282823980515f1a607314602657634e487b7160e01b5f525f60045260245ffd5b305f52607381538281f3fe730000000000000000000000000000000000000000301460806040525f5ffdfea2646970667358221220a7167b6827f1b454312a1bca54af200e9f35977627c9f639f869c924ec2b8e0464736f6c63430008230033", + "deployedBytecode": "0x730000000000000000000000000000000000000000301460806040525f5ffdfea2646970667358221220a7167b6827f1b454312a1bca54af200e9f35977627c9f639f869c924ec2b8e0464736f6c63430008230033", "linkReferences": {}, "deployedLinkReferences": {} } diff --git a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/Math.json b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/Math.json similarity index 66% rename from dependencies/@openzeppelin-contracts-5.5.0/build/contracts/Math.json rename to dependencies/@openzeppelin-contracts-5.7.0/build/contracts/Math.json index 6152ed8..5bd73c5 100644 --- a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/Math.json +++ b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/Math.json @@ -3,8 +3,8 @@ "contractName": "Math", "sourceName": "contracts/utils/math/Math.sol", "abi": [], - "bytecode": "0x60556032600b8282823980515f1a607314602657634e487b7160e01b5f525f60045260245ffd5b305f52607381538281f3fe730000000000000000000000000000000000000000301460806040525f5ffdfea26469706673582212200d6fb6da637b36e3d11a31f1fe07d405ec6a84ff22eb5e2a7c636febecdd926b64736f6c634300081b0033", - "deployedBytecode": "0x730000000000000000000000000000000000000000301460806040525f5ffdfea26469706673582212200d6fb6da637b36e3d11a31f1fe07d405ec6a84ff22eb5e2a7c636febecdd926b64736f6c634300081b0033", + "bytecode": "0x60556032600b8282823980515f1a607314602657634e487b7160e01b5f525f60045260245ffd5b305f52607381538281f3fe730000000000000000000000000000000000000000301460806040525f5ffdfea26469706673582212204adecaa4fb9f3fbd3b640c274cfa9a45d5ecb382ea985a661657b3b8b251c46064736f6c63430008230033", + "deployedBytecode": "0x730000000000000000000000000000000000000000301460806040525f5ffdfea26469706673582212204adecaa4fb9f3fbd3b640c274cfa9a45d5ecb382ea985a661657b3b8b251c46064736f6c63430008230033", "linkReferences": {}, "deployedLinkReferences": {} } diff --git a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/Memory.json b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/Memory.json similarity index 66% rename from dependencies/@openzeppelin-contracts-5.5.0/build/contracts/Memory.json rename to dependencies/@openzeppelin-contracts-5.7.0/build/contracts/Memory.json index 8f65721..63cd5f0 100644 --- a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/Memory.json +++ b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/Memory.json @@ -3,8 +3,8 @@ "contractName": "Memory", "sourceName": "contracts/utils/Memory.sol", "abi": [], - "bytecode": "0x60556032600b8282823980515f1a607314602657634e487b7160e01b5f525f60045260245ffd5b305f52607381538281f3fe730000000000000000000000000000000000000000301460806040525f5ffdfea2646970667358221220b5d4d7575db220704f1c9d89d9b6295886b2acb402d8b520a6dddb4d595baf3564736f6c634300081b0033", - "deployedBytecode": "0x730000000000000000000000000000000000000000301460806040525f5ffdfea2646970667358221220b5d4d7575db220704f1c9d89d9b6295886b2acb402d8b520a6dddb4d595baf3564736f6c634300081b0033", + "bytecode": "0x60556032600b8282823980515f1a607314602657634e487b7160e01b5f525f60045260245ffd5b305f52607381538281f3fe730000000000000000000000000000000000000000301460806040525f5ffdfea2646970667358221220957689d6aa9c640273de8a8bd7ac55b83b89768cced5f67f5bb9b1f84824432e64736f6c63430008230033", + "deployedBytecode": "0x730000000000000000000000000000000000000000301460806040525f5ffdfea2646970667358221220957689d6aa9c640273de8a8bd7ac55b83b89768cced5f67f5bb9b1f84824432e64736f6c63430008230033", "linkReferences": {}, "deployedLinkReferences": {} } diff --git a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/MerkleProof.json b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/MerkleProof.json similarity index 71% rename from dependencies/@openzeppelin-contracts-5.5.0/build/contracts/MerkleProof.json rename to dependencies/@openzeppelin-contracts-5.7.0/build/contracts/MerkleProof.json index 1c4fcdc..ce2f8a0 100644 --- a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/MerkleProof.json +++ b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/MerkleProof.json @@ -9,8 +9,8 @@ "type": "error" } ], - "bytecode": "0x60556032600b8282823980515f1a607314602657634e487b7160e01b5f525f60045260245ffd5b305f52607381538281f3fe730000000000000000000000000000000000000000301460806040525f5ffdfea2646970667358221220d1ce122d98b28b2410080eca30b264cbc114fab9c6cbad1353fd110c499357e464736f6c634300081b0033", - "deployedBytecode": "0x730000000000000000000000000000000000000000301460806040525f5ffdfea2646970667358221220d1ce122d98b28b2410080eca30b264cbc114fab9c6cbad1353fd110c499357e464736f6c634300081b0033", + "bytecode": "0x60556032600b8282823980515f1a607314602657634e487b7160e01b5f525f60045260245ffd5b305f52607381538281f3fe730000000000000000000000000000000000000000301460806040525f5ffdfea26469706673582212209bc174349cce4be9e2b4423b8c86c3284fe01c4f6fbad9863538a7158a520e6f64736f6c63430008230033", + "deployedBytecode": "0x730000000000000000000000000000000000000000301460806040525f5ffdfea26469706673582212209bc174349cce4be9e2b4423b8c86c3284fe01c4f6fbad9863538a7158a520e6f64736f6c63430008230033", "linkReferences": {}, "deployedLinkReferences": {} } diff --git a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/MerkleTree.json b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/MerkleTree.json similarity index 79% rename from dependencies/@openzeppelin-contracts-5.5.0/build/contracts/MerkleTree.json rename to dependencies/@openzeppelin-contracts-5.7.0/build/contracts/MerkleTree.json index 25cde3e..284fd7b 100644 --- a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/MerkleTree.json +++ b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/MerkleTree.json @@ -25,8 +25,8 @@ "type": "error" } ], - "bytecode": "0x60556032600b8282823980515f1a607314602657634e487b7160e01b5f525f60045260245ffd5b305f52607381538281f3fe730000000000000000000000000000000000000000301460806040525f5ffdfea2646970667358221220152d0cbf141f54416bea4d89c1500cc69ae61d9a87ed1e74f194d76f2ec58c6c64736f6c634300081b0033", - "deployedBytecode": "0x730000000000000000000000000000000000000000301460806040525f5ffdfea2646970667358221220152d0cbf141f54416bea4d89c1500cc69ae61d9a87ed1e74f194d76f2ec58c6c64736f6c634300081b0033", + "bytecode": "0x60556032600b8282823980515f1a607314602657634e487b7160e01b5f525f60045260245ffd5b305f52607381538281f3fe730000000000000000000000000000000000000000301460806040525f5ffdfea26469706673582212209f9b632c1ea2669e639966bfa29f7da08aed6b2fe03a28a43351884a8a549ece64736f6c63430008230033", + "deployedBytecode": "0x730000000000000000000000000000000000000000301460806040525f5ffdfea26469706673582212209f9b632c1ea2669e639966bfa29f7da08aed6b2fe03a28a43351884a8a549ece64736f6c63430008230033", "linkReferences": {}, "deployedLinkReferences": {} } diff --git a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/MessageHashUtils.json b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/MessageHashUtils.json similarity index 57% rename from dependencies/@openzeppelin-contracts-5.5.0/build/contracts/MessageHashUtils.json rename to dependencies/@openzeppelin-contracts-5.7.0/build/contracts/MessageHashUtils.json index 6fe2a80..e975b71 100644 --- a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/MessageHashUtils.json +++ b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/MessageHashUtils.json @@ -2,9 +2,15 @@ "_format": "hh-sol-artifact-1", "contractName": "MessageHashUtils", "sourceName": "contracts/utils/cryptography/MessageHashUtils.sol", - "abi": [], - "bytecode": "0x60556032600b8282823980515f1a607314602657634e487b7160e01b5f525f60045260245ffd5b305f52607381538281f3fe730000000000000000000000000000000000000000301460806040525f5ffdfea264697066735822122099a4cce95972d17bdb9fcb901e864b4ac1492a5db7ed99fc93ed7540940f074464736f6c634300081b0033", - "deployedBytecode": "0x730000000000000000000000000000000000000000301460806040525f5ffdfea264697066735822122099a4cce95972d17bdb9fcb901e864b4ac1492a5db7ed99fc93ed7540940f074464736f6c634300081b0033", + "abi": [ + { + "inputs": [], + "name": "ERC5267ExtensionsNotSupported", + "type": "error" + } + ], + "bytecode": "0x60556032600b8282823980515f1a607314602657634e487b7160e01b5f525f60045260245ffd5b305f52607381538281f3fe730000000000000000000000000000000000000000301460806040525f5ffdfea2646970667358221220d2f5365b54d18c9d0085fadd8326a13068a66c1bb2512104351e13c0223bad2e64736f6c63430008230033", + "deployedBytecode": "0x730000000000000000000000000000000000000000301460806040525f5ffdfea2646970667358221220d2f5365b54d18c9d0085fadd8326a13068a66c1bb2512104351e13c0223bad2e64736f6c63430008230033", "linkReferences": {}, "deployedLinkReferences": {} } diff --git a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/MultiSignerERC7913.json b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/MultiSignerERC7913.json similarity index 100% rename from dependencies/@openzeppelin-contracts-5.5.0/build/contracts/MultiSignerERC7913.json rename to dependencies/@openzeppelin-contracts-5.7.0/build/contracts/MultiSignerERC7913.json diff --git a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/MultiSignerERC7913Weighted.json b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/MultiSignerERC7913Weighted.json similarity index 100% rename from dependencies/@openzeppelin-contracts-5.5.0/build/contracts/MultiSignerERC7913Weighted.json rename to dependencies/@openzeppelin-contracts-5.7.0/build/contracts/MultiSignerERC7913Weighted.json diff --git a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/Multicall.json b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/Multicall.json similarity index 100% rename from dependencies/@openzeppelin-contracts-5.5.0/build/contracts/Multicall.json rename to dependencies/@openzeppelin-contracts-5.7.0/build/contracts/Multicall.json diff --git a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/Nonces.json b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/Nonces.json similarity index 100% rename from dependencies/@openzeppelin-contracts-5.5.0/build/contracts/Nonces.json rename to dependencies/@openzeppelin-contracts-5.7.0/build/contracts/Nonces.json diff --git a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/NoncesKeyed.json b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/NoncesKeyed.json similarity index 100% rename from dependencies/@openzeppelin-contracts-5.5.0/build/contracts/NoncesKeyed.json rename to dependencies/@openzeppelin-contracts-5.7.0/build/contracts/NoncesKeyed.json diff --git a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/Ownable.json b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/Ownable.json similarity index 100% rename from dependencies/@openzeppelin-contracts-5.5.0/build/contracts/Ownable.json rename to dependencies/@openzeppelin-contracts-5.7.0/build/contracts/Ownable.json diff --git a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/Ownable2Step.json b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/Ownable2Step.json similarity index 100% rename from dependencies/@openzeppelin-contracts-5.5.0/build/contracts/Ownable2Step.json rename to dependencies/@openzeppelin-contracts-5.7.0/build/contracts/Ownable2Step.json diff --git a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/P256.json b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/P256.json similarity index 66% rename from dependencies/@openzeppelin-contracts-5.5.0/build/contracts/P256.json rename to dependencies/@openzeppelin-contracts-5.7.0/build/contracts/P256.json index 5b264e7..1702b7f 100644 --- a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/P256.json +++ b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/P256.json @@ -3,8 +3,8 @@ "contractName": "P256", "sourceName": "contracts/utils/cryptography/P256.sol", "abi": [], - "bytecode": "0x60556032600b8282823980515f1a607314602657634e487b7160e01b5f525f60045260245ffd5b305f52607381538281f3fe730000000000000000000000000000000000000000301460806040525f5ffdfea2646970667358221220c45b8765745204fa8b52995cfca199a09e0b17ac77520f3166b0301bb3bcb8a064736f6c634300081b0033", - "deployedBytecode": "0x730000000000000000000000000000000000000000301460806040525f5ffdfea2646970667358221220c45b8765745204fa8b52995cfca199a09e0b17ac77520f3166b0301bb3bcb8a064736f6c634300081b0033", + "bytecode": "0x60556032600b8282823980515f1a607314602657634e487b7160e01b5f525f60045260245ffd5b305f52607381538281f3fe730000000000000000000000000000000000000000301460806040525f5ffdfea2646970667358221220c0448af4f4c4aa0e7f756c62179d50a51635336da24f6d8129d42edb41baff3664736f6c63430008230033", + "deployedBytecode": "0x730000000000000000000000000000000000000000301460806040525f5ffdfea2646970667358221220c0448af4f4c4aa0e7f756c62179d50a51635336da24f6d8129d42edb41baff3664736f6c63430008230033", "linkReferences": {}, "deployedLinkReferences": {} } diff --git a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/Packing.json b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/Packing.json similarity index 70% rename from dependencies/@openzeppelin-contracts-5.5.0/build/contracts/Packing.json rename to dependencies/@openzeppelin-contracts-5.7.0/build/contracts/Packing.json index be73c61..bd9cee2 100644 --- a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/Packing.json +++ b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/Packing.json @@ -9,8 +9,8 @@ "type": "error" } ], - "bytecode": "0x60556032600b8282823980515f1a607314602657634e487b7160e01b5f525f60045260245ffd5b305f52607381538281f3fe730000000000000000000000000000000000000000301460806040525f5ffdfea2646970667358221220e62db5a2cc2140c16fc51476401f061d88202cb8c699e83d8ae5391e545b318064736f6c634300081b0033", - "deployedBytecode": "0x730000000000000000000000000000000000000000301460806040525f5ffdfea2646970667358221220e62db5a2cc2140c16fc51476401f061d88202cb8c699e83d8ae5391e545b318064736f6c634300081b0033", + "bytecode": "0x60556032600b8282823980515f1a607314602657634e487b7160e01b5f525f60045260245ffd5b305f52607381538281f3fe730000000000000000000000000000000000000000301460806040525f5ffdfea2646970667358221220b6c33cfbb9c820f6ef8a955b4c8f617ebaafe377a4cdfb594c4df3deadaecd6f64736f6c63430008230033", + "deployedBytecode": "0x730000000000000000000000000000000000000000301460806040525f5ffdfea2646970667358221220b6c33cfbb9c820f6ef8a955b4c8f617ebaafe377a4cdfb594c4df3deadaecd6f64736f6c63430008230033", "linkReferences": {}, "deployedLinkReferences": {} } diff --git a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/Panic.json b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/Panic.json similarity index 66% rename from dependencies/@openzeppelin-contracts-5.5.0/build/contracts/Panic.json rename to dependencies/@openzeppelin-contracts-5.7.0/build/contracts/Panic.json index fee5e60..cbb81f3 100644 --- a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/Panic.json +++ b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/Panic.json @@ -3,8 +3,8 @@ "contractName": "Panic", "sourceName": "contracts/utils/Panic.sol", "abi": [], - "bytecode": "0x60556032600b8282823980515f1a607314602657634e487b7160e01b5f525f60045260245ffd5b305f52607381538281f3fe730000000000000000000000000000000000000000301460806040525f5ffdfea26469706673582212206caec39495ea6073a37d5399121744cac67d9c1c61c3b425451550b17d3e17ba64736f6c634300081b0033", - "deployedBytecode": "0x730000000000000000000000000000000000000000301460806040525f5ffdfea26469706673582212206caec39495ea6073a37d5399121744cac67d9c1c61c3b425451550b17d3e17ba64736f6c634300081b0033", + "bytecode": "0x60556032600b8282823980515f1a607314602657634e487b7160e01b5f525f60045260245ffd5b305f52607381538281f3fe730000000000000000000000000000000000000000301460806040525f5ffdfea264697066735822122041f4941bfb5c6752d30b82cdc6ecda93b87b22657c90793232e7d8db553dea9264736f6c63430008230033", + "deployedBytecode": "0x730000000000000000000000000000000000000000301460806040525f5ffdfea264697066735822122041f4941bfb5c6752d30b82cdc6ecda93b87b22657c90793232e7d8db553dea9264736f6c63430008230033", "linkReferences": {}, "deployedLinkReferences": {} } diff --git a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/Pausable.json b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/Pausable.json similarity index 100% rename from dependencies/@openzeppelin-contracts-5.5.0/build/contracts/Pausable.json rename to dependencies/@openzeppelin-contracts-5.7.0/build/contracts/Pausable.json diff --git a/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/Paymaster.json b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/Paymaster.json new file mode 100644 index 0000000..951bf56 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/Paymaster.json @@ -0,0 +1,144 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "Paymaster", + "sourceName": "contracts/account/paymaster/Paymaster.sol", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "PaymasterUnauthorized", + "type": "error" + }, + { + "inputs": [], + "name": "entryPoint", + "outputs": [ + { + "internalType": "contract IEntryPoint", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "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.7.0/build/contracts/PaymasterERC20.json b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/PaymasterERC20.json new file mode 100644 index 0000000..3ee92ac --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/PaymasterERC20.json @@ -0,0 +1,206 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "PaymasterERC20", + "sourceName": "contracts/account/paymaster/extensions/PaymasterERC20.sol", + "abi": [ + { + "inputs": [], + "name": "OutOfRangeAccess", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "contract IERC20", + "name": "token", + "type": "address" + }, + { + "internalType": "uint256", + "name": "prefundAmount", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "actualAmount", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "prefundContext", + "type": "bytes" + } + ], + "name": "PaymasterERC20FailedRefund", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "PaymasterUnauthorized", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "userOpHash", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "address", + "name": "token", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "tokenAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "tokenPerNative", + "type": "uint256" + } + ], + "name": "UserOperationSponsored", + "type": "event" + }, + { + "inputs": [], + "name": "entryPoint", + "outputs": [ + { + "internalType": "contract IEntryPoint", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "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.7.0/build/contracts/PaymasterERC20Guarantor.json b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/PaymasterERC20Guarantor.json new file mode 100644 index 0000000..2668c69 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/PaymasterERC20Guarantor.json @@ -0,0 +1,231 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "PaymasterERC20Guarantor", + "sourceName": "contracts/account/paymaster/extensions/PaymasterERC20Guarantor.sol", + "abi": [ + { + "inputs": [], + "name": "OutOfRangeAccess", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "contract IERC20", + "name": "token", + "type": "address" + }, + { + "internalType": "uint256", + "name": "prefundAmount", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "actualAmount", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "prefundContext", + "type": "bytes" + } + ], + "name": "PaymasterERC20FailedRefund", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "PaymasterUnauthorized", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "userOpHash", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "address", + "name": "guarantor", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "prefundAmount", + "type": "uint256" + } + ], + "name": "UserOperationGuaranteed", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "userOpHash", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "address", + "name": "token", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "tokenAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "tokenPerNative", + "type": "uint256" + } + ], + "name": "UserOperationSponsored", + "type": "event" + }, + { + "inputs": [], + "name": "entryPoint", + "outputs": [ + { + "internalType": "contract IEntryPoint", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "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.7.0/build/contracts/PaymasterERC721Owner.json b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/PaymasterERC721Owner.json new file mode 100644 index 0000000..39006c0 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/PaymasterERC721Owner.json @@ -0,0 +1,157 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "PaymasterERC721Owner", + "sourceName": "contracts/account/paymaster/extensions/PaymasterERC721Owner.sol", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "PaymasterUnauthorized", + "type": "error" + }, + { + "inputs": [], + "name": "entryPoint", + "outputs": [ + { + "internalType": "contract IEntryPoint", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "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": [], + "name": "token", + "outputs": [ + { + "internalType": "contract IERC721", + "name": "", + "type": "address" + } + ], + "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.7.0/build/contracts/PaymasterSigner.json b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/PaymasterSigner.json new file mode 100644 index 0000000..7a5f468 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/PaymasterSigner.json @@ -0,0 +1,209 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "PaymasterSigner", + "sourceName": "contracts/account/paymaster/extensions/PaymasterSigner.sol", + "abi": [ + { + "inputs": [], + "name": "InvalidShortString", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "PaymasterUnauthorized", + "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": [], + "name": "entryPoint", + "outputs": [ + { + "internalType": "contract IEntryPoint", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "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.5.0/build/contracts/Proxy.json b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/Proxy.json similarity index 100% rename from dependencies/@openzeppelin-contracts-5.5.0/build/contracts/Proxy.json rename to dependencies/@openzeppelin-contracts-5.7.0/build/contracts/Proxy.json diff --git a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/ProxyAdmin.json b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/ProxyAdmin.json similarity index 96% rename from dependencies/@openzeppelin-contracts-5.5.0/build/contracts/ProxyAdmin.json rename to dependencies/@openzeppelin-contracts-5.7.0/build/contracts/ProxyAdmin.json index 52ddda6..e443821 100644 --- a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/ProxyAdmin.json +++ b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/ProxyAdmin.json @@ -125,8 +125,8 @@ "type": "function" } ], - "bytecode": "0x6080604052348015600e575f5ffd5b506040516104e63803806104e6833981016040819052602b9160b4565b806001600160a01b038116605857604051631e4fbdf760e01b81525f600482015260240160405180910390fd5b605f816065565b505060df565b5f80546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b5f6020828403121560c3575f5ffd5b81516001600160a01b038116811460d8575f5ffd5b9392505050565b6103fa806100ec5f395ff3fe608060405260043610610049575f3560e01c8063715018a61461004d5780638da5cb5b146100635780639623609d1461008e578063ad3cb1cc146100a1578063f2fde38b146100de575b5f5ffd5b348015610058575f5ffd5b506100616100fd565b005b34801561006e575f5ffd5b505f546040516001600160a01b0390911681526020015b60405180910390f35b61006161009c366004610260565b610110565b3480156100ac575f5ffd5b506100d1604051806040016040528060058152602001640352e302e360dc1b81525081565b6040516100859190610365565b3480156100e9575f5ffd5b506100616100f836600461037e565b61017b565b6101056101bd565b61010e5f6101e9565b565b6101186101bd565b60405163278f794360e11b81526001600160a01b03841690634f1ef2869034906101489086908690600401610399565b5f604051808303818588803b15801561015f575f5ffd5b505af1158015610171573d5f5f3e3d5ffd5b5050505050505050565b6101836101bd565b6001600160a01b0381166101b157604051631e4fbdf760e01b81525f60048201526024015b60405180910390fd5b6101ba816101e9565b50565b5f546001600160a01b0316331461010e5760405163118cdaa760e01b81523360048201526024016101a8565b5f80546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6001600160a01b03811681146101ba575f5ffd5b634e487b7160e01b5f52604160045260245ffd5b5f5f5f60608486031215610272575f5ffd5b833561027d81610238565b9250602084013561028d81610238565b9150604084013567ffffffffffffffff8111156102a8575f5ffd5b8401601f810186136102b8575f5ffd5b803567ffffffffffffffff8111156102d2576102d261024c565b604051601f8201601f19908116603f0116810167ffffffffffffffff811182821017156103015761030161024c565b604052818152828201602001881015610318575f5ffd5b816020840160208301375f602083830101528093505050509250925092565b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b602081525f6103776020830184610337565b9392505050565b5f6020828403121561038e575f5ffd5b813561037781610238565b6001600160a01b03831681526040602082018190525f906103bc90830184610337565b94935050505056fea264697066735822122006969be45262ce7a7d55a8ed09d4fc3284f19ccf33907228dd20e0d30f8ba79f64736f6c634300081b0033", - "deployedBytecode": "0x608060405260043610610049575f3560e01c8063715018a61461004d5780638da5cb5b146100635780639623609d1461008e578063ad3cb1cc146100a1578063f2fde38b146100de575b5f5ffd5b348015610058575f5ffd5b506100616100fd565b005b34801561006e575f5ffd5b505f546040516001600160a01b0390911681526020015b60405180910390f35b61006161009c366004610260565b610110565b3480156100ac575f5ffd5b506100d1604051806040016040528060058152602001640352e302e360dc1b81525081565b6040516100859190610365565b3480156100e9575f5ffd5b506100616100f836600461037e565b61017b565b6101056101bd565b61010e5f6101e9565b565b6101186101bd565b60405163278f794360e11b81526001600160a01b03841690634f1ef2869034906101489086908690600401610399565b5f604051808303818588803b15801561015f575f5ffd5b505af1158015610171573d5f5f3e3d5ffd5b5050505050505050565b6101836101bd565b6001600160a01b0381166101b157604051631e4fbdf760e01b81525f60048201526024015b60405180910390fd5b6101ba816101e9565b50565b5f546001600160a01b0316331461010e5760405163118cdaa760e01b81523360048201526024016101a8565b5f80546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6001600160a01b03811681146101ba575f5ffd5b634e487b7160e01b5f52604160045260245ffd5b5f5f5f60608486031215610272575f5ffd5b833561027d81610238565b9250602084013561028d81610238565b9150604084013567ffffffffffffffff8111156102a8575f5ffd5b8401601f810186136102b8575f5ffd5b803567ffffffffffffffff8111156102d2576102d261024c565b604051601f8201601f19908116603f0116810167ffffffffffffffff811182821017156103015761030161024c565b604052818152828201602001881015610318575f5ffd5b816020840160208301375f602083830101528093505050509250925092565b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b602081525f6103776020830184610337565b9392505050565b5f6020828403121561038e575f5ffd5b813561037781610238565b6001600160a01b03831681526040602082018190525f906103bc90830184610337565b94935050505056fea264697066735822122006969be45262ce7a7d55a8ed09d4fc3284f19ccf33907228dd20e0d30f8ba79f64736f6c634300081b0033", + "bytecode": "0x6080604052348015600e575f5ffd5b506040516104e63803806104e6833981016040819052602b9160b4565b806001600160a01b038116605857604051631e4fbdf760e01b81525f600482015260240160405180910390fd5b605f816065565b505060df565b5f80546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b5f6020828403121560c3575f5ffd5b81516001600160a01b038116811460d8575f5ffd5b9392505050565b6103fa806100ec5f395ff3fe608060405260043610610049575f3560e01c8063715018a61461004d5780638da5cb5b146100635780639623609d1461008e578063ad3cb1cc146100a1578063f2fde38b146100de575b5f5ffd5b348015610058575f5ffd5b506100616100fd565b005b34801561006e575f5ffd5b505f546040516001600160a01b0390911681526020015b60405180910390f35b61006161009c366004610260565b610110565b3480156100ac575f5ffd5b506100d1604051806040016040528060058152602001640352e302e360dc1b81525081565b6040516100859190610365565b3480156100e9575f5ffd5b506100616100f836600461037e565b61017b565b6101056101bd565b61010e5f6101e9565b565b6101186101bd565b60405163278f794360e11b81526001600160a01b03841690634f1ef2869034906101489086908690600401610399565b5f604051808303818588803b15801561015f575f5ffd5b505af1158015610171573d5f5f3e3d5ffd5b5050505050505050565b6101836101bd565b6001600160a01b0381166101b157604051631e4fbdf760e01b81525f60048201526024015b60405180910390fd5b6101ba816101e9565b50565b5f546001600160a01b0316331461010e5760405163118cdaa760e01b81523360048201526024016101a8565b5f80546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6001600160a01b03811681146101ba575f5ffd5b634e487b7160e01b5f52604160045260245ffd5b5f5f5f60608486031215610272575f5ffd5b833561027d81610238565b9250602084013561028d81610238565b9150604084013567ffffffffffffffff8111156102a8575f5ffd5b8401601f810186136102b8575f5ffd5b803567ffffffffffffffff8111156102d2576102d261024c565b604051601f8201601f19908116603f0116810167ffffffffffffffff811182821017156103015761030161024c565b604052818152828201602001881015610318575f5ffd5b816020840160208301375f602083830101528093505050509250925092565b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b602081525f6103776020830184610337565b9392505050565b5f6020828403121561038e575f5ffd5b813561037781610238565b6001600160a01b03831681526040602082018190525f906103bc90830184610337565b94935050505056fea26469706673582212201dee9c8150c961c89cb25180f0dabc8bd0164c46f92e16e64bbd9300a76f2a0364736f6c63430008230033", + "deployedBytecode": "0x608060405260043610610049575f3560e01c8063715018a61461004d5780638da5cb5b146100635780639623609d1461008e578063ad3cb1cc146100a1578063f2fde38b146100de575b5f5ffd5b348015610058575f5ffd5b506100616100fd565b005b34801561006e575f5ffd5b505f546040516001600160a01b0390911681526020015b60405180910390f35b61006161009c366004610260565b610110565b3480156100ac575f5ffd5b506100d1604051806040016040528060058152602001640352e302e360dc1b81525081565b6040516100859190610365565b3480156100e9575f5ffd5b506100616100f836600461037e565b61017b565b6101056101bd565b61010e5f6101e9565b565b6101186101bd565b60405163278f794360e11b81526001600160a01b03841690634f1ef2869034906101489086908690600401610399565b5f604051808303818588803b15801561015f575f5ffd5b505af1158015610171573d5f5f3e3d5ffd5b5050505050505050565b6101836101bd565b6001600160a01b0381166101b157604051631e4fbdf760e01b81525f60048201526024015b60405180910390fd5b6101ba816101e9565b50565b5f546001600160a01b0316331461010e5760405163118cdaa760e01b81523360048201526024016101a8565b5f80546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6001600160a01b03811681146101ba575f5ffd5b634e487b7160e01b5f52604160045260245ffd5b5f5f5f60608486031215610272575f5ffd5b833561027d81610238565b9250602084013561028d81610238565b9150604084013567ffffffffffffffff8111156102a8575f5ffd5b8401601f810186136102b8575f5ffd5b803567ffffffffffffffff8111156102d2576102d261024c565b604051601f8201601f19908116603f0116810167ffffffffffffffff811182821017156103015761030161024c565b604052818152828201602001881015610318575f5ffd5b816020840160208301375f602083830101528093505050509250925092565b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b602081525f6103776020830184610337565b9392505050565b5f6020828403121561038e575f5ffd5b813561037781610238565b6001600160a01b03831681526040602082018190525f906103bc90830184610337565b94935050505056fea26469706673582212201dee9c8150c961c89cb25180f0dabc8bd0164c46f92e16e64bbd9300a76f2a0364736f6c63430008230033", "linkReferences": {}, "deployedLinkReferences": {} } diff --git a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/RLP.json b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/RLP.json similarity index 70% rename from dependencies/@openzeppelin-contracts-5.5.0/build/contracts/RLP.json rename to dependencies/@openzeppelin-contracts-5.7.0/build/contracts/RLP.json index 7fe7251..12d5908 100644 --- a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/RLP.json +++ b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/RLP.json @@ -9,8 +9,8 @@ "type": "error" } ], - "bytecode": "0x60556032600b8282823980515f1a607314602657634e487b7160e01b5f525f60045260245ffd5b305f52607381538281f3fe730000000000000000000000000000000000000000301460806040525f5ffdfea26469706673582212201492eaf8369f0a7662f6451955a028a8bd70e48fb3a87de56a0a8c2e9a93c25f64736f6c634300081b0033", - "deployedBytecode": "0x730000000000000000000000000000000000000000301460806040525f5ffdfea26469706673582212201492eaf8369f0a7662f6451955a028a8bd70e48fb3a87de56a0a8c2e9a93c25f64736f6c634300081b0033", + "bytecode": "0x60556032600b8282823980515f1a607314602657634e487b7160e01b5f525f60045260245ffd5b305f52607381538281f3fe730000000000000000000000000000000000000000301460806040525f5ffdfea2646970667358221220a1898e3033d0b9e4dbebbb14ba89a2471acabf2308f3bca5b4aaf775f95d316d64736f6c63430008230033", + "deployedBytecode": "0x730000000000000000000000000000000000000000301460806040525f5ffdfea2646970667358221220a1898e3033d0b9e4dbebbb14ba89a2471acabf2308f3bca5b4aaf775f95d316d64736f6c63430008230033", "linkReferences": {}, "deployedLinkReferences": {} } diff --git a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/RSA.json b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/RSA.json similarity index 66% rename from dependencies/@openzeppelin-contracts-5.5.0/build/contracts/RSA.json rename to dependencies/@openzeppelin-contracts-5.7.0/build/contracts/RSA.json index cf086ff..68a1b16 100644 --- a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/RSA.json +++ b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/RSA.json @@ -3,8 +3,8 @@ "contractName": "RSA", "sourceName": "contracts/utils/cryptography/RSA.sol", "abi": [], - "bytecode": "0x60556032600b8282823980515f1a607314602657634e487b7160e01b5f525f60045260245ffd5b305f52607381538281f3fe730000000000000000000000000000000000000000301460806040525f5ffdfea264697066735822122079578706c3e170342172fd908d93f444ee927eaa5c33be71b84b741667bc20c964736f6c634300081b0033", - "deployedBytecode": "0x730000000000000000000000000000000000000000301460806040525f5ffdfea264697066735822122079578706c3e170342172fd908d93f444ee927eaa5c33be71b84b741667bc20c964736f6c634300081b0033", + "bytecode": "0x60556032600b8282823980515f1a607314602657634e487b7160e01b5f525f60045260245ffd5b305f52607381538281f3fe730000000000000000000000000000000000000000301460806040525f5ffdfea2646970667358221220b5ac7309a18371c206165117067871b97f6665db749071083a3903eb2c1ae2e564736f6c63430008230033", + "deployedBytecode": "0x730000000000000000000000000000000000000000301460806040525f5ffdfea2646970667358221220b5ac7309a18371c206165117067871b97f6665db749071083a3903eb2c1ae2e564736f6c63430008230033", "linkReferences": {}, "deployedLinkReferences": {} } diff --git a/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/RateLimiter.json b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/RateLimiter.json new file mode 100644 index 0000000..5535b4c --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/RateLimiter.json @@ -0,0 +1,16 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "RateLimiter", + "sourceName": "contracts/utils/RateLimiter.sol", + "abi": [ + { + "inputs": [], + "name": "RateLimitExceeded", + "type": "error" + } + ], + "bytecode": "0x60556032600b8282823980515f1a607314602657634e487b7160e01b5f525f60045260245ffd5b305f52607381538281f3fe730000000000000000000000000000000000000000301460806040525f5ffdfea26469706673582212209860f54fe5e0e82026d53dd7f41bbbfb77127bb65db65c1fc0c1a36f3e1b3a2964736f6c63430008230033", + "deployedBytecode": "0x730000000000000000000000000000000000000000301460806040525f5ffdfea26469706673582212209860f54fe5e0e82026d53dd7f41bbbfb77127bb65db65c1fc0c1a36f3e1b3a2964736f6c63430008230033", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/ReentrancyGuard.json b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/ReentrancyGuard.json similarity index 100% rename from dependencies/@openzeppelin-contracts-5.5.0/build/contracts/ReentrancyGuard.json rename to dependencies/@openzeppelin-contracts-5.7.0/build/contracts/ReentrancyGuard.json diff --git a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/ReentrancyGuardTransient.json b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/ReentrancyGuardTransient.json similarity index 100% rename from dependencies/@openzeppelin-contracts-5.5.0/build/contracts/ReentrancyGuardTransient.json rename to dependencies/@openzeppelin-contracts-5.7.0/build/contracts/ReentrancyGuardTransient.json diff --git a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/RelayedCall.json b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/RelayedCall.json similarity index 66% rename from dependencies/@openzeppelin-contracts-5.5.0/build/contracts/RelayedCall.json rename to dependencies/@openzeppelin-contracts-5.7.0/build/contracts/RelayedCall.json index 031037b..0798825 100644 --- a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/RelayedCall.json +++ b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/RelayedCall.json @@ -3,8 +3,8 @@ "contractName": "RelayedCall", "sourceName": "contracts/utils/RelayedCall.sol", "abi": [], - "bytecode": "0x60556032600b8282823980515f1a607314602657634e487b7160e01b5f525f60045260245ffd5b305f52607381538281f3fe730000000000000000000000000000000000000000301460806040525f5ffdfea264697066735822122069604396df8bf0204c41aa0e7ac7e008c255383e6bb3dca349b16f1074f7e81764736f6c634300081b0033", - "deployedBytecode": "0x730000000000000000000000000000000000000000301460806040525f5ffdfea264697066735822122069604396df8bf0204c41aa0e7ac7e008c255383e6bb3dca349b16f1074f7e81764736f6c634300081b0033", + "bytecode": "0x60556032600b8282823980515f1a607314602657634e487b7160e01b5f525f60045260245ffd5b305f52607381538281f3fe730000000000000000000000000000000000000000301460806040525f5ffdfea2646970667358221220745602411ea9e6ad5f2d0d60076c78dad9206b9382ca88487bd397dffe33d3e864736f6c63430008230033", + "deployedBytecode": "0x730000000000000000000000000000000000000000301460806040525f5ffdfea2646970667358221220745602411ea9e6ad5f2d0d60076c78dad9206b9382ca88487bd397dffe33d3e864736f6c63430008230033", "linkReferences": {}, "deployedLinkReferences": {} } diff --git a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/SafeCast.json b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/SafeCast.json similarity index 87% rename from dependencies/@openzeppelin-contracts-5.5.0/build/contracts/SafeCast.json rename to dependencies/@openzeppelin-contracts-5.7.0/build/contracts/SafeCast.json index 27a4487..d019847 100644 --- a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/SafeCast.json +++ b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/SafeCast.json @@ -58,8 +58,8 @@ "type": "error" } ], - "bytecode": "0x60556032600b8282823980515f1a607314602657634e487b7160e01b5f525f60045260245ffd5b305f52607381538281f3fe730000000000000000000000000000000000000000301460806040525f5ffdfea2646970667358221220cdc0a6d6f1844696fe5e3590c11b6e01357d685363c24c8322eb82bed674804364736f6c634300081b0033", - "deployedBytecode": "0x730000000000000000000000000000000000000000301460806040525f5ffdfea2646970667358221220cdc0a6d6f1844696fe5e3590c11b6e01357d685363c24c8322eb82bed674804364736f6c634300081b0033", + "bytecode": "0x60556032600b8282823980515f1a607314602657634e487b7160e01b5f525f60045260245ffd5b305f52607381538281f3fe730000000000000000000000000000000000000000301460806040525f5ffdfea2646970667358221220800b682da6ccf80b235f38e64780e804d00ce05c9caedff1673a4dbf0d0ece9164736f6c63430008230033", + "deployedBytecode": "0x730000000000000000000000000000000000000000301460806040525f5ffdfea2646970667358221220800b682da6ccf80b235f38e64780e804d00ce05c9caedff1673a4dbf0d0ece9164736f6c63430008230033", "linkReferences": {}, "deployedLinkReferences": {} } diff --git a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/SafeERC20.json b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/SafeERC20.json similarity index 83% rename from dependencies/@openzeppelin-contracts-5.5.0/build/contracts/SafeERC20.json rename to dependencies/@openzeppelin-contracts-5.7.0/build/contracts/SafeERC20.json index 96deeb8..28ae765 100644 --- a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/SafeERC20.json +++ b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/SafeERC20.json @@ -36,8 +36,8 @@ "type": "error" } ], - "bytecode": "0x60556032600b8282823980515f1a607314602657634e487b7160e01b5f525f60045260245ffd5b305f52607381538281f3fe730000000000000000000000000000000000000000301460806040525f5ffdfea2646970667358221220c7f196645ee9bda993db908f74713cec954f227759d59ed130e9a4e0390ccfef64736f6c634300081b0033", - "deployedBytecode": "0x730000000000000000000000000000000000000000301460806040525f5ffdfea2646970667358221220c7f196645ee9bda993db908f74713cec954f227759d59ed130e9a4e0390ccfef64736f6c634300081b0033", + "bytecode": "0x60556032600b8282823980515f1a607314602657634e487b7160e01b5f525f60045260245ffd5b305f52607381538281f3fe730000000000000000000000000000000000000000301460806040525f5ffdfea264697066735822122008bb8a57a69d7725dca9d9e2c7439e8fa344011ee9dd7c3e5d5bafebd4a3d33664736f6c63430008230033", + "deployedBytecode": "0x730000000000000000000000000000000000000000301460806040525f5ffdfea264697066735822122008bb8a57a69d7725dca9d9e2c7439e8fa344011ee9dd7c3e5d5bafebd4a3d33664736f6c63430008230033", "linkReferences": {}, "deployedLinkReferences": {} } diff --git a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/ShortStrings.json b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/ShortStrings.json similarity index 76% rename from dependencies/@openzeppelin-contracts-5.5.0/build/contracts/ShortStrings.json rename to dependencies/@openzeppelin-contracts-5.7.0/build/contracts/ShortStrings.json index e7665d6..70d72a3 100644 --- a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/ShortStrings.json +++ b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/ShortStrings.json @@ -20,8 +20,8 @@ "type": "error" } ], - "bytecode": "0x60556032600b8282823980515f1a607314602657634e487b7160e01b5f525f60045260245ffd5b305f52607381538281f3fe730000000000000000000000000000000000000000301460806040525f5ffdfea264697066735822122013040afd371e073fd5f8cf04a886d037b3fde94ae067c85f8868b1a0f966593f64736f6c634300081b0033", - "deployedBytecode": "0x730000000000000000000000000000000000000000301460806040525f5ffdfea264697066735822122013040afd371e073fd5f8cf04a886d037b3fde94ae067c85f8868b1a0f966593f64736f6c634300081b0033", + "bytecode": "0x60556032600b8282823980515f1a607314602657634e487b7160e01b5f525f60045260245ffd5b305f52607381538281f3fe730000000000000000000000000000000000000000301460806040525f5ffdfea2646970667358221220ccf300352a09463f5fbee77834e8000eef61cd4b8a232e9e0a117fc1676905eb64736f6c63430008230033", + "deployedBytecode": "0x730000000000000000000000000000000000000000301460806040525f5ffdfea2646970667358221220ccf300352a09463f5fbee77834e8000eef61cd4b8a232e9e0a117fc1676905eb64736f6c63430008230033", "linkReferences": {}, "deployedLinkReferences": {} } diff --git a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/SignatureChecker.json b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/SignatureChecker.json similarity index 67% rename from dependencies/@openzeppelin-contracts-5.5.0/build/contracts/SignatureChecker.json rename to dependencies/@openzeppelin-contracts-5.7.0/build/contracts/SignatureChecker.json index cb96231..f5438f7 100644 --- a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/SignatureChecker.json +++ b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/SignatureChecker.json @@ -3,8 +3,8 @@ "contractName": "SignatureChecker", "sourceName": "contracts/utils/cryptography/SignatureChecker.sol", "abi": [], - "bytecode": "0x60556032600b8282823980515f1a607314602657634e487b7160e01b5f525f60045260245ffd5b305f52607381538281f3fe730000000000000000000000000000000000000000301460806040525f5ffdfea2646970667358221220cdcad06e5027852aa976d4d1eb727a1245bc684dfc88257b29f837e642a37aad64736f6c634300081b0033", - "deployedBytecode": "0x730000000000000000000000000000000000000000301460806040525f5ffdfea2646970667358221220cdcad06e5027852aa976d4d1eb727a1245bc684dfc88257b29f837e642a37aad64736f6c634300081b0033", + "bytecode": "0x60556032600b8282823980515f1a607314602657634e487b7160e01b5f525f60045260245ffd5b305f52607381538281f3fe730000000000000000000000000000000000000000301460806040525f5ffdfea264697066735822122065e35f282014994791fa60553247058108a858613f3058e14ee608fc2bb6006864736f6c63430008230033", + "deployedBytecode": "0x730000000000000000000000000000000000000000301460806040525f5ffdfea264697066735822122065e35f282014994791fa60553247058108a858613f3058e14ee608fc2bb6006864736f6c63430008230033", "linkReferences": {}, "deployedLinkReferences": {} } diff --git a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/SignedMath.json b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/SignedMath.json similarity index 66% rename from dependencies/@openzeppelin-contracts-5.5.0/build/contracts/SignedMath.json rename to dependencies/@openzeppelin-contracts-5.7.0/build/contracts/SignedMath.json index 49095ba..be010d3 100644 --- a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/SignedMath.json +++ b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/SignedMath.json @@ -3,8 +3,8 @@ "contractName": "SignedMath", "sourceName": "contracts/utils/math/SignedMath.sol", "abi": [], - "bytecode": "0x60556032600b8282823980515f1a607314602657634e487b7160e01b5f525f60045260245ffd5b305f52607381538281f3fe730000000000000000000000000000000000000000301460806040525f5ffdfea2646970667358221220b88d8d2710edc1e83c6bb4401e99631441b7a7f7894f6d46a3d8b8e0791b1acf64736f6c634300081b0033", - "deployedBytecode": "0x730000000000000000000000000000000000000000301460806040525f5ffdfea2646970667358221220b88d8d2710edc1e83c6bb4401e99631441b7a7f7894f6d46a3d8b8e0791b1acf64736f6c634300081b0033", + "bytecode": "0x60556032600b8282823980515f1a607314602657634e487b7160e01b5f525f60045260245ffd5b305f52607381538281f3fe730000000000000000000000000000000000000000301460806040525f5ffdfea2646970667358221220e03afb9f49043c83e839b0a47ab0363c467c0a8aaab7c436d7fa35b7f5a008a664736f6c63430008230033", + "deployedBytecode": "0x730000000000000000000000000000000000000000301460806040525f5ffdfea2646970667358221220e03afb9f49043c83e839b0a47ab0363c467c0a8aaab7c436d7fa35b7f5a008a664736f6c63430008230033", "linkReferences": {}, "deployedLinkReferences": {} } diff --git a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/SignerECDSA.json b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/SignerECDSA.json similarity index 100% rename from dependencies/@openzeppelin-contracts-5.5.0/build/contracts/SignerECDSA.json rename to dependencies/@openzeppelin-contracts-5.7.0/build/contracts/SignerECDSA.json diff --git a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/SignerEIP7702.json b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/SignerEIP7702.json similarity index 100% rename from dependencies/@openzeppelin-contracts-5.5.0/build/contracts/SignerEIP7702.json rename to dependencies/@openzeppelin-contracts-5.7.0/build/contracts/SignerEIP7702.json diff --git a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/SignerERC7913.json b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/SignerERC7913.json similarity index 100% rename from dependencies/@openzeppelin-contracts-5.5.0/build/contracts/SignerERC7913.json rename to dependencies/@openzeppelin-contracts-5.7.0/build/contracts/SignerERC7913.json diff --git a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/SignerP256.json b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/SignerP256.json similarity index 100% rename from dependencies/@openzeppelin-contracts-5.5.0/build/contracts/SignerP256.json rename to dependencies/@openzeppelin-contracts-5.7.0/build/contracts/SignerP256.json diff --git a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/SignerRSA.json b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/SignerRSA.json similarity index 100% rename from dependencies/@openzeppelin-contracts-5.5.0/build/contracts/SignerRSA.json rename to dependencies/@openzeppelin-contracts-5.7.0/build/contracts/SignerRSA.json diff --git a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/SignerWebAuthn.json b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/SignerWebAuthn.json similarity index 100% rename from dependencies/@openzeppelin-contracts-5.5.0/build/contracts/SignerWebAuthn.json rename to dependencies/@openzeppelin-contracts-5.7.0/build/contracts/SignerWebAuthn.json diff --git a/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/SimulateCall.json b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/SimulateCall.json new file mode 100644 index 0000000..a51cd42 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/SimulateCall.json @@ -0,0 +1,10 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "SimulateCall", + "sourceName": "contracts/utils/SimulateCall.sol", + "abi": [], + "bytecode": "0x60556032600b8282823980515f1a607314602657634e487b7160e01b5f525f60045260245ffd5b305f52607381538281f3fe730000000000000000000000000000000000000000301460806040525f5ffdfea2646970667358221220891b25a5df9aaf325e2f60cd9d8ad2a8e536c5690f72631ac94225d5648cb94c64736f6c63430008230033", + "deployedBytecode": "0x730000000000000000000000000000000000000000301460806040525f5ffdfea2646970667358221220891b25a5df9aaf325e2f60cd9d8ad2a8e536c5690f72631ac94225d5648cb94c64736f6c63430008230033", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/SlotDerivation.json b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/SlotDerivation.json similarity index 66% rename from dependencies/@openzeppelin-contracts-5.5.0/build/contracts/SlotDerivation.json rename to dependencies/@openzeppelin-contracts-5.7.0/build/contracts/SlotDerivation.json index a11f9db..3562a45 100644 --- a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/SlotDerivation.json +++ b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/SlotDerivation.json @@ -3,8 +3,8 @@ "contractName": "SlotDerivation", "sourceName": "contracts/utils/SlotDerivation.sol", "abi": [], - "bytecode": "0x60556032600b8282823980515f1a607314602657634e487b7160e01b5f525f60045260245ffd5b305f52607381538281f3fe730000000000000000000000000000000000000000301460806040525f5ffdfea264697066735822122082e6bc1df61e2706da75e36de5d47d9c39bb3cdaee748a906155b6256dde985f64736f6c634300081b0033", - "deployedBytecode": "0x730000000000000000000000000000000000000000301460806040525f5ffdfea264697066735822122082e6bc1df61e2706da75e36de5d47d9c39bb3cdaee748a906155b6256dde985f64736f6c634300081b0033", + "bytecode": "0x60556032600b8282823980515f1a607314602657634e487b7160e01b5f525f60045260245ffd5b305f52607381538281f3fe730000000000000000000000000000000000000000301460806040525f5ffdfea26469706673582212200648d204f386cf7075533e383f3f05c7b23d960cac4a4ebc279e1a9f004e204264736f6c63430008230033", + "deployedBytecode": "0x730000000000000000000000000000000000000000301460806040525f5ffdfea26469706673582212200648d204f386cf7075533e383f3f05c7b23d960cac4a4ebc279e1a9f004e204264736f6c63430008230033", "linkReferences": {}, "deployedLinkReferences": {} } diff --git a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/StorageSlot.json b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/StorageSlot.json similarity index 66% rename from dependencies/@openzeppelin-contracts-5.5.0/build/contracts/StorageSlot.json rename to dependencies/@openzeppelin-contracts-5.7.0/build/contracts/StorageSlot.json index d9f83cd..ea5dc51 100644 --- a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/StorageSlot.json +++ b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/StorageSlot.json @@ -3,8 +3,8 @@ "contractName": "StorageSlot", "sourceName": "contracts/utils/StorageSlot.sol", "abi": [], - "bytecode": "0x60556032600b8282823980515f1a607314602657634e487b7160e01b5f525f60045260245ffd5b305f52607381538281f3fe730000000000000000000000000000000000000000301460806040525f5ffdfea26469706673582212200d83593a1d7d29bd8ee1c3bd9b728524fc750d1c9bedc1a23f3d73b8940f181364736f6c634300081b0033", - "deployedBytecode": "0x730000000000000000000000000000000000000000301460806040525f5ffdfea26469706673582212200d83593a1d7d29bd8ee1c3bd9b728524fc750d1c9bedc1a23f3d73b8940f181364736f6c634300081b0033", + "bytecode": "0x60556032600b8282823980515f1a607314602657634e487b7160e01b5f525f60045260245ffd5b305f52607381538281f3fe730000000000000000000000000000000000000000301460806040525f5ffdfea26469706673582212205071db957cd818964902971a1e444695ee76fe4d6195cb8af92a73da0be40deb64736f6c63430008230033", + "deployedBytecode": "0x730000000000000000000000000000000000000000301460806040525f5ffdfea26469706673582212205071db957cd818964902971a1e444695ee76fe4d6195cb8af92a73da0be40deb64736f6c63430008230033", "linkReferences": {}, "deployedLinkReferences": {} } diff --git a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/Strings.json b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/Strings.json similarity index 81% rename from dependencies/@openzeppelin-contracts-5.5.0/build/contracts/Strings.json rename to dependencies/@openzeppelin-contracts-5.7.0/build/contracts/Strings.json index 684b50b..5976c33 100644 --- a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/Strings.json +++ b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/Strings.json @@ -30,8 +30,8 @@ "type": "error" } ], - "bytecode": "0x60556032600b8282823980515f1a607314602657634e487b7160e01b5f525f60045260245ffd5b305f52607381538281f3fe730000000000000000000000000000000000000000301460806040525f5ffdfea2646970667358221220d53b4bc3b947f89c0e51024becef619846f2f45bcddbe51c2ccce9a263fa15cb64736f6c634300081b0033", - "deployedBytecode": "0x730000000000000000000000000000000000000000301460806040525f5ffdfea2646970667358221220d53b4bc3b947f89c0e51024becef619846f2f45bcddbe51c2ccce9a263fa15cb64736f6c634300081b0033", + "bytecode": "0x60556032600b8282823980515f1a607314602657634e487b7160e01b5f525f60045260245ffd5b305f52607381538281f3fe730000000000000000000000000000000000000000301460806040525f5ffdfea2646970667358221220182b14d42f8c32c3cdef4f0d3f30b3c2216f065e498f6c06960bf97218f1aa4564736f6c63430008230033", + "deployedBytecode": "0x730000000000000000000000000000000000000000301460806040525f5ffdfea2646970667358221220182b14d42f8c32c3cdef4f0d3f30b3c2216f065e498f6c06960bf97218f1aa4564736f6c63430008230033", "linkReferences": {}, "deployedLinkReferences": {} } diff --git a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/Time.json b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/Time.json similarity index 66% rename from dependencies/@openzeppelin-contracts-5.5.0/build/contracts/Time.json rename to dependencies/@openzeppelin-contracts-5.7.0/build/contracts/Time.json index 94dc3a5..37e6667 100644 --- a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/Time.json +++ b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/Time.json @@ -3,8 +3,8 @@ "contractName": "Time", "sourceName": "contracts/utils/types/Time.sol", "abi": [], - "bytecode": "0x60556032600b8282823980515f1a607314602657634e487b7160e01b5f525f60045260245ffd5b305f52607381538281f3fe730000000000000000000000000000000000000000301460806040525f5ffdfea264697066735822122041517724ff3424a07d01fa50b6057ff094eb35b7524fcbeefa295681fc7f158164736f6c634300081b0033", - "deployedBytecode": "0x730000000000000000000000000000000000000000301460806040525f5ffdfea264697066735822122041517724ff3424a07d01fa50b6057ff094eb35b7524fcbeefa295681fc7f158164736f6c634300081b0033", + "bytecode": "0x60556032600b8282823980515f1a607314602657634e487b7160e01b5f525f60045260245ffd5b305f52607381538281f3fe730000000000000000000000000000000000000000301460806040525f5ffdfea26469706673582212205c9e64b2495514575262029c87810fe0f9dbd97f1a2422bd15de746ee646a51d64736f6c63430008230033", + "deployedBytecode": "0x730000000000000000000000000000000000000000301460806040525f5ffdfea26469706673582212205c9e64b2495514575262029c87810fe0f9dbd97f1a2422bd15de746ee646a51d64736f6c63430008230033", "linkReferences": {}, "deployedLinkReferences": {} } diff --git a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/TimelockController.json b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/TimelockController.json similarity index 99% rename from dependencies/@openzeppelin-contracts-5.5.0/build/contracts/TimelockController.json rename to dependencies/@openzeppelin-contracts-5.7.0/build/contracts/TimelockController.json index d658642..ffecd89 100644 --- a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/TimelockController.json +++ b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/TimelockController.json @@ -1000,8 +1000,8 @@ "type": "receive" } ], - "bytecode": "0x608060405234801561000f575f5ffd5b50604051611d2c380380611d2c83398101604081905261002e916102f6565b6100385f3061017b565b506001600160a01b03811615610054576100525f8261017b565b505b5f5b83518110156100e8576100a87fb09aa5aeb3702cfd50b6b62bc4532604938f21248a27a1d5ca736082b6819cc185838151811061009557610095610375565b602002602001015161017b60201b60201c565b506100df7ffd643c72710c63c0180259aba6b2d05451e3591a24e58b62239378085726f78385838151811061009557610095610375565b50600101610056565b505f5b82518110156101335761012a7fd8aa0f3194971a2a116679f7c2090f6939c8d4e01a2a8d7e41d55e5351469e6384838151811061009557610095610375565b506001016100eb565b506002849055604080515f8152602081018690527f11c24f4ead16507c69ac467fbd5e4eed5fb5c699626d2cc6d66421df253886d5910160405180910390a150505050610389565b5f828152602081815260408083206001600160a01b038516845290915281205460ff1661021b575f838152602081815260408083206001600160a01b03861684529091529020805460ff191660011790556101d33390565b6001600160a01b0316826001600160a01b0316847f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a450600161021e565b505f5b92915050565b634e487b7160e01b5f52604160045260245ffd5b80516001600160a01b038116811461024e575f5ffd5b919050565b5f82601f830112610262575f5ffd5b81516001600160401b0381111561027b5761027b610224565b604051600582901b90603f8201601f191681016001600160401b03811182821017156102a9576102a9610224565b6040529182526020818501810192908101868411156102c6575f5ffd5b6020860192505b838310156102ec576102de83610238565b8152602092830192016102cd565b5095945050505050565b5f5f5f5f60808587031215610309575f5ffd5b845160208601519094506001600160401b03811115610326575f5ffd5b61033287828801610253565b604087015190945090506001600160401b0381111561034f575f5ffd5b61035b87828801610253565b92505061036a60608601610238565b905092959194509250565b634e487b7160e01b5f52603260045260245ffd5b611996806103965f395ff3fe6080604052600436106101b2575f3560e01c80638065657f116100e7578063bc197c8111610087578063d547741f11610062578063d547741f14610546578063e38335e514610565578063f23a6e6114610578578063f27a0c92146105a3575f5ffd5b8063bc197c81146104d1578063c4d252f5146104fc578063d45c44351461051b575f5ffd5b806391d14854116100c257806391d148541461044d578063a217fddf1461046c578063b08e51c01461047f578063b1c5f427146104b2575f5ffd5b80638065657f146103dc5780638f2a0bb0146103fb5780638f61f4f51461041a575f5ffd5b80632ab0f5291161015257806336568abe1161012d57806336568abe14610353578063584b153e1461037257806364d62353146103915780637958004c146103b0575f5ffd5b80632ab0f529146102f65780632f2ff15d1461031557806331d5075014610334575f5ffd5b8063134008d31161018d578063134008d31461025357806313bc9f2014610266578063150b7a0214610285578063248a9ca3146102c8575f5ffd5b806301d5062a146101bd57806301ffc9a7146101de57806307bd026514610212575f5ffd5b366101b957005b5f5ffd5b3480156101c8575f5ffd5b506101dc6101d7366004611163565b6105b7565b005b3480156101e9575f5ffd5b506101fd6101f83660046111d1565b61068b565b60405190151581526020015b60405180910390f35b34801561021d575f5ffd5b506102457fd8aa0f3194971a2a116679f7c2090f6939c8d4e01a2a8d7e41d55e5351469e6381565b604051908152602001610209565b6101dc6102613660046111f8565b61069b565b348015610271575f5ffd5b506101fd61028036600461125e565b61074d565b348015610290575f5ffd5b506102af61029f366004611324565b630a85bd0160e11b949350505050565b6040516001600160e01b03199091168152602001610209565b3480156102d3575f5ffd5b506102456102e236600461125e565b5f9081526020819052604090206001015490565b348015610301575f5ffd5b506101fd61031036600461125e565b610772565b348015610320575f5ffd5b506101dc61032f366004611387565b61077a565b34801561033f575f5ffd5b506101fd61034e36600461125e565b6107a4565b34801561035e575f5ffd5b506101dc61036d366004611387565b6107c8565b34801561037d575f5ffd5b506101fd61038c36600461125e565b610800565b34801561039c575f5ffd5b506101dc6103ab36600461125e565b610845565b3480156103bb575f5ffd5b506103cf6103ca36600461125e565b6108b8565b60405161020991906113c5565b3480156103e7575f5ffd5b506102456103f63660046111f8565b610900565b348015610406575f5ffd5b506101dc61041536600461142b565b61093e565b348015610425575f5ffd5b506102457fb09aa5aeb3702cfd50b6b62bc4532604938f21248a27a1d5ca736082b6819cc181565b348015610458575f5ffd5b506101fd610467366004611387565b610aca565b348015610477575f5ffd5b506102455f81565b34801561048a575f5ffd5b506102457ffd643c72710c63c0180259aba6b2d05451e3591a24e58b62239378085726f78381565b3480156104bd575f5ffd5b506102456104cc3660046114dd565b610af2565b3480156104dc575f5ffd5b506102af6104eb366004611606565b63bc197c8160e01b95945050505050565b348015610507575f5ffd5b506101dc61051636600461125e565b610b36565b348015610526575f5ffd5b5061024561053536600461125e565b5f9081526001602052604090205490565b348015610551575f5ffd5b506101dc610560366004611387565b610be0565b6101dc6105733660046114dd565b610c04565b348015610583575f5ffd5b506102af6105923660046116b2565b63f23a6e6160e01b95945050505050565b3480156105ae575f5ffd5b50600254610245565b7fb09aa5aeb3702cfd50b6b62bc4532604938f21248a27a1d5ca736082b6819cc16105e181610d85565b5f6105f0898989898989610900565b90506105fc8184610d92565b5f817f4cf4410cc57040e44862ef0f45f3dd5a5e02db8eb8add648d4b0e236f1d07dca8b8b8b8b8b8a6040516106379695949392919061172d565b60405180910390a3831561068057807f20fda5fd27a1ea7bf5b9567f143ac5470bb059374a27e8f67cb44f946f6d03878560405161067791815260200190565b60405180910390a25b505050505050505050565b5f61069582610e23565b92915050565b7fd8aa0f3194971a2a116679f7c2090f6939c8d4e01a2a8d7e41d55e5351469e636106c6815f610aca565b6106d4576106d48133610e47565b5f6106e3888888888888610900565b90506106ef8185610e84565b6106fb88888888610ed2565b5f817fc2617efa69bab66782fa219543714338489c4e9e178271560a91b82c3f612b588a8a8a8a6040516107329493929190611769565b60405180910390a361074381610f46565b5050505050505050565b5f60025b61075a836108b8565b600381111561076b5761076b6113b1565b1492915050565b5f6003610751565b5f8281526020819052604090206001015461079481610d85565b61079e8383610f71565b50505050565b5f806107af836108b8565b60038111156107c0576107c06113b1565b141592915050565b6001600160a01b03811633146107f15760405163334bd91960e11b815260040160405180910390fd5b6107fb8282611000565b505050565b5f5f61080b836108b8565b90506001816003811115610821576108216113b1565b148061083e5750600281600381111561083c5761083c6113b1565b145b9392505050565b333081146108765760405163e2850c5960e01b81526001600160a01b03821660048201526024015b60405180910390fd5b60025460408051918252602082018490527f11c24f4ead16507c69ac467fbd5e4eed5fb5c699626d2cc6d66421df253886d5910160405180910390a150600255565b5f81815260016020526040812054805f036108d557505f92915050565b600181036108e65750600392915050565b428111156108f75750600192915050565b50600292915050565b5f86868686868660405160200161091c9695949392919061172d565b6040516020818303038152906040528051906020012090509695505050505050565b7fb09aa5aeb3702cfd50b6b62bc4532604938f21248a27a1d5ca736082b6819cc161096881610d85565b88871415806109775750888514155b156109a9576040516001624fcdef60e01b03198152600481018a9052602481018690526044810188905260640161086d565b5f6109ba8b8b8b8b8b8b8b8b610af2565b90506109c68184610d92565b5f5b8a811015610a7b5780827f4cf4410cc57040e44862ef0f45f3dd5a5e02db8eb8add648d4b0e236f1d07dca8e8e85818110610a0557610a05611790565b9050602002016020810190610a1a91906117a4565b8d8d86818110610a2c57610a2c611790565b905060200201358c8c87818110610a4557610a45611790565b9050602002810190610a5791906117bd565b8c8b604051610a6b9695949392919061172d565b60405180910390a36001016109c8565b508315610abd57807f20fda5fd27a1ea7bf5b9567f143ac5470bb059374a27e8f67cb44f946f6d038785604051610ab491815260200190565b60405180910390a25b5050505050505050505050565b5f918252602082815260408084206001600160a01b0393909316845291905290205460ff1690565b5f8888888888888888604051602001610b12989796959493929190611893565b60405160208183030381529060405280519060200120905098975050505050505050565b7ffd643c72710c63c0180259aba6b2d05451e3591a24e58b62239378085726f783610b6081610d85565b610b6982610800565b610ba55781610b786002611069565b610b826001611069565b604051635ead8eb560e01b8152600481019390935217602482015260440161086d565b5f828152600160205260408082208290555183917fbaa1eb22f2a492ba1a5fea61b8df4d27c6c8b5f3971e63bb58fa14ff72eedb7091a25050565b5f82815260208190526040902060010154610bfa81610d85565b61079e8383611000565b7fd8aa0f3194971a2a116679f7c2090f6939c8d4e01a2a8d7e41d55e5351469e63610c2f815f610aca565b610c3d57610c3d8133610e47565b8786141580610c4c5750878414155b15610c7e576040516001624fcdef60e01b0319815260048101899052602481018590526044810187905260640161086d565b5f610c8f8a8a8a8a8a8a8a8a610af2565b9050610c9b8185610e84565b5f5b89811015610d6f575f8b8b83818110610cb857610cb8611790565b9050602002016020810190610ccd91906117a4565b90505f8a8a84818110610ce257610ce2611790565b905060200201359050365f8a8a86818110610cff57610cff611790565b9050602002810190610d1191906117bd565b91509150610d2184848484610ed2565b84867fc2617efa69bab66782fa219543714338489c4e9e178271560a91b82c3f612b5886868686604051610d589493929190611769565b60405180910390a350505050806001019050610c9d565b50610d7981610f46565b50505050505050505050565b610d8f8133610e47565b50565b610d9b826107a4565b15610dcc5781610daa5f611069565b604051635ead8eb560e01b81526004810192909252602482015260440161086d565b5f610dd660025490565b905080821015610e0357604051635433660960e01b8152600481018390526024810182905260440161086d565b610e0d8242611932565b5f93845260016020526040909320929092555050565b5f6001600160e01b03198216630271189760e51b148061069557506106958261108b565b610e518282610aca565b610e805760405163e2517d3f60e01b81526001600160a01b03821660048201526024810183905260440161086d565b5050565b610e8d8261074d565b610e9c5781610daa6002611069565b8015801590610eb15750610eaf81610772565b155b15610e805760405163121534c360e31b81526004810182905260240161086d565b5f5f856001600160a01b0316858585604051610eef929190611951565b5f6040518083038185875af1925050503d805f8114610f29576040519150601f19603f3d011682016040523d82523d5f602084013e610f2e565b606091505b5091509150610f3d82826110bf565b50505050505050565b610f4f8161074d565b610f5e5780610daa6002611069565b5f90815260016020819052604090912055565b5f610f7c8383610aca565b610ff9575f838152602081815260408083206001600160a01b03861684529091529020805460ff19166001179055610fb13390565b6001600160a01b0316826001600160a01b0316847f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a4506001610695565b505f610695565b5f61100b8383610aca565b15610ff9575f838152602081815260408083206001600160a01b0386168085529252808320805460ff1916905551339286917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9190a4506001610695565b5f81600381111561107c5761107c6113b1565b600160ff919091161b92915050565b5f6001600160e01b03198216637965db0b60e01b148061069557506301ffc9a760e01b6001600160e01b0319831614610695565b606082156110ce575080610695565b8151156110e3576110de826110fc565b610695565b60405163d6bda27560e01b815260040160405180910390fd5b805160208201fd5b80356001600160a01b038116811461111a575f5ffd5b919050565b5f5f83601f84011261112f575f5ffd5b5081356001600160401b03811115611145575f5ffd5b60208301915083602082850101111561115c575f5ffd5b9250929050565b5f5f5f5f5f5f5f60c0888a031215611179575f5ffd5b61118288611104565b96506020880135955060408801356001600160401b038111156111a3575f5ffd5b6111af8a828b0161111f565b989b979a50986060810135976080820135975060a09091013595509350505050565b5f602082840312156111e1575f5ffd5b81356001600160e01b03198116811461083e575f5ffd5b5f5f5f5f5f5f60a0878903121561120d575f5ffd5b61121687611104565b95506020870135945060408701356001600160401b03811115611237575f5ffd5b61124389828a0161111f565b979a9699509760608101359660809091013595509350505050565b5f6020828403121561126e575f5ffd5b5035919050565b634e487b7160e01b5f52604160045260245ffd5b604051601f8201601f191681016001600160401b03811182821017156112b1576112b1611275565b604052919050565b5f82601f8301126112c8575f5ffd5b81356001600160401b038111156112e1576112e1611275565b6112f4601f8201601f1916602001611289565b818152846020838601011115611308575f5ffd5b816020850160208301375f918101602001919091529392505050565b5f5f5f5f60808587031215611337575f5ffd5b61134085611104565b935061134e60208601611104565b92506040850135915060608501356001600160401b0381111561136f575f5ffd5b61137b878288016112b9565b91505092959194509250565b5f5f60408385031215611398575f5ffd5b823591506113a860208401611104565b90509250929050565b634e487b7160e01b5f52602160045260245ffd5b60208101600483106113e557634e487b7160e01b5f52602160045260245ffd5b91905290565b5f5f83601f8401126113fb575f5ffd5b5081356001600160401b03811115611411575f5ffd5b6020830191508360208260051b850101111561115c575f5ffd5b5f5f5f5f5f5f5f5f5f60c08a8c031215611443575f5ffd5b89356001600160401b03811115611458575f5ffd5b6114648c828d016113eb565b909a5098505060208a01356001600160401b03811115611482575f5ffd5b61148e8c828d016113eb565b90985096505060408a01356001600160401b038111156114ac575f5ffd5b6114b88c828d016113eb565b9a9d999c50979a969997986060880135976080810135975060a0013595509350505050565b5f5f5f5f5f5f5f5f60a0898b0312156114f4575f5ffd5b88356001600160401b03811115611509575f5ffd5b6115158b828c016113eb565b90995097505060208901356001600160401b03811115611533575f5ffd5b61153f8b828c016113eb565b90975095505060408901356001600160401b0381111561155d575f5ffd5b6115698b828c016113eb565b999c989b509699959896976060870135966080013595509350505050565b5f82601f830112611596575f5ffd5b81356001600160401b038111156115af576115af611275565b8060051b6115bf60208201611289565b918252602081850181019290810190868411156115da575f5ffd5b6020860192505b838310156115fc5782358252602092830192909101906115e1565b9695505050505050565b5f5f5f5f5f60a0868803121561161a575f5ffd5b61162386611104565b945061163160208701611104565b935060408601356001600160401b0381111561164b575f5ffd5b61165788828901611587565b93505060608601356001600160401b03811115611672575f5ffd5b61167e88828901611587565b92505060808601356001600160401b03811115611699575f5ffd5b6116a5888289016112b9565b9150509295509295909350565b5f5f5f5f5f60a086880312156116c6575f5ffd5b6116cf86611104565b94506116dd60208701611104565b9350604086013592506060860135915060808601356001600160401b03811115611699575f5ffd5b81835281816020850137505f828201602090810191909152601f909101601f19169091010190565b60018060a01b038716815285602082015260a060408201525f61175460a083018688611705565b60608301949094525060800152949350505050565b60018060a01b0385168152836020820152606060408201525f6115fc606083018486611705565b634e487b7160e01b5f52603260045260245ffd5b5f602082840312156117b4575f5ffd5b61083e82611104565b5f5f8335601e198436030181126117d2575f5ffd5b8301803591506001600160401b038211156117eb575f5ffd5b60200191503681900382131561115c575f5ffd5b5f8383855260208501945060208460051b820101835f5b8681101561188757838303601f19018852813536879003601e1901811261183b575f5ffd5b86016020810190356001600160401b03811115611856575f5ffd5b803603821315611864575f5ffd5b61186f858284611705565b60209a8b019a90955093909301925050600101611816565b50909695505050505050565b60a080825281018890525f8960c08301825b8b8110156118d3576001600160a01b036118be84611104565b168252602092830192909101906001016118a5565b5083810360208501528881526001600160fb1b038911156118f2575f5ffd5b8860051b9150818a6020830137018281036020908101604085015261191a90820187896117ff565b60608401959095525050608001529695505050505050565b8082018082111561069557634e487b7160e01b5f52601160045260245ffd5b818382375f910190815291905056fea2646970667358221220b15571ce3bcbbdc8ae740f1513865c342fe905cca762d8f8d002c4b6dc294a0764736f6c634300081b0033", - "deployedBytecode": "0x6080604052600436106101b2575f3560e01c80638065657f116100e7578063bc197c8111610087578063d547741f11610062578063d547741f14610546578063e38335e514610565578063f23a6e6114610578578063f27a0c92146105a3575f5ffd5b8063bc197c81146104d1578063c4d252f5146104fc578063d45c44351461051b575f5ffd5b806391d14854116100c257806391d148541461044d578063a217fddf1461046c578063b08e51c01461047f578063b1c5f427146104b2575f5ffd5b80638065657f146103dc5780638f2a0bb0146103fb5780638f61f4f51461041a575f5ffd5b80632ab0f5291161015257806336568abe1161012d57806336568abe14610353578063584b153e1461037257806364d62353146103915780637958004c146103b0575f5ffd5b80632ab0f529146102f65780632f2ff15d1461031557806331d5075014610334575f5ffd5b8063134008d31161018d578063134008d31461025357806313bc9f2014610266578063150b7a0214610285578063248a9ca3146102c8575f5ffd5b806301d5062a146101bd57806301ffc9a7146101de57806307bd026514610212575f5ffd5b366101b957005b5f5ffd5b3480156101c8575f5ffd5b506101dc6101d7366004611163565b6105b7565b005b3480156101e9575f5ffd5b506101fd6101f83660046111d1565b61068b565b60405190151581526020015b60405180910390f35b34801561021d575f5ffd5b506102457fd8aa0f3194971a2a116679f7c2090f6939c8d4e01a2a8d7e41d55e5351469e6381565b604051908152602001610209565b6101dc6102613660046111f8565b61069b565b348015610271575f5ffd5b506101fd61028036600461125e565b61074d565b348015610290575f5ffd5b506102af61029f366004611324565b630a85bd0160e11b949350505050565b6040516001600160e01b03199091168152602001610209565b3480156102d3575f5ffd5b506102456102e236600461125e565b5f9081526020819052604090206001015490565b348015610301575f5ffd5b506101fd61031036600461125e565b610772565b348015610320575f5ffd5b506101dc61032f366004611387565b61077a565b34801561033f575f5ffd5b506101fd61034e36600461125e565b6107a4565b34801561035e575f5ffd5b506101dc61036d366004611387565b6107c8565b34801561037d575f5ffd5b506101fd61038c36600461125e565b610800565b34801561039c575f5ffd5b506101dc6103ab36600461125e565b610845565b3480156103bb575f5ffd5b506103cf6103ca36600461125e565b6108b8565b60405161020991906113c5565b3480156103e7575f5ffd5b506102456103f63660046111f8565b610900565b348015610406575f5ffd5b506101dc61041536600461142b565b61093e565b348015610425575f5ffd5b506102457fb09aa5aeb3702cfd50b6b62bc4532604938f21248a27a1d5ca736082b6819cc181565b348015610458575f5ffd5b506101fd610467366004611387565b610aca565b348015610477575f5ffd5b506102455f81565b34801561048a575f5ffd5b506102457ffd643c72710c63c0180259aba6b2d05451e3591a24e58b62239378085726f78381565b3480156104bd575f5ffd5b506102456104cc3660046114dd565b610af2565b3480156104dc575f5ffd5b506102af6104eb366004611606565b63bc197c8160e01b95945050505050565b348015610507575f5ffd5b506101dc61051636600461125e565b610b36565b348015610526575f5ffd5b5061024561053536600461125e565b5f9081526001602052604090205490565b348015610551575f5ffd5b506101dc610560366004611387565b610be0565b6101dc6105733660046114dd565b610c04565b348015610583575f5ffd5b506102af6105923660046116b2565b63f23a6e6160e01b95945050505050565b3480156105ae575f5ffd5b50600254610245565b7fb09aa5aeb3702cfd50b6b62bc4532604938f21248a27a1d5ca736082b6819cc16105e181610d85565b5f6105f0898989898989610900565b90506105fc8184610d92565b5f817f4cf4410cc57040e44862ef0f45f3dd5a5e02db8eb8add648d4b0e236f1d07dca8b8b8b8b8b8a6040516106379695949392919061172d565b60405180910390a3831561068057807f20fda5fd27a1ea7bf5b9567f143ac5470bb059374a27e8f67cb44f946f6d03878560405161067791815260200190565b60405180910390a25b505050505050505050565b5f61069582610e23565b92915050565b7fd8aa0f3194971a2a116679f7c2090f6939c8d4e01a2a8d7e41d55e5351469e636106c6815f610aca565b6106d4576106d48133610e47565b5f6106e3888888888888610900565b90506106ef8185610e84565b6106fb88888888610ed2565b5f817fc2617efa69bab66782fa219543714338489c4e9e178271560a91b82c3f612b588a8a8a8a6040516107329493929190611769565b60405180910390a361074381610f46565b5050505050505050565b5f60025b61075a836108b8565b600381111561076b5761076b6113b1565b1492915050565b5f6003610751565b5f8281526020819052604090206001015461079481610d85565b61079e8383610f71565b50505050565b5f806107af836108b8565b60038111156107c0576107c06113b1565b141592915050565b6001600160a01b03811633146107f15760405163334bd91960e11b815260040160405180910390fd5b6107fb8282611000565b505050565b5f5f61080b836108b8565b90506001816003811115610821576108216113b1565b148061083e5750600281600381111561083c5761083c6113b1565b145b9392505050565b333081146108765760405163e2850c5960e01b81526001600160a01b03821660048201526024015b60405180910390fd5b60025460408051918252602082018490527f11c24f4ead16507c69ac467fbd5e4eed5fb5c699626d2cc6d66421df253886d5910160405180910390a150600255565b5f81815260016020526040812054805f036108d557505f92915050565b600181036108e65750600392915050565b428111156108f75750600192915050565b50600292915050565b5f86868686868660405160200161091c9695949392919061172d565b6040516020818303038152906040528051906020012090509695505050505050565b7fb09aa5aeb3702cfd50b6b62bc4532604938f21248a27a1d5ca736082b6819cc161096881610d85565b88871415806109775750888514155b156109a9576040516001624fcdef60e01b03198152600481018a9052602481018690526044810188905260640161086d565b5f6109ba8b8b8b8b8b8b8b8b610af2565b90506109c68184610d92565b5f5b8a811015610a7b5780827f4cf4410cc57040e44862ef0f45f3dd5a5e02db8eb8add648d4b0e236f1d07dca8e8e85818110610a0557610a05611790565b9050602002016020810190610a1a91906117a4565b8d8d86818110610a2c57610a2c611790565b905060200201358c8c87818110610a4557610a45611790565b9050602002810190610a5791906117bd565b8c8b604051610a6b9695949392919061172d565b60405180910390a36001016109c8565b508315610abd57807f20fda5fd27a1ea7bf5b9567f143ac5470bb059374a27e8f67cb44f946f6d038785604051610ab491815260200190565b60405180910390a25b5050505050505050505050565b5f918252602082815260408084206001600160a01b0393909316845291905290205460ff1690565b5f8888888888888888604051602001610b12989796959493929190611893565b60405160208183030381529060405280519060200120905098975050505050505050565b7ffd643c72710c63c0180259aba6b2d05451e3591a24e58b62239378085726f783610b6081610d85565b610b6982610800565b610ba55781610b786002611069565b610b826001611069565b604051635ead8eb560e01b8152600481019390935217602482015260440161086d565b5f828152600160205260408082208290555183917fbaa1eb22f2a492ba1a5fea61b8df4d27c6c8b5f3971e63bb58fa14ff72eedb7091a25050565b5f82815260208190526040902060010154610bfa81610d85565b61079e8383611000565b7fd8aa0f3194971a2a116679f7c2090f6939c8d4e01a2a8d7e41d55e5351469e63610c2f815f610aca565b610c3d57610c3d8133610e47565b8786141580610c4c5750878414155b15610c7e576040516001624fcdef60e01b0319815260048101899052602481018590526044810187905260640161086d565b5f610c8f8a8a8a8a8a8a8a8a610af2565b9050610c9b8185610e84565b5f5b89811015610d6f575f8b8b83818110610cb857610cb8611790565b9050602002016020810190610ccd91906117a4565b90505f8a8a84818110610ce257610ce2611790565b905060200201359050365f8a8a86818110610cff57610cff611790565b9050602002810190610d1191906117bd565b91509150610d2184848484610ed2565b84867fc2617efa69bab66782fa219543714338489c4e9e178271560a91b82c3f612b5886868686604051610d589493929190611769565b60405180910390a350505050806001019050610c9d565b50610d7981610f46565b50505050505050505050565b610d8f8133610e47565b50565b610d9b826107a4565b15610dcc5781610daa5f611069565b604051635ead8eb560e01b81526004810192909252602482015260440161086d565b5f610dd660025490565b905080821015610e0357604051635433660960e01b8152600481018390526024810182905260440161086d565b610e0d8242611932565b5f93845260016020526040909320929092555050565b5f6001600160e01b03198216630271189760e51b148061069557506106958261108b565b610e518282610aca565b610e805760405163e2517d3f60e01b81526001600160a01b03821660048201526024810183905260440161086d565b5050565b610e8d8261074d565b610e9c5781610daa6002611069565b8015801590610eb15750610eaf81610772565b155b15610e805760405163121534c360e31b81526004810182905260240161086d565b5f5f856001600160a01b0316858585604051610eef929190611951565b5f6040518083038185875af1925050503d805f8114610f29576040519150601f19603f3d011682016040523d82523d5f602084013e610f2e565b606091505b5091509150610f3d82826110bf565b50505050505050565b610f4f8161074d565b610f5e5780610daa6002611069565b5f90815260016020819052604090912055565b5f610f7c8383610aca565b610ff9575f838152602081815260408083206001600160a01b03861684529091529020805460ff19166001179055610fb13390565b6001600160a01b0316826001600160a01b0316847f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a4506001610695565b505f610695565b5f61100b8383610aca565b15610ff9575f838152602081815260408083206001600160a01b0386168085529252808320805460ff1916905551339286917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9190a4506001610695565b5f81600381111561107c5761107c6113b1565b600160ff919091161b92915050565b5f6001600160e01b03198216637965db0b60e01b148061069557506301ffc9a760e01b6001600160e01b0319831614610695565b606082156110ce575080610695565b8151156110e3576110de826110fc565b610695565b60405163d6bda27560e01b815260040160405180910390fd5b805160208201fd5b80356001600160a01b038116811461111a575f5ffd5b919050565b5f5f83601f84011261112f575f5ffd5b5081356001600160401b03811115611145575f5ffd5b60208301915083602082850101111561115c575f5ffd5b9250929050565b5f5f5f5f5f5f5f60c0888a031215611179575f5ffd5b61118288611104565b96506020880135955060408801356001600160401b038111156111a3575f5ffd5b6111af8a828b0161111f565b989b979a50986060810135976080820135975060a09091013595509350505050565b5f602082840312156111e1575f5ffd5b81356001600160e01b03198116811461083e575f5ffd5b5f5f5f5f5f5f60a0878903121561120d575f5ffd5b61121687611104565b95506020870135945060408701356001600160401b03811115611237575f5ffd5b61124389828a0161111f565b979a9699509760608101359660809091013595509350505050565b5f6020828403121561126e575f5ffd5b5035919050565b634e487b7160e01b5f52604160045260245ffd5b604051601f8201601f191681016001600160401b03811182821017156112b1576112b1611275565b604052919050565b5f82601f8301126112c8575f5ffd5b81356001600160401b038111156112e1576112e1611275565b6112f4601f8201601f1916602001611289565b818152846020838601011115611308575f5ffd5b816020850160208301375f918101602001919091529392505050565b5f5f5f5f60808587031215611337575f5ffd5b61134085611104565b935061134e60208601611104565b92506040850135915060608501356001600160401b0381111561136f575f5ffd5b61137b878288016112b9565b91505092959194509250565b5f5f60408385031215611398575f5ffd5b823591506113a860208401611104565b90509250929050565b634e487b7160e01b5f52602160045260245ffd5b60208101600483106113e557634e487b7160e01b5f52602160045260245ffd5b91905290565b5f5f83601f8401126113fb575f5ffd5b5081356001600160401b03811115611411575f5ffd5b6020830191508360208260051b850101111561115c575f5ffd5b5f5f5f5f5f5f5f5f5f60c08a8c031215611443575f5ffd5b89356001600160401b03811115611458575f5ffd5b6114648c828d016113eb565b909a5098505060208a01356001600160401b03811115611482575f5ffd5b61148e8c828d016113eb565b90985096505060408a01356001600160401b038111156114ac575f5ffd5b6114b88c828d016113eb565b9a9d999c50979a969997986060880135976080810135975060a0013595509350505050565b5f5f5f5f5f5f5f5f60a0898b0312156114f4575f5ffd5b88356001600160401b03811115611509575f5ffd5b6115158b828c016113eb565b90995097505060208901356001600160401b03811115611533575f5ffd5b61153f8b828c016113eb565b90975095505060408901356001600160401b0381111561155d575f5ffd5b6115698b828c016113eb565b999c989b509699959896976060870135966080013595509350505050565b5f82601f830112611596575f5ffd5b81356001600160401b038111156115af576115af611275565b8060051b6115bf60208201611289565b918252602081850181019290810190868411156115da575f5ffd5b6020860192505b838310156115fc5782358252602092830192909101906115e1565b9695505050505050565b5f5f5f5f5f60a0868803121561161a575f5ffd5b61162386611104565b945061163160208701611104565b935060408601356001600160401b0381111561164b575f5ffd5b61165788828901611587565b93505060608601356001600160401b03811115611672575f5ffd5b61167e88828901611587565b92505060808601356001600160401b03811115611699575f5ffd5b6116a5888289016112b9565b9150509295509295909350565b5f5f5f5f5f60a086880312156116c6575f5ffd5b6116cf86611104565b94506116dd60208701611104565b9350604086013592506060860135915060808601356001600160401b03811115611699575f5ffd5b81835281816020850137505f828201602090810191909152601f909101601f19169091010190565b60018060a01b038716815285602082015260a060408201525f61175460a083018688611705565b60608301949094525060800152949350505050565b60018060a01b0385168152836020820152606060408201525f6115fc606083018486611705565b634e487b7160e01b5f52603260045260245ffd5b5f602082840312156117b4575f5ffd5b61083e82611104565b5f5f8335601e198436030181126117d2575f5ffd5b8301803591506001600160401b038211156117eb575f5ffd5b60200191503681900382131561115c575f5ffd5b5f8383855260208501945060208460051b820101835f5b8681101561188757838303601f19018852813536879003601e1901811261183b575f5ffd5b86016020810190356001600160401b03811115611856575f5ffd5b803603821315611864575f5ffd5b61186f858284611705565b60209a8b019a90955093909301925050600101611816565b50909695505050505050565b60a080825281018890525f8960c08301825b8b8110156118d3576001600160a01b036118be84611104565b168252602092830192909101906001016118a5565b5083810360208501528881526001600160fb1b038911156118f2575f5ffd5b8860051b9150818a6020830137018281036020908101604085015261191a90820187896117ff565b60608401959095525050608001529695505050505050565b8082018082111561069557634e487b7160e01b5f52601160045260245ffd5b818382375f910190815291905056fea2646970667358221220b15571ce3bcbbdc8ae740f1513865c342fe905cca762d8f8d002c4b6dc294a0764736f6c634300081b0033", + "bytecode": "0x608060405234801561000f575f5ffd5b50604051611d2c380380611d2c83398101604081905261002e916102f6565b6100385f3061017b565b506001600160a01b03811615610054576100525f8261017b565b505b5f5b83518110156100e8576100a87fb09aa5aeb3702cfd50b6b62bc4532604938f21248a27a1d5ca736082b6819cc185838151811061009557610095610375565b602002602001015161017b60201b60201c565b506100df7ffd643c72710c63c0180259aba6b2d05451e3591a24e58b62239378085726f78385838151811061009557610095610375565b50600101610056565b505f5b82518110156101335761012a7fd8aa0f3194971a2a116679f7c2090f6939c8d4e01a2a8d7e41d55e5351469e6384838151811061009557610095610375565b506001016100eb565b506002849055604080515f8152602081018690527f11c24f4ead16507c69ac467fbd5e4eed5fb5c699626d2cc6d66421df253886d5910160405180910390a150505050610389565b5f828152602081815260408083206001600160a01b038516845290915281205460ff1661021b575f838152602081815260408083206001600160a01b03861684529091529020805460ff191660011790556101d33390565b6001600160a01b0316826001600160a01b0316847f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a450600161021e565b505f5b92915050565b634e487b7160e01b5f52604160045260245ffd5b80516001600160a01b038116811461024e575f5ffd5b919050565b5f82601f830112610262575f5ffd5b81516001600160401b0381111561027b5761027b610224565b604051600582901b90603f8201601f191681016001600160401b03811182821017156102a9576102a9610224565b6040529182526020818501810192908101868411156102c6575f5ffd5b6020860192505b838310156102ec576102de83610238565b8152602092830192016102cd565b5095945050505050565b5f5f5f5f60808587031215610309575f5ffd5b845160208601519094506001600160401b03811115610326575f5ffd5b61033287828801610253565b604087015190945090506001600160401b0381111561034f575f5ffd5b61035b87828801610253565b92505061036a60608601610238565b905092959194509250565b634e487b7160e01b5f52603260045260245ffd5b611996806103965f395ff3fe6080604052600436106101b2575f3560e01c80638065657f116100e7578063bc197c8111610087578063d547741f11610062578063d547741f14610546578063e38335e514610565578063f23a6e6114610578578063f27a0c92146105a3575f5ffd5b8063bc197c81146104d1578063c4d252f5146104fc578063d45c44351461051b575f5ffd5b806391d14854116100c257806391d148541461044d578063a217fddf1461046c578063b08e51c01461047f578063b1c5f427146104b2575f5ffd5b80638065657f146103dc5780638f2a0bb0146103fb5780638f61f4f51461041a575f5ffd5b80632ab0f5291161015257806336568abe1161012d57806336568abe14610353578063584b153e1461037257806364d62353146103915780637958004c146103b0575f5ffd5b80632ab0f529146102f65780632f2ff15d1461031557806331d5075014610334575f5ffd5b8063134008d31161018d578063134008d31461025357806313bc9f2014610266578063150b7a0214610285578063248a9ca3146102c8575f5ffd5b806301d5062a146101bd57806301ffc9a7146101de57806307bd026514610212575f5ffd5b366101b957005b5f5ffd5b3480156101c8575f5ffd5b506101dc6101d7366004611163565b6105b7565b005b3480156101e9575f5ffd5b506101fd6101f83660046111d1565b61068b565b60405190151581526020015b60405180910390f35b34801561021d575f5ffd5b506102457fd8aa0f3194971a2a116679f7c2090f6939c8d4e01a2a8d7e41d55e5351469e6381565b604051908152602001610209565b6101dc6102613660046111f8565b61069b565b348015610271575f5ffd5b506101fd61028036600461125e565b61074d565b348015610290575f5ffd5b506102af61029f366004611324565b630a85bd0160e11b949350505050565b6040516001600160e01b03199091168152602001610209565b3480156102d3575f5ffd5b506102456102e236600461125e565b5f9081526020819052604090206001015490565b348015610301575f5ffd5b506101fd61031036600461125e565b610772565b348015610320575f5ffd5b506101dc61032f366004611387565b61077a565b34801561033f575f5ffd5b506101fd61034e36600461125e565b6107a4565b34801561035e575f5ffd5b506101dc61036d366004611387565b6107c8565b34801561037d575f5ffd5b506101fd61038c36600461125e565b610800565b34801561039c575f5ffd5b506101dc6103ab36600461125e565b610845565b3480156103bb575f5ffd5b506103cf6103ca36600461125e565b6108b8565b60405161020991906113c5565b3480156103e7575f5ffd5b506102456103f63660046111f8565b610900565b348015610406575f5ffd5b506101dc61041536600461142b565b61093e565b348015610425575f5ffd5b506102457fb09aa5aeb3702cfd50b6b62bc4532604938f21248a27a1d5ca736082b6819cc181565b348015610458575f5ffd5b506101fd610467366004611387565b610aca565b348015610477575f5ffd5b506102455f81565b34801561048a575f5ffd5b506102457ffd643c72710c63c0180259aba6b2d05451e3591a24e58b62239378085726f78381565b3480156104bd575f5ffd5b506102456104cc3660046114dd565b610af2565b3480156104dc575f5ffd5b506102af6104eb366004611606565b63bc197c8160e01b95945050505050565b348015610507575f5ffd5b506101dc61051636600461125e565b610b36565b348015610526575f5ffd5b5061024561053536600461125e565b5f9081526001602052604090205490565b348015610551575f5ffd5b506101dc610560366004611387565b610be0565b6101dc6105733660046114dd565b610c04565b348015610583575f5ffd5b506102af6105923660046116b2565b63f23a6e6160e01b95945050505050565b3480156105ae575f5ffd5b50600254610245565b7fb09aa5aeb3702cfd50b6b62bc4532604938f21248a27a1d5ca736082b6819cc16105e181610d85565b5f6105f0898989898989610900565b90506105fc8184610d92565b5f817f4cf4410cc57040e44862ef0f45f3dd5a5e02db8eb8add648d4b0e236f1d07dca8b8b8b8b8b8a6040516106379695949392919061172d565b60405180910390a3831561068057807f20fda5fd27a1ea7bf5b9567f143ac5470bb059374a27e8f67cb44f946f6d03878560405161067791815260200190565b60405180910390a25b505050505050505050565b5f61069582610e23565b92915050565b7fd8aa0f3194971a2a116679f7c2090f6939c8d4e01a2a8d7e41d55e5351469e636106c6815f610aca565b6106d4576106d48133610e47565b5f6106e3888888888888610900565b90506106ef8185610e84565b6106fb88888888610ed2565b5f817fc2617efa69bab66782fa219543714338489c4e9e178271560a91b82c3f612b588a8a8a8a6040516107329493929190611769565b60405180910390a361074381610f46565b5050505050505050565b5f60025b61075a836108b8565b600381111561076b5761076b6113b1565b1492915050565b5f6003610751565b5f8281526020819052604090206001015461079481610d85565b61079e8383610f71565b50505050565b5f806107af836108b8565b60038111156107c0576107c06113b1565b141592915050565b6001600160a01b03811633146107f15760405163334bd91960e11b815260040160405180910390fd5b6107fb8282611000565b505050565b5f5f61080b836108b8565b90506001816003811115610821576108216113b1565b148061083e5750600281600381111561083c5761083c6113b1565b145b9392505050565b333081146108765760405163e2850c5960e01b81526001600160a01b03821660048201526024015b60405180910390fd5b60025460408051918252602082018490527f11c24f4ead16507c69ac467fbd5e4eed5fb5c699626d2cc6d66421df253886d5910160405180910390a150600255565b5f81815260016020526040812054805f036108d557505f92915050565b600181036108e65750600392915050565b428111156108f75750600192915050565b50600292915050565b5f86868686868660405160200161091c9695949392919061172d565b6040516020818303038152906040528051906020012090509695505050505050565b7fb09aa5aeb3702cfd50b6b62bc4532604938f21248a27a1d5ca736082b6819cc161096881610d85565b88871415806109775750888514155b156109a9576040516001624fcdef60e01b03198152600481018a9052602481018690526044810188905260640161086d565b5f6109ba8b8b8b8b8b8b8b8b610af2565b90506109c68184610d92565b5f5b8a811015610a7b5780827f4cf4410cc57040e44862ef0f45f3dd5a5e02db8eb8add648d4b0e236f1d07dca8e8e85818110610a0557610a05611790565b9050602002016020810190610a1a91906117a4565b8d8d86818110610a2c57610a2c611790565b905060200201358c8c87818110610a4557610a45611790565b9050602002810190610a5791906117bd565b8c8b604051610a6b9695949392919061172d565b60405180910390a36001016109c8565b508315610abd57807f20fda5fd27a1ea7bf5b9567f143ac5470bb059374a27e8f67cb44f946f6d038785604051610ab491815260200190565b60405180910390a25b5050505050505050505050565b5f918252602082815260408084206001600160a01b0393909316845291905290205460ff1690565b5f8888888888888888604051602001610b12989796959493929190611893565b60405160208183030381529060405280519060200120905098975050505050505050565b7ffd643c72710c63c0180259aba6b2d05451e3591a24e58b62239378085726f783610b6081610d85565b610b6982610800565b610ba55781610b786002611069565b610b826001611069565b604051635ead8eb560e01b8152600481019390935217602482015260440161086d565b5f828152600160205260408082208290555183917fbaa1eb22f2a492ba1a5fea61b8df4d27c6c8b5f3971e63bb58fa14ff72eedb7091a25050565b5f82815260208190526040902060010154610bfa81610d85565b61079e8383611000565b7fd8aa0f3194971a2a116679f7c2090f6939c8d4e01a2a8d7e41d55e5351469e63610c2f815f610aca565b610c3d57610c3d8133610e47565b8786141580610c4c5750878414155b15610c7e576040516001624fcdef60e01b0319815260048101899052602481018590526044810187905260640161086d565b5f610c8f8a8a8a8a8a8a8a8a610af2565b9050610c9b8185610e84565b5f5b89811015610d6f575f8b8b83818110610cb857610cb8611790565b9050602002016020810190610ccd91906117a4565b90505f8a8a84818110610ce257610ce2611790565b905060200201359050365f8a8a86818110610cff57610cff611790565b9050602002810190610d1191906117bd565b91509150610d2184848484610ed2565b84867fc2617efa69bab66782fa219543714338489c4e9e178271560a91b82c3f612b5886868686604051610d589493929190611769565b60405180910390a350505050806001019050610c9d565b50610d7981610f46565b50505050505050505050565b610d8f8133610e47565b50565b610d9b826107a4565b15610dcc5781610daa5f611069565b604051635ead8eb560e01b81526004810192909252602482015260440161086d565b5f610dd660025490565b905080821015610e0357604051635433660960e01b8152600481018390526024810182905260440161086d565b610e0d8242611932565b5f93845260016020526040909320929092555050565b5f6001600160e01b03198216630271189760e51b148061069557506106958261108b565b610e518282610aca565b610e805760405163e2517d3f60e01b81526001600160a01b03821660048201526024810183905260440161086d565b5050565b610e8d8261074d565b610e9c5781610daa6002611069565b8015801590610eb15750610eaf81610772565b155b15610e805760405163121534c360e31b81526004810182905260240161086d565b5f5f856001600160a01b0316858585604051610eef929190611951565b5f6040518083038185875af1925050503d805f8114610f29576040519150601f19603f3d011682016040523d82523d5f602084013e610f2e565b606091505b5091509150610f3d82826110bf565b50505050505050565b610f4f8161074d565b610f5e5780610daa6002611069565b5f90815260016020819052604090912055565b5f610f7c8383610aca565b610ff9575f838152602081815260408083206001600160a01b03861684529091529020805460ff19166001179055610fb13390565b6001600160a01b0316826001600160a01b0316847f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a4506001610695565b505f610695565b5f61100b8383610aca565b15610ff9575f838152602081815260408083206001600160a01b0386168085529252808320805460ff1916905551339286917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9190a4506001610695565b5f81600381111561107c5761107c6113b1565b600160ff919091161b92915050565b5f6001600160e01b03198216637965db0b60e01b148061069557506301ffc9a760e01b6001600160e01b0319831614610695565b606082156110ce575080610695565b8151156110e3576110de826110fc565b610695565b60405163d6bda27560e01b815260040160405180910390fd5b805160208201fd5b80356001600160a01b038116811461111a575f5ffd5b919050565b5f5f83601f84011261112f575f5ffd5b5081356001600160401b03811115611145575f5ffd5b60208301915083602082850101111561115c575f5ffd5b9250929050565b5f5f5f5f5f5f5f60c0888a031215611179575f5ffd5b61118288611104565b96506020880135955060408801356001600160401b038111156111a3575f5ffd5b6111af8a828b0161111f565b989b979a50986060810135976080820135975060a09091013595509350505050565b5f602082840312156111e1575f5ffd5b81356001600160e01b03198116811461083e575f5ffd5b5f5f5f5f5f5f60a0878903121561120d575f5ffd5b61121687611104565b95506020870135945060408701356001600160401b03811115611237575f5ffd5b61124389828a0161111f565b979a9699509760608101359660809091013595509350505050565b5f6020828403121561126e575f5ffd5b5035919050565b634e487b7160e01b5f52604160045260245ffd5b604051601f8201601f191681016001600160401b03811182821017156112b1576112b1611275565b604052919050565b5f82601f8301126112c8575f5ffd5b81356001600160401b038111156112e1576112e1611275565b6112f4601f8201601f1916602001611289565b818152846020838601011115611308575f5ffd5b816020850160208301375f918101602001919091529392505050565b5f5f5f5f60808587031215611337575f5ffd5b61134085611104565b935061134e60208601611104565b92506040850135915060608501356001600160401b0381111561136f575f5ffd5b61137b878288016112b9565b91505092959194509250565b5f5f60408385031215611398575f5ffd5b823591506113a860208401611104565b90509250929050565b634e487b7160e01b5f52602160045260245ffd5b60208101600483106113e557634e487b7160e01b5f52602160045260245ffd5b91905290565b5f5f83601f8401126113fb575f5ffd5b5081356001600160401b03811115611411575f5ffd5b6020830191508360208260051b850101111561115c575f5ffd5b5f5f5f5f5f5f5f5f5f60c08a8c031215611443575f5ffd5b89356001600160401b03811115611458575f5ffd5b6114648c828d016113eb565b909a5098505060208a01356001600160401b03811115611482575f5ffd5b61148e8c828d016113eb565b90985096505060408a01356001600160401b038111156114ac575f5ffd5b6114b88c828d016113eb565b9a9d999c50979a969997986060880135976080810135975060a0013595509350505050565b5f5f5f5f5f5f5f5f60a0898b0312156114f4575f5ffd5b88356001600160401b03811115611509575f5ffd5b6115158b828c016113eb565b90995097505060208901356001600160401b03811115611533575f5ffd5b61153f8b828c016113eb565b90975095505060408901356001600160401b0381111561155d575f5ffd5b6115698b828c016113eb565b999c989b509699959896976060870135966080013595509350505050565b5f82601f830112611596575f5ffd5b81356001600160401b038111156115af576115af611275565b8060051b6115bf60208201611289565b918252602081850181019290810190868411156115da575f5ffd5b6020860192505b838310156115fc5782358252602092830192909101906115e1565b9695505050505050565b5f5f5f5f5f60a0868803121561161a575f5ffd5b61162386611104565b945061163160208701611104565b935060408601356001600160401b0381111561164b575f5ffd5b61165788828901611587565b93505060608601356001600160401b03811115611672575f5ffd5b61167e88828901611587565b92505060808601356001600160401b03811115611699575f5ffd5b6116a5888289016112b9565b9150509295509295909350565b5f5f5f5f5f60a086880312156116c6575f5ffd5b6116cf86611104565b94506116dd60208701611104565b9350604086013592506060860135915060808601356001600160401b03811115611699575f5ffd5b81835281816020850137505f828201602090810191909152601f909101601f19169091010190565b60018060a01b038716815285602082015260a060408201525f61175460a083018688611705565b60608301949094525060800152949350505050565b60018060a01b0385168152836020820152606060408201525f6115fc606083018486611705565b634e487b7160e01b5f52603260045260245ffd5b5f602082840312156117b4575f5ffd5b61083e82611104565b5f5f8335601e198436030181126117d2575f5ffd5b8301803591506001600160401b038211156117eb575f5ffd5b60200191503681900382131561115c575f5ffd5b5f8383855260208501945060208460051b820101835f5b8681101561188757838303601f19018852813536879003601e1901811261183b575f5ffd5b86016020810190356001600160401b03811115611856575f5ffd5b803603821315611864575f5ffd5b61186f858284611705565b60209a8b019a90955093909301925050600101611816565b50909695505050505050565b60a080825281018890525f8960c08301825b8b8110156118d3576001600160a01b036118be84611104565b168252602092830192909101906001016118a5565b5083810360208501528881526001600160fb1b038911156118f2575f5ffd5b8860051b9150818a6020830137018281036020908101604085015261191a90820187896117ff565b60608401959095525050608001529695505050505050565b8082018082111561069557634e487b7160e01b5f52601160045260245ffd5b818382375f910190815291905056fea2646970667358221220d4c63f366082d45995e950a2b3c403ebb8a1e7c5f5ca60d8cc36d3ee23265e4964736f6c63430008230033", + "deployedBytecode": "0x6080604052600436106101b2575f3560e01c80638065657f116100e7578063bc197c8111610087578063d547741f11610062578063d547741f14610546578063e38335e514610565578063f23a6e6114610578578063f27a0c92146105a3575f5ffd5b8063bc197c81146104d1578063c4d252f5146104fc578063d45c44351461051b575f5ffd5b806391d14854116100c257806391d148541461044d578063a217fddf1461046c578063b08e51c01461047f578063b1c5f427146104b2575f5ffd5b80638065657f146103dc5780638f2a0bb0146103fb5780638f61f4f51461041a575f5ffd5b80632ab0f5291161015257806336568abe1161012d57806336568abe14610353578063584b153e1461037257806364d62353146103915780637958004c146103b0575f5ffd5b80632ab0f529146102f65780632f2ff15d1461031557806331d5075014610334575f5ffd5b8063134008d31161018d578063134008d31461025357806313bc9f2014610266578063150b7a0214610285578063248a9ca3146102c8575f5ffd5b806301d5062a146101bd57806301ffc9a7146101de57806307bd026514610212575f5ffd5b366101b957005b5f5ffd5b3480156101c8575f5ffd5b506101dc6101d7366004611163565b6105b7565b005b3480156101e9575f5ffd5b506101fd6101f83660046111d1565b61068b565b60405190151581526020015b60405180910390f35b34801561021d575f5ffd5b506102457fd8aa0f3194971a2a116679f7c2090f6939c8d4e01a2a8d7e41d55e5351469e6381565b604051908152602001610209565b6101dc6102613660046111f8565b61069b565b348015610271575f5ffd5b506101fd61028036600461125e565b61074d565b348015610290575f5ffd5b506102af61029f366004611324565b630a85bd0160e11b949350505050565b6040516001600160e01b03199091168152602001610209565b3480156102d3575f5ffd5b506102456102e236600461125e565b5f9081526020819052604090206001015490565b348015610301575f5ffd5b506101fd61031036600461125e565b610772565b348015610320575f5ffd5b506101dc61032f366004611387565b61077a565b34801561033f575f5ffd5b506101fd61034e36600461125e565b6107a4565b34801561035e575f5ffd5b506101dc61036d366004611387565b6107c8565b34801561037d575f5ffd5b506101fd61038c36600461125e565b610800565b34801561039c575f5ffd5b506101dc6103ab36600461125e565b610845565b3480156103bb575f5ffd5b506103cf6103ca36600461125e565b6108b8565b60405161020991906113c5565b3480156103e7575f5ffd5b506102456103f63660046111f8565b610900565b348015610406575f5ffd5b506101dc61041536600461142b565b61093e565b348015610425575f5ffd5b506102457fb09aa5aeb3702cfd50b6b62bc4532604938f21248a27a1d5ca736082b6819cc181565b348015610458575f5ffd5b506101fd610467366004611387565b610aca565b348015610477575f5ffd5b506102455f81565b34801561048a575f5ffd5b506102457ffd643c72710c63c0180259aba6b2d05451e3591a24e58b62239378085726f78381565b3480156104bd575f5ffd5b506102456104cc3660046114dd565b610af2565b3480156104dc575f5ffd5b506102af6104eb366004611606565b63bc197c8160e01b95945050505050565b348015610507575f5ffd5b506101dc61051636600461125e565b610b36565b348015610526575f5ffd5b5061024561053536600461125e565b5f9081526001602052604090205490565b348015610551575f5ffd5b506101dc610560366004611387565b610be0565b6101dc6105733660046114dd565b610c04565b348015610583575f5ffd5b506102af6105923660046116b2565b63f23a6e6160e01b95945050505050565b3480156105ae575f5ffd5b50600254610245565b7fb09aa5aeb3702cfd50b6b62bc4532604938f21248a27a1d5ca736082b6819cc16105e181610d85565b5f6105f0898989898989610900565b90506105fc8184610d92565b5f817f4cf4410cc57040e44862ef0f45f3dd5a5e02db8eb8add648d4b0e236f1d07dca8b8b8b8b8b8a6040516106379695949392919061172d565b60405180910390a3831561068057807f20fda5fd27a1ea7bf5b9567f143ac5470bb059374a27e8f67cb44f946f6d03878560405161067791815260200190565b60405180910390a25b505050505050505050565b5f61069582610e23565b92915050565b7fd8aa0f3194971a2a116679f7c2090f6939c8d4e01a2a8d7e41d55e5351469e636106c6815f610aca565b6106d4576106d48133610e47565b5f6106e3888888888888610900565b90506106ef8185610e84565b6106fb88888888610ed2565b5f817fc2617efa69bab66782fa219543714338489c4e9e178271560a91b82c3f612b588a8a8a8a6040516107329493929190611769565b60405180910390a361074381610f46565b5050505050505050565b5f60025b61075a836108b8565b600381111561076b5761076b6113b1565b1492915050565b5f6003610751565b5f8281526020819052604090206001015461079481610d85565b61079e8383610f71565b50505050565b5f806107af836108b8565b60038111156107c0576107c06113b1565b141592915050565b6001600160a01b03811633146107f15760405163334bd91960e11b815260040160405180910390fd5b6107fb8282611000565b505050565b5f5f61080b836108b8565b90506001816003811115610821576108216113b1565b148061083e5750600281600381111561083c5761083c6113b1565b145b9392505050565b333081146108765760405163e2850c5960e01b81526001600160a01b03821660048201526024015b60405180910390fd5b60025460408051918252602082018490527f11c24f4ead16507c69ac467fbd5e4eed5fb5c699626d2cc6d66421df253886d5910160405180910390a150600255565b5f81815260016020526040812054805f036108d557505f92915050565b600181036108e65750600392915050565b428111156108f75750600192915050565b50600292915050565b5f86868686868660405160200161091c9695949392919061172d565b6040516020818303038152906040528051906020012090509695505050505050565b7fb09aa5aeb3702cfd50b6b62bc4532604938f21248a27a1d5ca736082b6819cc161096881610d85565b88871415806109775750888514155b156109a9576040516001624fcdef60e01b03198152600481018a9052602481018690526044810188905260640161086d565b5f6109ba8b8b8b8b8b8b8b8b610af2565b90506109c68184610d92565b5f5b8a811015610a7b5780827f4cf4410cc57040e44862ef0f45f3dd5a5e02db8eb8add648d4b0e236f1d07dca8e8e85818110610a0557610a05611790565b9050602002016020810190610a1a91906117a4565b8d8d86818110610a2c57610a2c611790565b905060200201358c8c87818110610a4557610a45611790565b9050602002810190610a5791906117bd565b8c8b604051610a6b9695949392919061172d565b60405180910390a36001016109c8565b508315610abd57807f20fda5fd27a1ea7bf5b9567f143ac5470bb059374a27e8f67cb44f946f6d038785604051610ab491815260200190565b60405180910390a25b5050505050505050505050565b5f918252602082815260408084206001600160a01b0393909316845291905290205460ff1690565b5f8888888888888888604051602001610b12989796959493929190611893565b60405160208183030381529060405280519060200120905098975050505050505050565b7ffd643c72710c63c0180259aba6b2d05451e3591a24e58b62239378085726f783610b6081610d85565b610b6982610800565b610ba55781610b786002611069565b610b826001611069565b604051635ead8eb560e01b8152600481019390935217602482015260440161086d565b5f828152600160205260408082208290555183917fbaa1eb22f2a492ba1a5fea61b8df4d27c6c8b5f3971e63bb58fa14ff72eedb7091a25050565b5f82815260208190526040902060010154610bfa81610d85565b61079e8383611000565b7fd8aa0f3194971a2a116679f7c2090f6939c8d4e01a2a8d7e41d55e5351469e63610c2f815f610aca565b610c3d57610c3d8133610e47565b8786141580610c4c5750878414155b15610c7e576040516001624fcdef60e01b0319815260048101899052602481018590526044810187905260640161086d565b5f610c8f8a8a8a8a8a8a8a8a610af2565b9050610c9b8185610e84565b5f5b89811015610d6f575f8b8b83818110610cb857610cb8611790565b9050602002016020810190610ccd91906117a4565b90505f8a8a84818110610ce257610ce2611790565b905060200201359050365f8a8a86818110610cff57610cff611790565b9050602002810190610d1191906117bd565b91509150610d2184848484610ed2565b84867fc2617efa69bab66782fa219543714338489c4e9e178271560a91b82c3f612b5886868686604051610d589493929190611769565b60405180910390a350505050806001019050610c9d565b50610d7981610f46565b50505050505050505050565b610d8f8133610e47565b50565b610d9b826107a4565b15610dcc5781610daa5f611069565b604051635ead8eb560e01b81526004810192909252602482015260440161086d565b5f610dd660025490565b905080821015610e0357604051635433660960e01b8152600481018390526024810182905260440161086d565b610e0d8242611932565b5f93845260016020526040909320929092555050565b5f6001600160e01b03198216630271189760e51b148061069557506106958261108b565b610e518282610aca565b610e805760405163e2517d3f60e01b81526001600160a01b03821660048201526024810183905260440161086d565b5050565b610e8d8261074d565b610e9c5781610daa6002611069565b8015801590610eb15750610eaf81610772565b155b15610e805760405163121534c360e31b81526004810182905260240161086d565b5f5f856001600160a01b0316858585604051610eef929190611951565b5f6040518083038185875af1925050503d805f8114610f29576040519150601f19603f3d011682016040523d82523d5f602084013e610f2e565b606091505b5091509150610f3d82826110bf565b50505050505050565b610f4f8161074d565b610f5e5780610daa6002611069565b5f90815260016020819052604090912055565b5f610f7c8383610aca565b610ff9575f838152602081815260408083206001600160a01b03861684529091529020805460ff19166001179055610fb13390565b6001600160a01b0316826001600160a01b0316847f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a4506001610695565b505f610695565b5f61100b8383610aca565b15610ff9575f838152602081815260408083206001600160a01b0386168085529252808320805460ff1916905551339286917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9190a4506001610695565b5f81600381111561107c5761107c6113b1565b600160ff919091161b92915050565b5f6001600160e01b03198216637965db0b60e01b148061069557506301ffc9a760e01b6001600160e01b0319831614610695565b606082156110ce575080610695565b8151156110e3576110de826110fc565b610695565b60405163d6bda27560e01b815260040160405180910390fd5b805160208201fd5b80356001600160a01b038116811461111a575f5ffd5b919050565b5f5f83601f84011261112f575f5ffd5b5081356001600160401b03811115611145575f5ffd5b60208301915083602082850101111561115c575f5ffd5b9250929050565b5f5f5f5f5f5f5f60c0888a031215611179575f5ffd5b61118288611104565b96506020880135955060408801356001600160401b038111156111a3575f5ffd5b6111af8a828b0161111f565b989b979a50986060810135976080820135975060a09091013595509350505050565b5f602082840312156111e1575f5ffd5b81356001600160e01b03198116811461083e575f5ffd5b5f5f5f5f5f5f60a0878903121561120d575f5ffd5b61121687611104565b95506020870135945060408701356001600160401b03811115611237575f5ffd5b61124389828a0161111f565b979a9699509760608101359660809091013595509350505050565b5f6020828403121561126e575f5ffd5b5035919050565b634e487b7160e01b5f52604160045260245ffd5b604051601f8201601f191681016001600160401b03811182821017156112b1576112b1611275565b604052919050565b5f82601f8301126112c8575f5ffd5b81356001600160401b038111156112e1576112e1611275565b6112f4601f8201601f1916602001611289565b818152846020838601011115611308575f5ffd5b816020850160208301375f918101602001919091529392505050565b5f5f5f5f60808587031215611337575f5ffd5b61134085611104565b935061134e60208601611104565b92506040850135915060608501356001600160401b0381111561136f575f5ffd5b61137b878288016112b9565b91505092959194509250565b5f5f60408385031215611398575f5ffd5b823591506113a860208401611104565b90509250929050565b634e487b7160e01b5f52602160045260245ffd5b60208101600483106113e557634e487b7160e01b5f52602160045260245ffd5b91905290565b5f5f83601f8401126113fb575f5ffd5b5081356001600160401b03811115611411575f5ffd5b6020830191508360208260051b850101111561115c575f5ffd5b5f5f5f5f5f5f5f5f5f60c08a8c031215611443575f5ffd5b89356001600160401b03811115611458575f5ffd5b6114648c828d016113eb565b909a5098505060208a01356001600160401b03811115611482575f5ffd5b61148e8c828d016113eb565b90985096505060408a01356001600160401b038111156114ac575f5ffd5b6114b88c828d016113eb565b9a9d999c50979a969997986060880135976080810135975060a0013595509350505050565b5f5f5f5f5f5f5f5f60a0898b0312156114f4575f5ffd5b88356001600160401b03811115611509575f5ffd5b6115158b828c016113eb565b90995097505060208901356001600160401b03811115611533575f5ffd5b61153f8b828c016113eb565b90975095505060408901356001600160401b0381111561155d575f5ffd5b6115698b828c016113eb565b999c989b509699959896976060870135966080013595509350505050565b5f82601f830112611596575f5ffd5b81356001600160401b038111156115af576115af611275565b8060051b6115bf60208201611289565b918252602081850181019290810190868411156115da575f5ffd5b6020860192505b838310156115fc5782358252602092830192909101906115e1565b9695505050505050565b5f5f5f5f5f60a0868803121561161a575f5ffd5b61162386611104565b945061163160208701611104565b935060408601356001600160401b0381111561164b575f5ffd5b61165788828901611587565b93505060608601356001600160401b03811115611672575f5ffd5b61167e88828901611587565b92505060808601356001600160401b03811115611699575f5ffd5b6116a5888289016112b9565b9150509295509295909350565b5f5f5f5f5f60a086880312156116c6575f5ffd5b6116cf86611104565b94506116dd60208701611104565b9350604086013592506060860135915060808601356001600160401b03811115611699575f5ffd5b81835281816020850137505f828201602090810191909152601f909101601f19169091010190565b60018060a01b038716815285602082015260a060408201525f61175460a083018688611705565b60608301949094525060800152949350505050565b60018060a01b0385168152836020820152606060408201525f6115fc606083018486611705565b634e487b7160e01b5f52603260045260245ffd5b5f602082840312156117b4575f5ffd5b61083e82611104565b5f5f8335601e198436030181126117d2575f5ffd5b8301803591506001600160401b038211156117eb575f5ffd5b60200191503681900382131561115c575f5ffd5b5f8383855260208501945060208460051b820101835f5b8681101561188757838303601f19018852813536879003601e1901811261183b575f5ffd5b86016020810190356001600160401b03811115611856575f5ffd5b803603821315611864575f5ffd5b61186f858284611705565b60209a8b019a90955093909301925050600101611816565b50909695505050505050565b60a080825281018890525f8960c08301825b8b8110156118d3576001600160a01b036118be84611104565b168252602092830192909101906001016118a5565b5083810360208501528881526001600160fb1b038911156118f2575f5ffd5b8860051b9150818a6020830137018281036020908101604085015261191a90820187896117ff565b60608401959095525050608001529695505050505050565b8082018082111561069557634e487b7160e01b5f52601160045260245ffd5b818382375f910190815291905056fea2646970667358221220d4c63f366082d45995e950a2b3c403ebb8a1e7c5f5ca60d8cc36d3ee23265e4964736f6c63430008230033", "linkReferences": {}, "deployedLinkReferences": {} } diff --git a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/TransientSlot.json b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/TransientSlot.json similarity index 66% rename from dependencies/@openzeppelin-contracts-5.5.0/build/contracts/TransientSlot.json rename to dependencies/@openzeppelin-contracts-5.7.0/build/contracts/TransientSlot.json index b8e8758..2c347cf 100644 --- a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/TransientSlot.json +++ b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/TransientSlot.json @@ -3,8 +3,8 @@ "contractName": "TransientSlot", "sourceName": "contracts/utils/TransientSlot.sol", "abi": [], - "bytecode": "0x60556032600b8282823980515f1a607314602657634e487b7160e01b5f525f60045260245ffd5b305f52607381538281f3fe730000000000000000000000000000000000000000301460806040525f5ffdfea264697066735822122056e7566396f44ea053921930c5ee6ce15e653afb493fe8b609093d19f270272264736f6c634300081b0033", - "deployedBytecode": "0x730000000000000000000000000000000000000000301460806040525f5ffdfea264697066735822122056e7566396f44ea053921930c5ee6ce15e653afb493fe8b609093d19f270272264736f6c634300081b0033", + "bytecode": "0x60556032600b8282823980515f1a607314602657634e487b7160e01b5f525f60045260245ffd5b305f52607381538281f3fe730000000000000000000000000000000000000000301460806040525f5ffdfea264697066735822122095e66fed05a8363dc3eed139c17fa1a58c3a6b2b74753ec41593cf1fe5f7340b64736f6c63430008230033", + "deployedBytecode": "0x730000000000000000000000000000000000000000301460806040525f5ffdfea264697066735822122095e66fed05a8363dc3eed139c17fa1a58c3a6b2b74753ec41593cf1fe5f7340b64736f6c63430008230033", "linkReferences": {}, "deployedLinkReferences": {} } diff --git a/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/TransparentUpgradeableProxy.json b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/TransparentUpgradeableProxy.json new file mode 100644 index 0000000..f4a1898 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/TransparentUpgradeableProxy.json @@ -0,0 +1,121 @@ +{ + "_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": "ERC1967ProxyUninitialized", + "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": "0x60a0604052604051610d77380380610d7783398101604081905261002291610366565b82818051610043576040516330a289cf60e21b815260040160405180910390fd5b61004d82826100ab565b50508160405161005c9061032a565b6001600160a01b039091168152602001604051809103905ff080158015610085573d5f5f3e3d5ffd5b506001600160a01b03166080526100a361009e60805190565b610109565b505050610437565b6100b482610176565b6040516001600160a01b038316907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b905f90a28051156100fd576100f882826101f4565b505050565b610105610295565b5050565b7f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f6101485f516020610d575f395f51905f52546001600160a01b031690565b604080516001600160a01b03928316815291841660208301520160405180910390a1610173816102b6565b50565b806001600160a01b03163b5f036101b057604051634c9c8ce360e01b81526001600160a01b03821660048201526024015b60405180910390fd5b807f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5b80546001600160a01b0319166001600160a01b039290921691909117905550565b60605f61020184846102f3565b905080801561022257505f3d118061022257505f846001600160a01b03163b115b156102375761022f610306565b91505061028f565b801561026157604051639996b31560e01b81526001600160a01b03851660048201526024016101a7565b3d156102745761026f61031f565b61028d565b60405163d6bda27560e01b815260040160405180910390fd5b505b92915050565b34156102b45760405163b398979f60e01b815260040160405180910390fd5b565b6001600160a01b0381166102df57604051633173bdd160e11b81525f60048201526024016101a7565b805f516020610d575f395f51905f526101d3565b5f5f5f835160208501865af49392505050565b6040513d81523d5f602083013e3d602001810160405290565b6040513d5f823e3d81fd5b6104e68061087183390190565b80516001600160a01b038116811461034d575f5ffd5b919050565b634e487b7160e01b5f52604160045260245ffd5b5f5f5f60608486031215610378575f5ffd5b61038184610337565b925061038f60208501610337565b60408501519092506001600160401b038111156103aa575f5ffd5b8401601f810186136103ba575f5ffd5b80516001600160401b038111156103d3576103d3610352565b604051601f8201601f19908116603f011681016001600160401b038111828210171561040157610401610352565b604052818152828201602001881015610418575f5ffd5b8160208401602083015e5f602083830101528093505050509250925092565b60805161042361044e5f395f601001526104235ff3fe608060405261000c61000e565b005b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316330361007a575f356001600160e01b03191663278f794360e11b14610070576040516334ad5dbb60e21b815260040160405180910390fd5b610078610082565b565b6100786100b0565b5f8061009136600481846102e1565b81019061009e919061031c565b915091506100ac82826100c0565b5050565b6100786100bb61011a565b610151565b6100c98261016f565b6040516001600160a01b038316907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b905f90a28051156101125761010d82826101ea565b505050565b6100ac61028b565b5f61014c7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc546001600160a01b031690565b905090565b365f5f375f5f365f845af43d5f5f3e80801561016b573d5ff35b3d5ffd5b806001600160a01b03163b5f036101a957604051634c9c8ce360e01b81526001600160a01b03821660048201526024015b60405180910390fd5b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc80546001600160a01b0319166001600160a01b0392909216919091179055565b60605f6101f784846102aa565b905080801561021857505f3d118061021857505f846001600160a01b03163b115b1561022d576102256102bd565b915050610285565b801561025757604051639996b31560e01b81526001600160a01b03851660048201526024016101a0565b3d1561026a576102656102d6565b610283565b60405163d6bda27560e01b815260040160405180910390fd5b505b92915050565b34156100785760405163b398979f60e01b815260040160405180910390fd5b5f5f5f835160208501865af49392505050565b6040513d81523d5f602083013e3d602001810160405290565b6040513d5f823e3d81fd5b5f5f858511156102ef575f5ffd5b838611156102fb575f5ffd5b5050820193919092039150565b634e487b7160e01b5f52604160045260245ffd5b5f5f6040838503121561032d575f5ffd5b82356001600160a01b0381168114610343575f5ffd5b9150602083013567ffffffffffffffff81111561035e575f5ffd5b8301601f8101851361036e575f5ffd5b803567ffffffffffffffff81111561038857610388610308565b604051601f8201601f19908116603f0116810167ffffffffffffffff811182821017156103b7576103b7610308565b6040528181528282016020018710156103ce575f5ffd5b816020840160208301375f60208383010152809350505050925092905056fea26469706673582212208cb9df74ccdd64c50014a276c0e7577f4bb13cb1e8a4edb17a112b17b3535b6b64736f6c634300082300336080604052348015600e575f5ffd5b506040516104e63803806104e6833981016040819052602b9160b4565b806001600160a01b038116605857604051631e4fbdf760e01b81525f600482015260240160405180910390fd5b605f816065565b505060df565b5f80546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b5f6020828403121560c3575f5ffd5b81516001600160a01b038116811460d8575f5ffd5b9392505050565b6103fa806100ec5f395ff3fe608060405260043610610049575f3560e01c8063715018a61461004d5780638da5cb5b146100635780639623609d1461008e578063ad3cb1cc146100a1578063f2fde38b146100de575b5f5ffd5b348015610058575f5ffd5b506100616100fd565b005b34801561006e575f5ffd5b505f546040516001600160a01b0390911681526020015b60405180910390f35b61006161009c366004610260565b610110565b3480156100ac575f5ffd5b506100d1604051806040016040528060058152602001640352e302e360dc1b81525081565b6040516100859190610365565b3480156100e9575f5ffd5b506100616100f836600461037e565b61017b565b6101056101bd565b61010e5f6101e9565b565b6101186101bd565b60405163278f794360e11b81526001600160a01b03841690634f1ef2869034906101489086908690600401610399565b5f604051808303818588803b15801561015f575f5ffd5b505af1158015610171573d5f5f3e3d5ffd5b5050505050505050565b6101836101bd565b6001600160a01b0381166101b157604051631e4fbdf760e01b81525f60048201526024015b60405180910390fd5b6101ba816101e9565b50565b5f546001600160a01b0316331461010e5760405163118cdaa760e01b81523360048201526024016101a8565b5f80546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6001600160a01b03811681146101ba575f5ffd5b634e487b7160e01b5f52604160045260245ffd5b5f5f5f60608486031215610272575f5ffd5b833561027d81610238565b9250602084013561028d81610238565b9150604084013567ffffffffffffffff8111156102a8575f5ffd5b8401601f810186136102b8575f5ffd5b803567ffffffffffffffff8111156102d2576102d261024c565b604051601f8201601f19908116603f0116810167ffffffffffffffff811182821017156103015761030161024c565b604052818152828201602001881015610318575f5ffd5b816020840160208301375f602083830101528093505050509250925092565b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b602081525f6103776020830184610337565b9392505050565b5f6020828403121561038e575f5ffd5b813561037781610238565b6001600160a01b03831681526040602082018190525f906103bc90830184610337565b94935050505056fea26469706673582212201dee9c8150c961c89cb25180f0dabc8bd0164c46f92e16e64bbd9300a76f2a0364736f6c63430008230033b53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103", + "deployedBytecode": "0x608060405261000c61000e565b005b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316330361007a575f356001600160e01b03191663278f794360e11b14610070576040516334ad5dbb60e21b815260040160405180910390fd5b610078610082565b565b6100786100b0565b5f8061009136600481846102e1565b81019061009e919061031c565b915091506100ac82826100c0565b5050565b6100786100bb61011a565b610151565b6100c98261016f565b6040516001600160a01b038316907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b905f90a28051156101125761010d82826101ea565b505050565b6100ac61028b565b5f61014c7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc546001600160a01b031690565b905090565b365f5f375f5f365f845af43d5f5f3e80801561016b573d5ff35b3d5ffd5b806001600160a01b03163b5f036101a957604051634c9c8ce360e01b81526001600160a01b03821660048201526024015b60405180910390fd5b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc80546001600160a01b0319166001600160a01b0392909216919091179055565b60605f6101f784846102aa565b905080801561021857505f3d118061021857505f846001600160a01b03163b115b1561022d576102256102bd565b915050610285565b801561025757604051639996b31560e01b81526001600160a01b03851660048201526024016101a0565b3d1561026a576102656102d6565b610283565b60405163d6bda27560e01b815260040160405180910390fd5b505b92915050565b34156100785760405163b398979f60e01b815260040160405180910390fd5b5f5f5f835160208501865af49392505050565b6040513d81523d5f602083013e3d602001810160405290565b6040513d5f823e3d81fd5b5f5f858511156102ef575f5ffd5b838611156102fb575f5ffd5b5050820193919092039150565b634e487b7160e01b5f52604160045260245ffd5b5f5f6040838503121561032d575f5ffd5b82356001600160a01b0381168114610343575f5ffd5b9150602083013567ffffffffffffffff81111561035e575f5ffd5b8301601f8101851361036e575f5ffd5b803567ffffffffffffffff81111561038857610388610308565b604051601f8201601f19908116603f0116810167ffffffffffffffff811182821017156103b7576103b7610308565b6040528181528282016020018710156103ce575f5ffd5b816020840160208301375f60208383010152809350505050925092905056fea26469706673582212208cb9df74ccdd64c50014a276c0e7577f4bb13cb1e8a4edb17a112b17b3535b6b64736f6c63430008230033", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/TrieProof.json b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/TrieProof.json new file mode 100644 index 0000000..35bc532 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/TrieProof.json @@ -0,0 +1,22 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "TrieProof", + "sourceName": "contracts/utils/cryptography/TrieProof.sol", + "abi": [ + { + "inputs": [ + { + "internalType": "enum TrieProof.ProofError", + "name": "err", + "type": "uint8" + } + ], + "name": "TrieProofTraversalError", + "type": "error" + } + ], + "bytecode": "0x60556032600b8282823980515f1a607314602657634e487b7160e01b5f525f60045260245ffd5b305f52607381538281f3fe730000000000000000000000000000000000000000301460806040525f5ffdfea26469706673582212206f7d2890e3fad1f9c130a00402feed6b5f046a1657f5f418a702cda348961dff64736f6c63430008230033", + "deployedBytecode": "0x730000000000000000000000000000000000000000301460806040525f5ffdfea26469706673582212206f7d2890e3fad1f9c130a00402feed6b5f046a1657f5f418a702cda348961dff64736f6c63430008230033", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/UUPSUpgradeable.json b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/UUPSUpgradeable.json similarity index 100% rename from dependencies/@openzeppelin-contracts-5.5.0/build/contracts/UUPSUpgradeable.json rename to dependencies/@openzeppelin-contracts-5.7.0/build/contracts/UUPSUpgradeable.json diff --git a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/UpgradeableBeacon.json b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/UpgradeableBeacon.json similarity index 96% rename from dependencies/@openzeppelin-contracts-5.5.0/build/contracts/UpgradeableBeacon.json rename to dependencies/@openzeppelin-contracts-5.7.0/build/contracts/UpgradeableBeacon.json index 6353559..c0eee24 100644 --- a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/UpgradeableBeacon.json +++ b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/UpgradeableBeacon.json @@ -144,8 +144,8 @@ "type": "function" } ], - "bytecode": "0x608060405234801561000f575f5ffd5b5060405161042138038061042183398101604081905261002e9161015f565b806001600160a01b03811661005d57604051631e4fbdf760e01b81525f60048201526024015b60405180910390fd5b61006681610077565b50610070826100c6565b5050610190565b5f80546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b806001600160a01b03163b5f036100fb5760405163211eb15960e21b81526001600160a01b0382166004820152602401610054565b600180546001600160a01b0319166001600160a01b0383169081179091556040517fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b905f90a250565b80516001600160a01b038116811461015a575f5ffd5b919050565b5f5f60408385031215610170575f5ffd5b61017983610144565b915061018760208401610144565b90509250929050565b6102848061019d5f395ff3fe608060405234801561000f575f5ffd5b5060043610610055575f3560e01c80633659cfe6146100595780635c60da1b1461006e578063715018a6146100975780638da5cb5b1461009f578063f2fde38b146100af575b5f5ffd5b61006c610067366004610221565b6100c2565b005b6001546001600160a01b03165b6040516001600160a01b03909116815260200160405180910390f35b61006c6100d6565b5f546001600160a01b031661007b565b61006c6100bd366004610221565b6100e9565b6100ca610128565b6100d381610154565b50565b6100de610128565b6100e75f6101d2565b565b6100f1610128565b6001600160a01b03811661011f57604051631e4fbdf760e01b81525f60048201526024015b60405180910390fd5b6100d3816101d2565b5f546001600160a01b031633146100e75760405163118cdaa760e01b8152336004820152602401610116565b806001600160a01b03163b5f036101895760405163211eb15960e21b81526001600160a01b0382166004820152602401610116565b600180546001600160a01b0319166001600160a01b0383169081179091556040517fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b905f90a250565b5f80546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b5f60208284031215610231575f5ffd5b81356001600160a01b0381168114610247575f5ffd5b939250505056fea264697066735822122085d01e60d91b3008d8108f0464ce5af78ace614cd48711dfeeaa2f8206dddf7164736f6c634300081b0033", - "deployedBytecode": "0x608060405234801561000f575f5ffd5b5060043610610055575f3560e01c80633659cfe6146100595780635c60da1b1461006e578063715018a6146100975780638da5cb5b1461009f578063f2fde38b146100af575b5f5ffd5b61006c610067366004610221565b6100c2565b005b6001546001600160a01b03165b6040516001600160a01b03909116815260200160405180910390f35b61006c6100d6565b5f546001600160a01b031661007b565b61006c6100bd366004610221565b6100e9565b6100ca610128565b6100d381610154565b50565b6100de610128565b6100e75f6101d2565b565b6100f1610128565b6001600160a01b03811661011f57604051631e4fbdf760e01b81525f60048201526024015b60405180910390fd5b6100d3816101d2565b5f546001600160a01b031633146100e75760405163118cdaa760e01b8152336004820152602401610116565b806001600160a01b03163b5f036101895760405163211eb15960e21b81526001600160a01b0382166004820152602401610116565b600180546001600160a01b0319166001600160a01b0383169081179091556040517fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b905f90a250565b5f80546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b5f60208284031215610231575f5ffd5b81356001600160a01b0381168114610247575f5ffd5b939250505056fea264697066735822122085d01e60d91b3008d8108f0464ce5af78ace614cd48711dfeeaa2f8206dddf7164736f6c634300081b0033", + "bytecode": "0x608060405234801561000f575f5ffd5b5060405161042138038061042183398101604081905261002e9161015f565b806001600160a01b03811661005d57604051631e4fbdf760e01b81525f60048201526024015b60405180910390fd5b61006681610077565b50610070826100c6565b5050610190565b5f80546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b806001600160a01b03163b5f036100fb5760405163211eb15960e21b81526001600160a01b0382166004820152602401610054565b600180546001600160a01b0319166001600160a01b0383169081179091556040517fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b905f90a250565b80516001600160a01b038116811461015a575f5ffd5b919050565b5f5f60408385031215610170575f5ffd5b61017983610144565b915061018760208401610144565b90509250929050565b6102848061019d5f395ff3fe608060405234801561000f575f5ffd5b5060043610610055575f3560e01c80633659cfe6146100595780635c60da1b1461006e578063715018a6146100975780638da5cb5b1461009f578063f2fde38b146100af575b5f5ffd5b61006c610067366004610221565b6100c2565b005b6001546001600160a01b03165b6040516001600160a01b03909116815260200160405180910390f35b61006c6100d6565b5f546001600160a01b031661007b565b61006c6100bd366004610221565b6100e9565b6100ca610128565b6100d381610154565b50565b6100de610128565b6100e75f6101d2565b565b6100f1610128565b6001600160a01b03811661011f57604051631e4fbdf760e01b81525f60048201526024015b60405180910390fd5b6100d3816101d2565b5f546001600160a01b031633146100e75760405163118cdaa760e01b8152336004820152602401610116565b806001600160a01b03163b5f036101895760405163211eb15960e21b81526001600160a01b0382166004820152602401610116565b600180546001600160a01b0319166001600160a01b0383169081179091556040517fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b905f90a250565b5f80546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b5f60208284031215610231575f5ffd5b81356001600160a01b0381168114610247575f5ffd5b939250505056fea264697066735822122086395c9f1007235effb9ba05d2f96e9303b654009cdc93a2ba87602d9f6b70ac64736f6c63430008230033", + "deployedBytecode": "0x608060405234801561000f575f5ffd5b5060043610610055575f3560e01c80633659cfe6146100595780635c60da1b1461006e578063715018a6146100975780638da5cb5b1461009f578063f2fde38b146100af575b5f5ffd5b61006c610067366004610221565b6100c2565b005b6001546001600160a01b03165b6040516001600160a01b03909116815260200160405180910390f35b61006c6100d6565b5f546001600160a01b031661007b565b61006c6100bd366004610221565b6100e9565b6100ca610128565b6100d381610154565b50565b6100de610128565b6100e75f6101d2565b565b6100f1610128565b6001600160a01b03811661011f57604051631e4fbdf760e01b81525f60048201526024015b60405180910390fd5b6100d3816101d2565b5f546001600160a01b031633146100e75760405163118cdaa760e01b8152336004820152602401610116565b806001600160a01b03163b5f036101895760405163211eb15960e21b81526001600160a01b0382166004820152602401610116565b600180546001600160a01b0319166001600160a01b0383169081179091556040517fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b905f90a250565b5f80546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b5f60208284031215610231575f5ffd5b81356001600160a01b0381168114610247575f5ffd5b939250505056fea264697066735822122086395c9f1007235effb9ba05d2f96e9303b654009cdc93a2ba87602d9f6b70ac64736f6c63430008230033", "linkReferences": {}, "deployedLinkReferences": {} } diff --git a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/VestingWallet.json b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/VestingWallet.json similarity index 98% rename from dependencies/@openzeppelin-contracts-5.5.0/build/contracts/VestingWallet.json rename to dependencies/@openzeppelin-contracts-5.7.0/build/contracts/VestingWallet.json index 2268790..c4856dc 100644 --- a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/VestingWallet.json +++ b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/VestingWallet.json @@ -333,8 +333,8 @@ "type": "receive" } ], - "bytecode": "0x60c0604052604051610a66380380610a66833981016040819052610022916100dc565b826001600160a01b03811661005057604051631e4fbdf760e01b81525f600482015260240160405180910390fd5b61005981610072565b506001600160401b039182166080521660a05250610129565b5f80546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b80516001600160401b03811681146100d7575f5ffd5b919050565b5f5f5f606084860312156100ee575f5ffd5b83516001600160a01b0381168114610104575f5ffd5b9250610112602085016100c1565b9150610120604085016100c1565b90509250925092565b60805160a05161090e6101585f395f8181610127015281816104d401526105b201525f6104ae015261090e5ff3fe6080604052600436106100dc575f3560e01c8063961325211161007c578063be9a655511610057578063be9a65551461024a578063efbe1c1c1461025e578063f2fde38b14610272578063fbccedae14610291575f5ffd5b806396132521146101e35780639852595c146101f7578063a3f8eace1461022b575f5ffd5b8063715018a6116100b7578063715018a614610176578063810ec23b1461018a57806386d1a69f146101a95780638da5cb5b146101bd575f5ffd5b80630a17b06b146100e75780630fb5a6b4146101195780631916558714610155575f5ffd5b366100e357005b5f5ffd5b3480156100f2575f5ffd5b506101066101013660046107d8565b6102a5565b6040519081526020015b60405180910390f35b348015610124575f5ffd5b507f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff16610106565b348015610160575f5ffd5b5061017461016f366004610807565b6102c8565b005b348015610181575f5ffd5b50610174610360565b348015610195575f5ffd5b506101066101a4366004610820565b610373565b3480156101b4575f5ffd5b50610174610406565b3480156101c8575f5ffd5b505f546040516001600160a01b039091168152602001610110565b3480156101ee575f5ffd5b50600154610106565b348015610202575f5ffd5b50610106610211366004610807565b6001600160a01b03165f9081526002602052604090205490565b348015610236575f5ffd5b50610106610245366004610807565b610477565b348015610255575f5ffd5b506101066104a3565b348015610269575f5ffd5b506101066104d1565b34801561027d575f5ffd5b5061017461028c366004610807565b610514565b34801561029c575f5ffd5b50610106610553565b5f6102c26102b260015490565b6102bc9047610865565b83610570565b92915050565b5f6102d282610477565b6001600160a01b0383165f908152600260205260408120805492935083929091906102fe908490610865565b90915550506040518181526001600160a01b038316907fc0e523490dd523c33b1878c9eb14ff46991e3f5b2cd33710918618f2a39cba1b9060200160405180910390a261035c826103565f546001600160a01b031690565b83610612565b5050565b61036861064c565b6103715f610678565b565b6001600160a01b0382165f908152600260205260408120546103ff906040516370a0823160e01b81523060048201526001600160a01b038616906370a0823190602401602060405180830381865afa1580156103d1573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906103f59190610878565b6102bc9190610865565b9392505050565b5f61040f610553565b90508060015f8282546104229190610865565b90915550506040518181527fda9d4e5f101b8b9b1c5b76d0c5a9f7923571acfc02376aa076b75a8c080c956b9060200160405180910390a161047461046e5f546001600160a01b031690565b826106c7565b50565b6001600160a01b0381165f908152600260205260408120546104998342610373565b6102c2919061088f565b67ffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001690565b5f7f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff166105056104a3565b61050f9190610865565b905090565b61051c61064c565b6001600160a01b03811661054a57604051631e4fbdf760e01b81525f60048201526024015b60405180910390fd5b61047481610678565b5f61055d60015490565b610566426102a5565b61050f919061088f565b5f6105796104a3565b8267ffffffffffffffff16101561059157505f6102c2565b6105996104d1565b8267ffffffffffffffff16106105b05750816102c2565b7f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff166105e36104a3565b6105f79067ffffffffffffffff851661088f565b61060190856108a2565b61060b91906108b9565b90506102c2565b61061f838383600161073a565b61064757604051635274afe760e01b81526001600160a01b0384166004820152602401610541565b505050565b5f546001600160a01b031633146103715760405163118cdaa760e01b8152336004820152602401610541565b5f80546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b804710156106f15760405163cf47918160e01b815247600482015260248101829052604401610541565b61070a828260405180602001604052805f81525061079c565b15610713575050565b3d156107215761035c6107b1565b60405163d6bda27560e01b815260040160405180910390fd5b60405163a9059cbb60e01b5f8181526001600160a01b038616600452602485905291602083604481808b5af1925060015f51148316610790578383151615610784573d5f823e3d81fd5b5f873b113d1516831692505b60405250949350505050565b5f5f5f83516020850186885af1949350505050565b6040513d5f823e3d81fd5b803567ffffffffffffffff811681146107d3575f5ffd5b919050565b5f602082840312156107e8575f5ffd5b6103ff826107bc565b80356001600160a01b03811681146107d3575f5ffd5b5f60208284031215610817575f5ffd5b6103ff826107f1565b5f5f60408385031215610831575f5ffd5b61083a836107f1565b9150610848602084016107bc565b90509250929050565b634e487b7160e01b5f52601160045260245ffd5b808201808211156102c2576102c2610851565b5f60208284031215610888575f5ffd5b5051919050565b818103818111156102c2576102c2610851565b80820281158282048414176102c2576102c2610851565b5f826108d357634e487b7160e01b5f52601260045260245ffd5b50049056fea26469706673582212201ef96bf4f676ed75c73358ea5b9c48322dd58430b7aaaf26b6570a7125c24a4d64736f6c634300081b0033", - "deployedBytecode": "0x6080604052600436106100dc575f3560e01c8063961325211161007c578063be9a655511610057578063be9a65551461024a578063efbe1c1c1461025e578063f2fde38b14610272578063fbccedae14610291575f5ffd5b806396132521146101e35780639852595c146101f7578063a3f8eace1461022b575f5ffd5b8063715018a6116100b7578063715018a614610176578063810ec23b1461018a57806386d1a69f146101a95780638da5cb5b146101bd575f5ffd5b80630a17b06b146100e75780630fb5a6b4146101195780631916558714610155575f5ffd5b366100e357005b5f5ffd5b3480156100f2575f5ffd5b506101066101013660046107d8565b6102a5565b6040519081526020015b60405180910390f35b348015610124575f5ffd5b507f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff16610106565b348015610160575f5ffd5b5061017461016f366004610807565b6102c8565b005b348015610181575f5ffd5b50610174610360565b348015610195575f5ffd5b506101066101a4366004610820565b610373565b3480156101b4575f5ffd5b50610174610406565b3480156101c8575f5ffd5b505f546040516001600160a01b039091168152602001610110565b3480156101ee575f5ffd5b50600154610106565b348015610202575f5ffd5b50610106610211366004610807565b6001600160a01b03165f9081526002602052604090205490565b348015610236575f5ffd5b50610106610245366004610807565b610477565b348015610255575f5ffd5b506101066104a3565b348015610269575f5ffd5b506101066104d1565b34801561027d575f5ffd5b5061017461028c366004610807565b610514565b34801561029c575f5ffd5b50610106610553565b5f6102c26102b260015490565b6102bc9047610865565b83610570565b92915050565b5f6102d282610477565b6001600160a01b0383165f908152600260205260408120805492935083929091906102fe908490610865565b90915550506040518181526001600160a01b038316907fc0e523490dd523c33b1878c9eb14ff46991e3f5b2cd33710918618f2a39cba1b9060200160405180910390a261035c826103565f546001600160a01b031690565b83610612565b5050565b61036861064c565b6103715f610678565b565b6001600160a01b0382165f908152600260205260408120546103ff906040516370a0823160e01b81523060048201526001600160a01b038616906370a0823190602401602060405180830381865afa1580156103d1573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906103f59190610878565b6102bc9190610865565b9392505050565b5f61040f610553565b90508060015f8282546104229190610865565b90915550506040518181527fda9d4e5f101b8b9b1c5b76d0c5a9f7923571acfc02376aa076b75a8c080c956b9060200160405180910390a161047461046e5f546001600160a01b031690565b826106c7565b50565b6001600160a01b0381165f908152600260205260408120546104998342610373565b6102c2919061088f565b67ffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001690565b5f7f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff166105056104a3565b61050f9190610865565b905090565b61051c61064c565b6001600160a01b03811661054a57604051631e4fbdf760e01b81525f60048201526024015b60405180910390fd5b61047481610678565b5f61055d60015490565b610566426102a5565b61050f919061088f565b5f6105796104a3565b8267ffffffffffffffff16101561059157505f6102c2565b6105996104d1565b8267ffffffffffffffff16106105b05750816102c2565b7f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff166105e36104a3565b6105f79067ffffffffffffffff851661088f565b61060190856108a2565b61060b91906108b9565b90506102c2565b61061f838383600161073a565b61064757604051635274afe760e01b81526001600160a01b0384166004820152602401610541565b505050565b5f546001600160a01b031633146103715760405163118cdaa760e01b8152336004820152602401610541565b5f80546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b804710156106f15760405163cf47918160e01b815247600482015260248101829052604401610541565b61070a828260405180602001604052805f81525061079c565b15610713575050565b3d156107215761035c6107b1565b60405163d6bda27560e01b815260040160405180910390fd5b60405163a9059cbb60e01b5f8181526001600160a01b038616600452602485905291602083604481808b5af1925060015f51148316610790578383151615610784573d5f823e3d81fd5b5f873b113d1516831692505b60405250949350505050565b5f5f5f83516020850186885af1949350505050565b6040513d5f823e3d81fd5b803567ffffffffffffffff811681146107d3575f5ffd5b919050565b5f602082840312156107e8575f5ffd5b6103ff826107bc565b80356001600160a01b03811681146107d3575f5ffd5b5f60208284031215610817575f5ffd5b6103ff826107f1565b5f5f60408385031215610831575f5ffd5b61083a836107f1565b9150610848602084016107bc565b90509250929050565b634e487b7160e01b5f52601160045260245ffd5b808201808211156102c2576102c2610851565b5f60208284031215610888575f5ffd5b5051919050565b818103818111156102c2576102c2610851565b80820281158282048414176102c2576102c2610851565b5f826108d357634e487b7160e01b5f52601260045260245ffd5b50049056fea26469706673582212201ef96bf4f676ed75c73358ea5b9c48322dd58430b7aaaf26b6570a7125c24a4d64736f6c634300081b0033", + "bytecode": "0x60c0604052604051610a66380380610a66833981016040819052610022916100dc565b826001600160a01b03811661005057604051631e4fbdf760e01b81525f600482015260240160405180910390fd5b61005981610072565b506001600160401b039182166080521660a05250610129565b5f80546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b80516001600160401b03811681146100d7575f5ffd5b919050565b5f5f5f606084860312156100ee575f5ffd5b83516001600160a01b0381168114610104575f5ffd5b9250610112602085016100c1565b9150610120604085016100c1565b90509250925092565b60805160a05161090e6101585f395f8181610127015281816104d401526105b201525f6104ae015261090e5ff3fe6080604052600436106100dc575f3560e01c8063961325211161007c578063be9a655511610057578063be9a65551461024a578063efbe1c1c1461025e578063f2fde38b14610272578063fbccedae14610291575f5ffd5b806396132521146101e35780639852595c146101f7578063a3f8eace1461022b575f5ffd5b8063715018a6116100b7578063715018a614610176578063810ec23b1461018a57806386d1a69f146101a95780638da5cb5b146101bd575f5ffd5b80630a17b06b146100e75780630fb5a6b4146101195780631916558714610155575f5ffd5b366100e357005b5f5ffd5b3480156100f2575f5ffd5b506101066101013660046107d8565b6102a5565b6040519081526020015b60405180910390f35b348015610124575f5ffd5b507f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff16610106565b348015610160575f5ffd5b5061017461016f366004610807565b6102c8565b005b348015610181575f5ffd5b50610174610360565b348015610195575f5ffd5b506101066101a4366004610820565b610373565b3480156101b4575f5ffd5b50610174610406565b3480156101c8575f5ffd5b505f546040516001600160a01b039091168152602001610110565b3480156101ee575f5ffd5b50600154610106565b348015610202575f5ffd5b50610106610211366004610807565b6001600160a01b03165f9081526002602052604090205490565b348015610236575f5ffd5b50610106610245366004610807565b610477565b348015610255575f5ffd5b506101066104a3565b348015610269575f5ffd5b506101066104d1565b34801561027d575f5ffd5b5061017461028c366004610807565b610514565b34801561029c575f5ffd5b50610106610553565b5f6102c26102b260015490565b6102bc9047610865565b83610570565b92915050565b5f6102d282610477565b6001600160a01b0383165f908152600260205260408120805492935083929091906102fe908490610865565b90915550506040518181526001600160a01b038316907fc0e523490dd523c33b1878c9eb14ff46991e3f5b2cd33710918618f2a39cba1b9060200160405180910390a261035c826103565f546001600160a01b031690565b83610612565b5050565b61036861064c565b6103715f610678565b565b6001600160a01b0382165f908152600260205260408120546103ff906040516370a0823160e01b81523060048201526001600160a01b038616906370a0823190602401602060405180830381865afa1580156103d1573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906103f59190610878565b6102bc9190610865565b9392505050565b5f61040f610553565b90508060015f8282546104229190610865565b90915550506040518181527fda9d4e5f101b8b9b1c5b76d0c5a9f7923571acfc02376aa076b75a8c080c956b9060200160405180910390a161047461046e5f546001600160a01b031690565b826106c7565b50565b6001600160a01b0381165f908152600260205260408120546104998342610373565b6102c2919061088f565b67ffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001690565b5f7f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff166105056104a3565b61050f9190610865565b905090565b61051c61064c565b6001600160a01b03811661054a57604051631e4fbdf760e01b81525f60048201526024015b60405180910390fd5b61047481610678565b5f61055d60015490565b610566426102a5565b61050f919061088f565b5f6105796104a3565b8267ffffffffffffffff16101561059157505f6102c2565b6105996104d1565b8267ffffffffffffffff16106105b05750816102c2565b7f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff166105e36104a3565b6105f79067ffffffffffffffff851661088f565b61060190856108a2565b61060b91906108b9565b90506102c2565b61061f838383600161073a565b61064757604051635274afe760e01b81526001600160a01b0384166004820152602401610541565b505050565b5f546001600160a01b031633146103715760405163118cdaa760e01b8152336004820152602401610541565b5f80546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b804710156106f15760405163cf47918160e01b815247600482015260248101829052604401610541565b61070a828260405180602001604052805f81525061079c565b15610713575050565b3d156107215761035c6107b1565b60405163d6bda27560e01b815260040160405180910390fd5b60405163a9059cbb60e01b5f8181526001600160a01b038616600452602485905291602083604481808b5af1925060015f51148316610790578383151615610784573d5f823e3d81fd5b5f873b113d1516831692505b60405250949350505050565b5f5f5f83516020850186885af1949350505050565b6040513d5f823e3d81fd5b803567ffffffffffffffff811681146107d3575f5ffd5b919050565b5f602082840312156107e8575f5ffd5b6103ff826107bc565b80356001600160a01b03811681146107d3575f5ffd5b5f60208284031215610817575f5ffd5b6103ff826107f1565b5f5f60408385031215610831575f5ffd5b61083a836107f1565b9150610848602084016107bc565b90509250929050565b634e487b7160e01b5f52601160045260245ffd5b808201808211156102c2576102c2610851565b5f60208284031215610888575f5ffd5b5051919050565b818103818111156102c2576102c2610851565b80820281158282048414176102c2576102c2610851565b5f826108d357634e487b7160e01b5f52601260045260245ffd5b50049056fea26469706673582212209f5f1c3bd935bf35e0c7ff30a285b40dd863920a4c0d56dbfe38486f9020048264736f6c63430008230033", + "deployedBytecode": "0x6080604052600436106100dc575f3560e01c8063961325211161007c578063be9a655511610057578063be9a65551461024a578063efbe1c1c1461025e578063f2fde38b14610272578063fbccedae14610291575f5ffd5b806396132521146101e35780639852595c146101f7578063a3f8eace1461022b575f5ffd5b8063715018a6116100b7578063715018a614610176578063810ec23b1461018a57806386d1a69f146101a95780638da5cb5b146101bd575f5ffd5b80630a17b06b146100e75780630fb5a6b4146101195780631916558714610155575f5ffd5b366100e357005b5f5ffd5b3480156100f2575f5ffd5b506101066101013660046107d8565b6102a5565b6040519081526020015b60405180910390f35b348015610124575f5ffd5b507f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff16610106565b348015610160575f5ffd5b5061017461016f366004610807565b6102c8565b005b348015610181575f5ffd5b50610174610360565b348015610195575f5ffd5b506101066101a4366004610820565b610373565b3480156101b4575f5ffd5b50610174610406565b3480156101c8575f5ffd5b505f546040516001600160a01b039091168152602001610110565b3480156101ee575f5ffd5b50600154610106565b348015610202575f5ffd5b50610106610211366004610807565b6001600160a01b03165f9081526002602052604090205490565b348015610236575f5ffd5b50610106610245366004610807565b610477565b348015610255575f5ffd5b506101066104a3565b348015610269575f5ffd5b506101066104d1565b34801561027d575f5ffd5b5061017461028c366004610807565b610514565b34801561029c575f5ffd5b50610106610553565b5f6102c26102b260015490565b6102bc9047610865565b83610570565b92915050565b5f6102d282610477565b6001600160a01b0383165f908152600260205260408120805492935083929091906102fe908490610865565b90915550506040518181526001600160a01b038316907fc0e523490dd523c33b1878c9eb14ff46991e3f5b2cd33710918618f2a39cba1b9060200160405180910390a261035c826103565f546001600160a01b031690565b83610612565b5050565b61036861064c565b6103715f610678565b565b6001600160a01b0382165f908152600260205260408120546103ff906040516370a0823160e01b81523060048201526001600160a01b038616906370a0823190602401602060405180830381865afa1580156103d1573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906103f59190610878565b6102bc9190610865565b9392505050565b5f61040f610553565b90508060015f8282546104229190610865565b90915550506040518181527fda9d4e5f101b8b9b1c5b76d0c5a9f7923571acfc02376aa076b75a8c080c956b9060200160405180910390a161047461046e5f546001600160a01b031690565b826106c7565b50565b6001600160a01b0381165f908152600260205260408120546104998342610373565b6102c2919061088f565b67ffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001690565b5f7f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff166105056104a3565b61050f9190610865565b905090565b61051c61064c565b6001600160a01b03811661054a57604051631e4fbdf760e01b81525f60048201526024015b60405180910390fd5b61047481610678565b5f61055d60015490565b610566426102a5565b61050f919061088f565b5f6105796104a3565b8267ffffffffffffffff16101561059157505f6102c2565b6105996104d1565b8267ffffffffffffffff16106105b05750816102c2565b7f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff166105e36104a3565b6105f79067ffffffffffffffff851661088f565b61060190856108a2565b61060b91906108b9565b90506102c2565b61061f838383600161073a565b61064757604051635274afe760e01b81526001600160a01b0384166004820152602401610541565b505050565b5f546001600160a01b031633146103715760405163118cdaa760e01b8152336004820152602401610541565b5f80546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b804710156106f15760405163cf47918160e01b815247600482015260248101829052604401610541565b61070a828260405180602001604052805f81525061079c565b15610713575050565b3d156107215761035c6107b1565b60405163d6bda27560e01b815260040160405180910390fd5b60405163a9059cbb60e01b5f8181526001600160a01b038616600452602485905291602083604481808b5af1925060015f51148316610790578383151615610784573d5f823e3d81fd5b5f873b113d1516831692505b60405250949350505050565b5f5f5f83516020850186885af1949350505050565b6040513d5f823e3d81fd5b803567ffffffffffffffff811681146107d3575f5ffd5b919050565b5f602082840312156107e8575f5ffd5b6103ff826107bc565b80356001600160a01b03811681146107d3575f5ffd5b5f60208284031215610817575f5ffd5b6103ff826107f1565b5f5f60408385031215610831575f5ffd5b61083a836107f1565b9150610848602084016107bc565b90509250929050565b634e487b7160e01b5f52601160045260245ffd5b808201808211156102c2576102c2610851565b5f60208284031215610888575f5ffd5b5051919050565b818103818111156102c2576102c2610851565b80820281158282048414176102c2576102c2610851565b5f826108d357634e487b7160e01b5f52601260045260245ffd5b50049056fea26469706673582212209f5f1c3bd935bf35e0c7ff30a285b40dd863920a4c0d56dbfe38486f9020048264736f6c63430008230033", "linkReferences": {}, "deployedLinkReferences": {} } diff --git a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/VestingWalletCliff.json b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/VestingWalletCliff.json similarity index 100% rename from dependencies/@openzeppelin-contracts-5.5.0/build/contracts/VestingWalletCliff.json rename to dependencies/@openzeppelin-contracts-5.7.0/build/contracts/VestingWalletCliff.json diff --git a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/Votes.json b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/Votes.json similarity index 100% rename from dependencies/@openzeppelin-contracts-5.5.0/build/contracts/Votes.json rename to dependencies/@openzeppelin-contracts-5.7.0/build/contracts/Votes.json diff --git a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/VotesExtended.json b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/VotesExtended.json similarity index 100% rename from dependencies/@openzeppelin-contracts-5.5.0/build/contracts/VotesExtended.json rename to dependencies/@openzeppelin-contracts-5.7.0/build/contracts/VotesExtended.json diff --git a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/WebAuthn.json b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/WebAuthn.json similarity index 67% rename from dependencies/@openzeppelin-contracts-5.5.0/build/contracts/WebAuthn.json rename to dependencies/@openzeppelin-contracts-5.7.0/build/contracts/WebAuthn.json index cc2c868..4165de1 100644 --- a/dependencies/@openzeppelin-contracts-5.5.0/build/contracts/WebAuthn.json +++ b/dependencies/@openzeppelin-contracts-5.7.0/build/contracts/WebAuthn.json @@ -3,8 +3,8 @@ "contractName": "WebAuthn", "sourceName": "contracts/utils/cryptography/WebAuthn.sol", "abi": [], - "bytecode": "0x60556032600b8282823980515f1a607314602657634e487b7160e01b5f525f60045260245ffd5b305f52607381538281f3fe730000000000000000000000000000000000000000301460806040525f5ffdfea2646970667358221220cad2e49561485028057f8fea728159bc0ae9db5da0d7eb4abf63f5018025179164736f6c634300081b0033", - "deployedBytecode": "0x730000000000000000000000000000000000000000301460806040525f5ffdfea2646970667358221220cad2e49561485028057f8fea728159bc0ae9db5da0d7eb4abf63f5018025179164736f6c634300081b0033", + "bytecode": "0x60556032600b8282823980515f1a607314602657634e487b7160e01b5f525f60045260245ffd5b305f52607381538281f3fe730000000000000000000000000000000000000000301460806040525f5ffdfea264697066735822122064abcd6ed0711d8d12c025366b2d591df8024c6de03e04cb3deaf02f11c2ab0964736f6c63430008230033", + "deployedBytecode": "0x730000000000000000000000000000000000000000301460806040525f5ffdfea264697066735822122064abcd6ed0711d8d12c025366b2d591df8024c6de03e04cb3deaf02f11c2ab0964736f6c63430008230033", "linkReferences": {}, "deployedLinkReferences": {} } diff --git a/dependencies/@openzeppelin-contracts-5.7.0/crosschain/CrosschainLinked.sol b/dependencies/@openzeppelin-contracts-5.7.0/crosschain/CrosschainLinked.sol new file mode 100644 index 0000000..95b4957 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.7.0/crosschain/CrosschainLinked.sol @@ -0,0 +1,114 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v5.7.0) (crosschain/CrosschainLinked.sol) + +pragma solidity ^0.8.26; + +import {IERC7786GatewaySource} from "../interfaces/draft-IERC7786.sol"; +import {InteroperableAddress} from "../utils/draft-InteroperableAddress.sol"; +import {Bytes} from "../utils/Bytes.sol"; +import {ERC7786Recipient} from "./ERC7786Recipient.sol"; + +/** + * @dev Core bridging mechanism. + * + * This contract contains the logic to register and send messages to counterparts on remote chains using ERC-7786 + * gateways. It ensure received messages originate from a counterpart. This is the base of token bridges such as + * {BridgeFungible}. + * + * Contracts that inherit from this contract can use the internal {_sendMessageToCounterpart} to send messages to their + * counterpart on a foreign chain. They must override the {_processMessage} function to handle messages that have + * been verified. + */ +abstract contract CrosschainLinked is ERC7786Recipient { + using Bytes for bytes; + using InteroperableAddress for bytes; + + struct Link { + address gateway; + bytes counterpart; // Full InteroperableAddress (chain ref + address) + } + mapping(bytes chain => Link) private _links; + + /** + * @dev Emitted when a new link is registered. + * + * Note: the `counterpart` argument is a full InteroperableAddress (chain ref + address). + */ + event LinkRegistered(address gateway, bytes counterpart); + + /** + * @dev Reverted when trying to register a link for a chain that is already registered. + * + * Note: the `chain` argument is a "chain-only" InteroperableAddress (empty address). + */ + error LinkAlreadyRegistered(bytes chain); + + constructor(Link[] memory links) { + for (uint256 i = 0; i < links.length; ++i) { + _setLink(links[i].gateway, links[i].counterpart, false); + } + } + + /** + * @dev Returns the ERC-7786 gateway used for sending and receiving cross-chain messages to a given chain. + * + * Note: The `chain` parameter is a "chain-only" InteroperableAddress (empty address) and the `counterpart` returns + * the full InteroperableAddress (chain ref + address) that is on `chain`. + */ + function getLink(bytes memory chain) public view virtual returns (address gateway, bytes memory counterpart) { + Link storage self = _links[chain]; + return (self.gateway, self.counterpart); + } + + /** + * @dev Internal setter to change the ERC-7786 gateway and counterpart for a given chain. Called at construction. + * + * Note: The `counterpart` parameter is the full InteroperableAddress (chain ref + address). + */ + function _setLink(address gateway, bytes memory counterpart, bool allowOverride) internal virtual { + // Sanity check, this should revert if gateway is not an ERC-7786 implementation. Note that since + // supportsAttribute returns data, an EOA would fail that test (nothing returned). + IERC7786GatewaySource(gateway).supportsAttribute(bytes4(0)); + + bytes memory chain = _extractChain(counterpart); + if (allowOverride || _links[chain].gateway == address(0)) { + _links[chain] = Link(gateway, counterpart); + emit LinkRegistered(gateway, counterpart); + } else { + revert LinkAlreadyRegistered(chain); + } + } + + /** + * @dev Internal messaging function + * + * Note: The `chain` parameter is a "chain-only" InteroperableAddress (empty address). + */ + function _sendMessageToCounterpart( + bytes memory chain, + bytes memory payload, + bytes[] memory attributes + ) internal virtual returns (bytes32) { + (address gateway, bytes memory counterpart) = getLink(chain); + return IERC7786GatewaySource(gateway).sendMessage(counterpart, payload, attributes); + } + + /// @inheritdoc ERC7786Recipient + function _isAuthorizedGateway( + address instance, + bytes calldata sender + ) internal view virtual override returns (bool) { + (address gateway, bytes memory router) = getLink(_extractChainCalldata(sender)); + return instance == gateway && sender.equal(router); + } + + function _extractChain(bytes memory self) private pure returns (bytes memory) { + (bytes2 chainType, bytes memory chainReference, ) = self.parseV1(); + return InteroperableAddress.formatV1(chainType, chainReference, hex""); + } + + function _extractChainCalldata(bytes calldata self) private pure returns (bytes memory) { + (bytes2 chainType, bytes calldata chainReference, ) = self.parseV1Calldata(); + return InteroperableAddress.formatV1(chainType, chainReference, hex""); + } +} diff --git a/dependencies/@openzeppelin-contracts-5.7.0/crosschain/CrosschainRemoteExecutor.sol b/dependencies/@openzeppelin-contracts-5.7.0/crosschain/CrosschainRemoteExecutor.sol new file mode 100644 index 0000000..9fb6cca --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.7.0/crosschain/CrosschainRemoteExecutor.sol @@ -0,0 +1,99 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v5.7.0) (crosschain/CrosschainRemoteExecutor.sol) + +pragma solidity ^0.8.27; + +import {IERC7786GatewaySource} from "../interfaces/draft-IERC7786.sol"; +import {ERC7786Recipient} from "./ERC7786Recipient.sol"; +import {ERC7579Utils, Mode, CallType, ExecType} from "../account/utils/draft-ERC7579Utils.sol"; +import {Bytes} from "../utils/Bytes.sol"; + +/** + * @dev Helper contract used to relay transactions received from a controller through an ERC-7786 gateway. This is + * used by the {GovernorCrosschain} governance module for the execution of cross-chain actions. + * + * A {CrosschainRemoteExecutor} address can be seen as the local identity of a remote executor on another chain. It + * holds assets and permissions for the sake of its controller. + */ +contract CrosschainRemoteExecutor is ERC7786Recipient { + using Bytes for bytes; + using ERC7579Utils for *; + + /// @dev Gateway used by the remote controller to relay instructions to this executor. + address private _gateway; + + /// @dev InteroperableAddress of the remote controller that is allowed to relay instructions to this executor. + bytes private _controller; + + /// @dev Emitted when the gateway or controller of this remote executor is updated. + event CrosschainControllerSet(address gateway, bytes controller); + + /// @dev Reverted when a non-controller tries to relay instructions to this executor. + error AccessRestricted(); + + constructor(address initialGateway, bytes memory initialController) { + _setup(initialGateway, initialController); + } + + /// @dev Accessor that returns the address of the gateway used by this remote executor. + function gateway() public view virtual returns (address) { + return _gateway; + } + + /** + * @dev Accessor that returns the interoperable address of the controller allowed to relay instructions to this + * remote executor. + */ + function controller() public view virtual returns (bytes memory) { + return _controller; + } + + /** + * @dev Endpoint allowing the controller to reconfigure the executor. This must be called by the executor itself + * following an instruction from the controller. + */ + function reconfigure(address newGateway, bytes memory newController) public virtual { + require(msg.sender == address(this), AccessRestricted()); + _setup(newGateway, newController); + } + + /// @dev Internal setter to reconfigure the gateway and controller. + function _setup(address gateway_, bytes memory controller_) internal virtual { + // Sanity check, this should revert if gateway is not an ERC-7786 implementation. Note that since + // supportsAttribute returns data, accounts without code would fail that test (nothing returned). + IERC7786GatewaySource(gateway_).supportsAttribute(bytes4(0)); + + _gateway = gateway_; + _controller = controller_; + + emit CrosschainControllerSet(gateway_, controller_); + } + + /// @inheritdoc ERC7786Recipient + function _isAuthorizedGateway( + address instance, + bytes calldata sender + ) internal view virtual override returns (bool) { + return gateway() == instance && controller().equal(sender); + } + + /// @inheritdoc ERC7786Recipient + function _processMessage( + address /*gateway*/, + bytes32 /*receiveId*/, + bytes calldata /*sender*/, + bytes calldata payload + ) internal virtual override { + // split payload + (CallType callType, ExecType execType, , ) = Mode.wrap(bytes32(payload[0x00:0x20])).decodeMode(); + bytes calldata executionCalldata = payload[0x20:]; + + if (callType == ERC7579Utils.CALLTYPE_SINGLE) { + executionCalldata.execSingle(execType); + } else if (callType == ERC7579Utils.CALLTYPE_BATCH) { + executionCalldata.execBatch(execType); + } else if (callType == ERC7579Utils.CALLTYPE_DELEGATECALL) { + executionCalldata.execDelegateCall(execType); + } else revert ERC7579Utils.ERC7579UnsupportedCallType(callType); + } +} diff --git a/dependencies/@openzeppelin-contracts-5.5.0/crosschain/ERC7786Recipient.sol b/dependencies/@openzeppelin-contracts-5.7.0/crosschain/ERC7786Recipient.sol similarity index 67% rename from dependencies/@openzeppelin-contracts-5.5.0/crosschain/ERC7786Recipient.sol rename to dependencies/@openzeppelin-contracts-5.7.0/crosschain/ERC7786Recipient.sol index 0035aee..926939b 100644 --- a/dependencies/@openzeppelin-contracts-5.5.0/crosschain/ERC7786Recipient.sol +++ b/dependencies/@openzeppelin-contracts-5.7.0/crosschain/ERC7786Recipient.sol @@ -1,10 +1,9 @@ // SPDX-License-Identifier: MIT -// OpenZeppelin Contracts (last updated v5.5.0) (crosschain/ERC7786Recipient.sol) +// OpenZeppelin Contracts (last updated v5.7.0) (crosschain/ERC7786Recipient.sol) pragma solidity ^0.8.20; import {IERC7786Recipient} from "../interfaces/draft-IERC7786.sol"; -import {BitMaps} from "../utils/structs/BitMaps.sol"; /** * @dev Base implementation of an ERC-7786 compliant cross-chain message receiver. @@ -13,21 +12,19 @@ import {BitMaps} from "../utils/structs/BitMaps.sol"; * destination gateways. This contract leaves two functions unimplemented: * * * {_isAuthorizedGateway}, an internal getter used to verify whether an address is recognised by the contract as a - * valid ERC-7786 destination gateway. One or multiple gateway can be supported. Note that any malicious address for + * valid ERC-7786 destination gateway. One or multiple gateways can be supported. Note that any malicious address for * which this function returns true would be able to impersonate any account on any other chain sending any message. * * * {_processMessage}, the internal function that will be called with any message that has been validated. * - * This contract implements replay protection, meaning that if two messages are received from the same gateway with the - * same `receiveId`, then the second one will NOT be executed, regardless of the result of {_isAuthorizedGateway}. + * ERC-7786 requires the gateway to ensure messages are not delivered more than once. Therefore, we don't need to keep + * track of the processed receiveId. + * + * @custom:stateless */ abstract contract ERC7786Recipient is IERC7786Recipient { - using BitMaps for BitMaps.BitMap; - - mapping(address gateway => BitMaps.BitMap) private _received; - + /// @dev Error thrown if the gateway is not authorized to send messages to this contract on behalf of the sender. error ERC7786RecipientUnauthorizedGateway(address gateway, bytes sender); - error ERC7786RecipientMessageAlreadyProcessed(address gateway, bytes32 receiveId); /// @inheritdoc IERC7786Recipient function receiveMessage( @@ -40,12 +37,6 @@ abstract contract ERC7786Recipient is IERC7786Recipient { revert ERC7786RecipientUnauthorizedGateway(msg.sender, sender); } - // Prevent duplicate execution - if (_received[msg.sender].get(uint256(receiveId))) { - revert ERC7786RecipientMessageAlreadyProcessed(msg.sender, receiveId); - } - _received[msg.sender].set(uint256(receiveId)); - _processMessage(msg.sender, receiveId, sender, payload); return IERC7786Recipient.receiveMessage.selector; @@ -60,7 +51,12 @@ abstract contract ERC7786Recipient is IERC7786Recipient { */ function _isAuthorizedGateway(address gateway, bytes calldata sender) internal view virtual returns (bool); - /// @dev Virtual function that should contain the logic to execute when a cross-chain message is received. + /** + * @dev Virtual function that should contain the logic to execute when a cross-chain message is received. + * + * NOTE: This function should revert on failure. Any silent failure from this function will result in the message + * being marked as received and not being retryable. + */ function _processMessage( address gateway, bytes32 receiveId, diff --git a/dependencies/@openzeppelin-contracts-5.7.0/crosschain/bridges/BridgeERC1155.sol b/dependencies/@openzeppelin-contracts-5.7.0/crosschain/bridges/BridgeERC1155.sol new file mode 100644 index 0000000..686ee6e --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.7.0/crosschain/bridges/BridgeERC1155.sol @@ -0,0 +1,131 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v5.7.0) (crosschain/bridges/BridgeERC1155.sol) + +pragma solidity ^0.8.26; + +import {IERC1155} from "../../interfaces/IERC1155.sol"; +import {IERC1155Receiver} from "../../interfaces/IERC1155Receiver.sol"; +import {IERC1155Errors} from "../../interfaces/draft-IERC6093.sol"; +import {ERC1155Holder} from "../../token/ERC1155/utils/ERC1155Holder.sol"; +import {BridgeMultiToken} from "./abstract/BridgeMultiToken.sol"; + +/** + * @dev This is a variant of {BridgeMultiToken} that implements the bridge logic for ERC-1155 tokens that do not expose + * a crosschain mint and burn mechanism. Instead, it takes custody of bridged assets. + */ +// slither-disable-next-line locked-ether +abstract contract BridgeERC1155 is BridgeMultiToken, ERC1155Holder { + IERC1155 private immutable _token; + + constructor(IERC1155 token_) { + _token = token_; + } + + /// @dev Return the address of the ERC1155 token this bridge operates on. + function token() public view virtual returns (IERC1155) { + return _token; + } + + /// @dev Equivalent to `crosschainTransferFrom(from, to, id, value, "")`. + function crosschainTransferFrom(address from, bytes memory to, uint256 id, uint256 value) public returns (bytes32) { + return crosschainTransferFrom(from, to, id, value, ""); + } + + /** + * @dev Transfer `value` of token `id` to a crosschain receiver. `data` is forwarded to the destination-chain + * ERC-1155 receiver's acceptance hook. + * + * Note: The `to` parameter is the full InteroperableAddress (chain ref + address). + */ + function crosschainTransferFrom( + address from, + bytes memory to, + uint256 id, + uint256 value, + bytes memory data + ) public returns (bytes32) { + uint256[] memory ids = new uint256[](1); + uint256[] memory values = new uint256[](1); + ids[0] = id; + values[0] = value; + + return crosschainTransferFrom(from, to, ids, values, data); + } + + /// @dev Equivalent to `crosschainTransferFrom(from, to, ids, values, "")`. + function crosschainTransferFrom( + address from, + bytes memory to, + uint256[] memory ids, + uint256[] memory values + ) public returns (bytes32) { + return crosschainTransferFrom(from, to, ids, values, ""); + } + + /** + * @dev Transfer `values` of tokens `ids` to a crosschain receiver. `data` is forwarded to the destination-chain + * ERC-1155 receiver's acceptance hook. + * + * Note: The `to` parameter is the full InteroperableAddress (chain ref + address). + */ + function crosschainTransferFrom( + address from, + bytes memory to, + uint256[] memory ids, + uint256[] memory values, + bytes memory data + ) public virtual returns (bytes32) { + // Permission is handled using the ERC1155's allowance system. This check replicates `ERC1155._checkAuthorized`. + address spender = _msgSender(); + require( + from == spender || token().isApprovedForAll(from, spender), + IERC1155Errors.ERC1155MissingApprovalForAll(spender, from) + ); + + // Perform the crosschain transfer and return the handler + return _crosschainTransfer(from, to, ids, values, data); + } + + /// @dev "Locking" tokens is done by taking custody. + function _onSend(address from, uint256[] memory ids, uint256[] memory values) internal virtual override { + token().safeBatchTransferFrom(from, address(this), ids, values, ""); + } + + /// @dev "Unlocking" tokens is done by releasing custody. + function _onReceive( + address to, + uint256[] memory ids, + uint256[] memory values, + bytes memory data + ) internal virtual override { + token().safeBatchTransferFrom(address(this), to, ids, values, data); + } + + /// @dev Support receiving tokens only if the transfer was initiated by the bridge itself. + function onERC1155Received( + address operator, + address /* from */, + uint256 /* id */, + uint256 /* value */, + bytes memory /* data */ + ) public virtual override returns (bytes4) { + return + msg.sender == address(_token) && operator == address(this) + ? IERC1155Receiver.onERC1155Received.selector + : bytes4(0); + } + + /// @dev Support receiving tokens only if the transfer was initiated by the bridge itself. + function onERC1155BatchReceived( + address operator, + address /* from */, + uint256[] memory /* ids */, + uint256[] memory /* values */, + bytes memory /* data */ + ) public virtual override returns (bytes4) { + return + msg.sender == address(_token) && operator == address(this) + ? IERC1155Receiver.onERC1155BatchReceived.selector + : bytes4(0); + } +} diff --git a/dependencies/@openzeppelin-contracts-5.7.0/crosschain/bridges/BridgeERC20.sol b/dependencies/@openzeppelin-contracts-5.7.0/crosschain/bridges/BridgeERC20.sol new file mode 100644 index 0000000..abbd156 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.7.0/crosschain/bridges/BridgeERC20.sol @@ -0,0 +1,42 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v5.7.0) (crosschain/bridges/BridgeERC20.sol) + +pragma solidity ^0.8.26; + +import {IERC20, SafeERC20} from "../../token/ERC20/utils/SafeERC20.sol"; +import {BridgeFungible} from "./abstract/BridgeFungible.sol"; + +/** + * @dev This is a variant of {BridgeFungible} that implements the bridge logic for ERC-20 tokens that do not expose a + * crosschain mint and burn mechanism. Instead, it takes custody of bridged assets. + * + * WARNING: Any mechanism in which the underlying token changes the {IERC20-balanceOf} of an account without an explicit + * transfer may desynchronize this contract's custodied balance from the supply minted or unlocked on the counterpart + * chain. Once the counterpart chain supply exceeds the custodied balance, redemptions on this chain revert in + * {SafeERC20-safeTransfer} due to insufficient balance. + */ +// slither-disable-next-line locked-ether +abstract contract BridgeERC20 is BridgeFungible { + using SafeERC20 for IERC20; + + IERC20 private immutable _token; + + constructor(IERC20 token_) { + _token = token_; + } + + /// @dev Return the address of the ERC20 token this bridge operates on. + function token() public view virtual returns (IERC20) { + return _token; + } + + /// @dev "Locking" tokens is done by taking custody + function _onSend(address from, uint256 amount) internal virtual override { + token().safeTransferFrom(from, address(this), amount); + } + + /// @dev "Unlocking" tokens is done by releasing custody + function _onReceive(address to, uint256 amount) internal virtual override { + token().safeTransfer(to, amount); + } +} diff --git a/dependencies/@openzeppelin-contracts-5.7.0/crosschain/bridges/BridgeERC721.sol b/dependencies/@openzeppelin-contracts-5.7.0/crosschain/bridges/BridgeERC721.sol new file mode 100644 index 0000000..782d1f0 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.7.0/crosschain/bridges/BridgeERC721.sol @@ -0,0 +1,62 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v5.7.0) (crosschain/bridges/BridgeERC721.sol) + +pragma solidity ^0.8.26; + +import {IERC721} from "../../interfaces/IERC721.sol"; +import {IERC721Errors} from "../../interfaces/draft-IERC6093.sol"; +import {BridgeNonFungible} from "./abstract/BridgeNonFungible.sol"; + +/** + * @dev This is a variant of {BridgeNonFungible} that implements the bridge logic for ERC-721 tokens that do not expose + * a crosschain mint and burn mechanism. Instead, it takes custody of bridged assets. + */ +// slither-disable-next-line locked-ether +abstract contract BridgeERC721 is BridgeNonFungible { + IERC721 private immutable _token; + + constructor(IERC721 token_) { + _token = token_; + } + + /// @dev Return the address of the ERC721 token this bridge operates on. + function token() public view virtual returns (IERC721) { + return _token; + } + + /** + * @dev Transfer `tokenId` from `from` (on this chain) to `to` (on a different chain). + * + * The `to` parameter is the full InteroperableAddress that references both the destination chain and the account + * on that chain. Similarly to the underlying token's {ERC721-transferFrom} function, this function can be called + * either by the token holder or by anyone that is approved by the token holder. It reuses the token's allowance + * system, meaning that an account that is "approved for all" or "approved for tokenId" can perform the crosschain + * transfer directly without having to take temporary custody of the token. + */ + function crosschainTransferFrom(address from, bytes memory to, uint256 tokenId) public virtual returns (bytes32) { + // Permission is handled using the ERC721's allowance system. This check replicates `ERC721._isAuthorized`. + address spender = _msgSender(); + require( + from == spender || token().isApprovedForAll(from, spender) || token().getApproved(tokenId) == spender, + IERC721Errors.ERC721InsufficientApproval(spender, tokenId) + ); + + // This call verifies that `from` is the owner of `tokenId` (in `_onSend`), and the previous checks ensure + // that `spender` is allowed to move tokenId on behalf of `from`. + // + // Perform the crosschain transfer and return the send id + return _crosschainTransfer(from, to, tokenId); + } + + /// @dev "Locking" tokens is done by taking custody + function _onSend(address from, uint256 tokenId) internal virtual override { + // slither-disable-next-line arbitrary-send-erc20 + token().transferFrom(from, address(this), tokenId); + } + + /// @dev "Unlocking" tokens is done by releasing custody + function _onReceive(address to, uint256 tokenId) internal virtual override { + // slither-disable-next-line arbitrary-send-erc20 + token().transferFrom(address(this), to, tokenId); + } +} diff --git a/dependencies/@openzeppelin-contracts-5.7.0/crosschain/bridges/BridgeERC7802.sol b/dependencies/@openzeppelin-contracts-5.7.0/crosschain/bridges/BridgeERC7802.sol new file mode 100644 index 0000000..76a0ff9 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.7.0/crosschain/bridges/BridgeERC7802.sol @@ -0,0 +1,34 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v5.6.0) (crosschain/bridges/BridgeERC7802.sol) + +pragma solidity ^0.8.26; + +import {IERC7802} from "../../interfaces/draft-IERC7802.sol"; +import {BridgeFungible} from "./abstract/BridgeFungible.sol"; + +/** + * @dev This is a variant of {BridgeFungible} that implements the bridge logic for ERC-7802 compliant tokens. + */ +// slither-disable-next-line locked-ether +abstract contract BridgeERC7802 is BridgeFungible { + IERC7802 private immutable _token; + + constructor(IERC7802 token_) { + _token = token_; + } + + /// @dev Return the address of the ERC20 token this bridge operates on. + function token() public view virtual returns (IERC7802) { + return _token; + } + + /// @dev "Locking" tokens using an ERC-7802 crosschain burn + function _onSend(address from, uint256 amount) internal virtual override { + token().crosschainBurn(from, amount); + } + + /// @dev "Unlocking" tokens using an ERC-7802 crosschain mint + function _onReceive(address to, uint256 amount) internal virtual override { + token().crosschainMint(to, amount); + } +} diff --git a/dependencies/@openzeppelin-contracts-5.7.0/crosschain/bridges/abstract/BridgeFungible.sol b/dependencies/@openzeppelin-contracts-5.7.0/crosschain/bridges/abstract/BridgeFungible.sol new file mode 100644 index 0000000..3755585 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.7.0/crosschain/bridges/abstract/BridgeFungible.sol @@ -0,0 +1,86 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v5.7.0) (crosschain/bridges/abstract/BridgeFungible.sol) + +pragma solidity ^0.8.26; + +import {InteroperableAddress} from "../../../utils/draft-InteroperableAddress.sol"; +import {Context} from "../../../utils/Context.sol"; +import {ERC7786Recipient} from "../../ERC7786Recipient.sol"; +import {CrosschainLinked} from "../../CrosschainLinked.sol"; + +/** + * @dev Base contract for bridging ERC-20 between chains using an ERC-7786 gateway. + * + * In order to use this contract, two functions must be implemented to link it to the token: + * * {_onSend}: called when a crosschain transfer is going out. Must take the sender tokens or revert. + * * {_onReceive}: called when a crosschain transfer is coming in. Must give tokens to the receiver. + * + * This base contract is used by the {BridgeERC20}, which interfaces with legacy ERC-20 tokens, and {BridgeERC7802}, + * which interface with ERC-7802 to provide an approve-free user experience. It is also used by the {ERC20Crosschain} + * extension, which embeds the bridge logic directly in the token contract. + */ +abstract contract BridgeFungible is Context, CrosschainLinked { + /// @dev Emitted when a crosschain ERC-20 transfer is sent. + event CrosschainFungibleTransferSent(bytes32 indexed sendId, address indexed from, bytes to, uint256 amount); + + /// @dev Emitted when a crosschain ERC-20 transfer is received. + event CrosschainFungibleTransferReceived(bytes32 indexed receiveId, bytes from, address indexed to, uint256 amount); + + /// @dev Revert reason when the address part of the interoperable address is empty. + error CrosschainFungibleEmptyAddress(); + + /** + * @dev Transfer `amount` tokens to a crosschain receiver. + * + * Note: The `to` parameter is the full InteroperableAddress (chain ref + address). + */ + function crosschainTransfer(bytes memory to, uint256 amount) public virtual returns (bytes32) { + return _crosschainTransfer(_msgSender(), to, amount); + } + + /** + * @dev Internal crosschain transfer function. + * + * Note: The `to` parameter is the full InteroperableAddress (chain ref + address). + */ + function _crosschainTransfer(address from, bytes memory to, uint256 amount) internal virtual returns (bytes32) { + _onSend(from, amount); + + (bytes2 chainType, bytes memory chainReference, bytes memory addr) = InteroperableAddress.parseV1(to); + require(addr.length > 0, CrosschainFungibleEmptyAddress()); + + bytes32 sendId = _sendMessageToCounterpart( + InteroperableAddress.formatV1(chainType, chainReference, hex""), + abi.encode(InteroperableAddress.formatEvmV1(block.chainid, from), addr, amount), + new bytes[](0) + ); + + emit CrosschainFungibleTransferSent(sendId, from, to, amount); + + return sendId; + } + + /// @inheritdoc ERC7786Recipient + function _processMessage( + address /*gateway*/, + bytes32 receiveId, + bytes calldata /*sender*/, + bytes calldata payload + ) internal virtual override { + // NOTE: Gateway is validated by {_isAuthorizedGateway} (implemented in {CrosschainLinked}). No need to check here. + + // split payload + (bytes memory from, bytes memory toEvm, uint256 amount) = abi.decode(payload, (bytes, bytes, uint256)); + address to = address(bytes20(toEvm)); + + _onReceive(to, amount); + + emit CrosschainFungibleTransferReceived(receiveId, from, to, amount); + } + + /// @dev Virtual function: implementation is required to handle token being burnt or locked on the source chain. + function _onSend(address from, uint256 amount) internal virtual; + + /// @dev Virtual function: implementation is required to handle token being minted or unlocked on the destination chain. + function _onReceive(address to, uint256 amount) internal virtual; +} diff --git a/dependencies/@openzeppelin-contracts-5.7.0/crosschain/bridges/abstract/BridgeMultiToken.sol b/dependencies/@openzeppelin-contracts-5.7.0/crosschain/bridges/abstract/BridgeMultiToken.sol new file mode 100644 index 0000000..1faca4f --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.7.0/crosschain/bridges/abstract/BridgeMultiToken.sol @@ -0,0 +1,99 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v5.7.0) (crosschain/bridges/abstract/BridgeMultiToken.sol) + +pragma solidity ^0.8.26; + +import {InteroperableAddress} from "../../../utils/draft-InteroperableAddress.sol"; +import {Context} from "../../../utils/Context.sol"; +import {ERC7786Recipient} from "../../ERC7786Recipient.sol"; +import {CrosschainLinked} from "../../CrosschainLinked.sol"; + +/** + * @dev Base contract for bridging ERC-1155 between chains using an ERC-7786 gateway. + * + * In order to use this contract, two functions must be implemented to link it to the token: + * * {_onSend}: called when a crosschain transfer is going out. Must take the sender tokens or revert. + * * {_onReceive}: called when a crosschain transfer is coming in. Must give tokens to the receiver. + * + * This base contract is used by the {BridgeERC1155}, which interfaces with legacy ERC-1155 tokens. It is also used by + * the {ERC1155Crosschain} extension, which embeds the bridge logic directly in the token contract. + * + * This base contract implements the crosschain transfer operation through internal functions. It is for the "child + * contracts" that inherit from this to implement the external interfaces and make these functions accessible. + */ +abstract contract BridgeMultiToken is Context, CrosschainLinked { + using InteroperableAddress for bytes; + + event CrosschainMultiTokenTransferSent( + bytes32 indexed sendId, + address indexed from, + bytes to, + uint256[] ids, + uint256[] values, + bytes data + ); + event CrosschainMultiTokenTransferReceived( + bytes32 indexed receiveId, + bytes from, + address indexed to, + uint256[] ids, + uint256[] values, + bytes data + ); + + /// @dev Revert reason when the address part of the interoperable address is empty. + error CrosschainMultiTokenEmptyAddress(); + + /** + * @dev Internal crosschain transfer function. `data` is forwarded through the ERC-7786 payload to + * {_onReceive} on the destination chain. + * + * Note: The `to` parameter is the full InteroperableAddress (chain ref + address). + */ + function _crosschainTransfer( + address from, + bytes memory to, + uint256[] memory ids, + uint256[] memory values, + bytes memory data + ) internal virtual returns (bytes32) { + _onSend(from, ids, values); + + (bytes2 chainType, bytes memory chainReference, bytes memory addr) = to.parseV1(); + require(addr.length > 0, CrosschainMultiTokenEmptyAddress()); + + bytes32 sendId = _sendMessageToCounterpart( + InteroperableAddress.formatV1(chainType, chainReference, hex""), + abi.encode(InteroperableAddress.formatEvmV1(block.chainid, from), addr, ids, values, data), + new bytes[](0) + ); + + emit CrosschainMultiTokenTransferSent(sendId, from, to, ids, values, data); + return sendId; + } + + /// @inheritdoc ERC7786Recipient + function _processMessage( + address /*gateway*/, + bytes32 receiveId, + bytes calldata /*sender*/, + bytes calldata payload + ) internal virtual override { + // NOTE: Gateway is validated by {_isAuthorizedGateway} (implemented in {CrosschainLinked}). No need to check here. + + // split payload + (bytes memory from, bytes memory toEvm, uint256[] memory ids, uint256[] memory values, bytes memory data) = abi + .decode(payload, (bytes, bytes, uint256[], uint256[], bytes)); + address to = address(bytes20(toEvm)); + + _onReceive(to, ids, values, data); + + emit CrosschainMultiTokenTransferReceived(receiveId, from, to, ids, values, data); + } + + /// @dev Virtual function: implementation is required to handle token being burnt or locked on the source chain. + function _onSend(address from, uint256[] memory ids, uint256[] memory values) internal virtual; + + /// @dev Virtual function: implementation is required to handle token being minted or unlocked on the destination chain. + function _onReceive(address to, uint256[] memory ids, uint256[] memory values, bytes memory data) internal virtual; +} diff --git a/dependencies/@openzeppelin-contracts-5.7.0/crosschain/bridges/abstract/BridgeNonFungible.sol b/dependencies/@openzeppelin-contracts-5.7.0/crosschain/bridges/abstract/BridgeNonFungible.sol new file mode 100644 index 0000000..49b85aa --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.7.0/crosschain/bridges/abstract/BridgeNonFungible.sol @@ -0,0 +1,79 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v5.7.0) (crosschain/bridges/abstract/BridgeNonFungible.sol) + +pragma solidity ^0.8.26; + +import {InteroperableAddress} from "../../../utils/draft-InteroperableAddress.sol"; +import {Context} from "../../../utils/Context.sol"; +import {ERC7786Recipient} from "../../ERC7786Recipient.sol"; +import {CrosschainLinked} from "../../CrosschainLinked.sol"; + +/** + * @dev Base contract for bridging ERC-721 between chains using an ERC-7786 gateway. + * + * In order to use this contract, two functions must be implemented to link it to the token: + * * {_onSend}: called when a crosschain transfer is going out. Must take the sender tokens or revert. + * * {_onReceive}: called when a crosschain transfer is coming in. Must give tokens to the receiver. + * + * This base contract is used by the {BridgeERC721}, which interfaces with legacy ERC-721 tokens. It is also used by + * the {ERC721Crosschain} extension, which embeds the bridge logic directly in the token contract. + */ +abstract contract BridgeNonFungible is Context, CrosschainLinked { + /// @dev Emitted when a crosschain ERC-721 transfer is sent. + event CrosschainNonFungibleTransferSent(bytes32 indexed sendId, address indexed from, bytes to, uint256 tokenId); + + /// @dev Emitted when a crosschain ERC-721 transfer is received. + event CrosschainNonFungibleTransferReceived( + bytes32 indexed receiveId, + bytes from, + address indexed to, + uint256 tokenId + ); + + /// @dev Revert reason when the address part of the interoperable address is empty. + error CrosschainNonFungibleEmptyAddress(); + + /** + * @dev Internal crosschain transfer function. + * + * NOTE: The `to` parameter is the full InteroperableAddress (chain ref + address). + */ + function _crosschainTransfer(address from, bytes memory to, uint256 tokenId) internal virtual returns (bytes32) { + _onSend(from, tokenId); + + (bytes2 chainType, bytes memory chainReference, bytes memory addr) = InteroperableAddress.parseV1(to); + require(addr.length > 0, CrosschainNonFungibleEmptyAddress()); + + bytes32 sendId = _sendMessageToCounterpart( + InteroperableAddress.formatV1(chainType, chainReference, hex""), + abi.encode(InteroperableAddress.formatEvmV1(block.chainid, from), addr, tokenId), + new bytes[](0) + ); + + emit CrosschainNonFungibleTransferSent(sendId, from, to, tokenId); + + return sendId; + } + + /// @inheritdoc ERC7786Recipient + function _processMessage( + address /*gateway*/, + bytes32 receiveId, + bytes calldata /*sender*/, + bytes calldata payload + ) internal virtual override { + // split payload + (bytes memory from, bytes memory toEvm, uint256 tokenId) = abi.decode(payload, (bytes, bytes, uint256)); + address to = address(bytes20(toEvm)); + + _onReceive(to, tokenId); + + emit CrosschainNonFungibleTransferReceived(receiveId, from, to, tokenId); + } + + /// @dev Virtual function: implementation is required to handle token being burnt or locked on the source chain. + function _onSend(address from, uint256 tokenId) internal virtual; + + /// @dev Virtual function: implementation is required to handle token being minted or unlocked on the destination chain. + function _onReceive(address to, uint256 tokenId) internal virtual; +} diff --git a/dependencies/@openzeppelin-contracts-5.5.0/finance/VestingWallet.sol b/dependencies/@openzeppelin-contracts-5.7.0/finance/VestingWallet.sol similarity index 98% rename from dependencies/@openzeppelin-contracts-5.5.0/finance/VestingWallet.sol rename to dependencies/@openzeppelin-contracts-5.7.0/finance/VestingWallet.sol index c627d4c..eabf885 100644 --- a/dependencies/@openzeppelin-contracts-5.5.0/finance/VestingWallet.sol +++ b/dependencies/@openzeppelin-contracts-5.7.0/finance/VestingWallet.sol @@ -1,5 +1,6 @@ // SPDX-License-Identifier: MIT -// OpenZeppelin Contracts (last updated v5.5.0) (finance/VestingWallet.sol) +// OpenZeppelin Contracts (last updated v5.6.0) (finance/VestingWallet.sol) + pragma solidity ^0.8.20; import {IERC20} from "../token/ERC20/IERC20.sol"; diff --git a/dependencies/@openzeppelin-contracts-5.5.0/finance/VestingWalletCliff.sol b/dependencies/@openzeppelin-contracts-5.7.0/finance/VestingWalletCliff.sol similarity index 88% rename from dependencies/@openzeppelin-contracts-5.5.0/finance/VestingWalletCliff.sol rename to dependencies/@openzeppelin-contracts-5.7.0/finance/VestingWalletCliff.sol index dd1da65..ef4ce90 100644 --- a/dependencies/@openzeppelin-contracts-5.5.0/finance/VestingWalletCliff.sol +++ b/dependencies/@openzeppelin-contracts-5.7.0/finance/VestingWalletCliff.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -// OpenZeppelin Contracts (last updated v5.1.0) (finance/VestingWalletCliff.sol) +// OpenZeppelin Contracts (last updated v5.7.0) (finance/VestingWalletCliff.sol) pragma solidity ^0.8.20; @@ -24,8 +24,9 @@ abstract contract VestingWalletCliff is VestingWallet { * constructor) and ends `cliffSeconds` later. */ constructor(uint64 cliffSeconds) { - if (cliffSeconds > duration()) { - revert InvalidCliffDuration(cliffSeconds, duration().toUint64()); + uint256 vestingDuration = duration(); + if (cliffSeconds > vestingDuration) { + revert InvalidCliffDuration(cliffSeconds, vestingDuration.toUint64()); } _cliff = start().toUint64() + cliffSeconds; } diff --git a/dependencies/@openzeppelin-contracts-5.5.0/governance/Governor.sol b/dependencies/@openzeppelin-contracts-5.7.0/governance/Governor.sol similarity index 98% rename from dependencies/@openzeppelin-contracts-5.5.0/governance/Governor.sol rename to dependencies/@openzeppelin-contracts-5.7.0/governance/Governor.sol index 6d49f11..fdb70fe 100644 --- a/dependencies/@openzeppelin-contracts-5.5.0/governance/Governor.sol +++ b/dependencies/@openzeppelin-contracts-5.7.0/governance/Governor.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -// OpenZeppelin Contracts (last updated v5.5.0) (governance/Governor.sol) +// OpenZeppelin Contracts (last updated v5.7.0) (governance/Governor.sol) pragma solidity ^0.8.24; @@ -348,16 +348,21 @@ abstract contract Governor is Context, ERC165, EIP712, Nonces, IGovernor, IERC72 bytes32 descriptionHash ) public virtual returns (uint256) { uint256 proposalId = getProposalId(targets, values, calldatas, descriptionHash); + bool needsQueueing = proposalNeedsQueuing(proposalId); _validateStateBitmap(proposalId, _encodeStateBitmap(ProposalState.Succeeded)); + if (!needsQueueing) { + revert GovernorProposalQueueingNotRequired(proposalId); + } + uint48 etaSeconds = _queueOperations(proposalId, targets, values, calldatas, descriptionHash); if (etaSeconds != 0) { _proposals[proposalId].etaSeconds = etaSeconds; emit ProposalQueued(proposalId, etaSeconds); } else { - revert GovernorQueueNotImplemented(); + revert GovernorProposalQueueingFailed(proposalId); } return proposalId; @@ -394,10 +399,11 @@ abstract contract Governor is Context, ERC165, EIP712, Nonces, IGovernor, IERC72 bytes32 descriptionHash ) public payable virtual returns (uint256) { uint256 proposalId = getProposalId(targets, values, calldatas, descriptionHash); + bool needsQueueing = proposalNeedsQueuing(proposalId); _validateStateBitmap( proposalId, - _encodeStateBitmap(ProposalState.Succeeded) | _encodeStateBitmap(ProposalState.Queued) + _encodeStateBitmap(needsQueueing ? ProposalState.Queued : ProposalState.Succeeded) ); // mark as executed before calls to avoid reentrancy @@ -735,7 +741,7 @@ abstract contract Governor is Context, ERC165, EIP712, Nonces, IGovernor, IERC72 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 @@ -746,6 +752,7 @@ abstract contract Governor is Context, ERC165, EIP712, Nonces, IGovernor, IERC72 * 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. diff --git a/dependencies/@openzeppelin-contracts-5.5.0/governance/IGovernor.sol b/dependencies/@openzeppelin-contracts-5.7.0/governance/IGovernor.sol similarity index 97% rename from dependencies/@openzeppelin-contracts-5.5.0/governance/IGovernor.sol rename to dependencies/@openzeppelin-contracts-5.7.0/governance/IGovernor.sol index 0988b4e..7e9de61 100644 --- a/dependencies/@openzeppelin-contracts-5.5.0/governance/IGovernor.sol +++ b/dependencies/@openzeppelin-contracts-5.7.0/governance/IGovernor.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -// OpenZeppelin Contracts (last updated v5.5.0) (governance/IGovernor.sol) +// OpenZeppelin Contracts (last updated v5.7.0) (governance/IGovernor.sol) pragma solidity >=0.8.4; @@ -87,14 +87,14 @@ interface IGovernor is IERC165, IERC6372 { error GovernorInvalidVoteParams(); /** - * @dev Queue operation is not implemented for this governor. Execute should be called directly. + * @dev This operation doesn't require queuing and should be executed directly. */ - error GovernorQueueNotImplemented(); + error GovernorProposalQueueingNotRequired(uint256 proposalId); /** - * @dev The proposal hasn't been queued yet. + * @dev Indicates a misconfigured timelock module. (e.g. {_queueOperations} returned a zero ETA) */ - error GovernorNotQueuedProposal(uint256 proposalId); + error GovernorProposalQueueingFailed(uint256 proposalId); /** * @dev The proposal has already been queued. diff --git a/dependencies/@openzeppelin-contracts-5.5.0/governance/TimelockController.sol b/dependencies/@openzeppelin-contracts-5.7.0/governance/TimelockController.sol similarity index 99% rename from dependencies/@openzeppelin-contracts-5.5.0/governance/TimelockController.sol rename to dependencies/@openzeppelin-contracts-5.7.0/governance/TimelockController.sol index 52aadce..f39d12a 100644 --- a/dependencies/@openzeppelin-contracts-5.5.0/governance/TimelockController.sol +++ b/dependencies/@openzeppelin-contracts-5.7.0/governance/TimelockController.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -// OpenZeppelin Contracts (last updated v5.5.0) (governance/TimelockController.sol) +// OpenZeppelin Contracts (last updated v5.6.0) (governance/TimelockController.sol) pragma solidity ^0.8.20; @@ -7,7 +7,6 @@ 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 @@ -155,7 +154,7 @@ contract TimelockController is AccessControl, ERC721Holder, ERC1155Holder { */ receive() external payable virtual {} - /// @inheritdoc IERC165 + /// @inheritdoc AccessControl function supportsInterface( bytes4 interfaceId ) public view virtual override(AccessControl, ERC1155Holder) returns (bool) { diff --git a/dependencies/@openzeppelin-contracts-5.5.0/governance/extensions/GovernorCountingFractional.sol b/dependencies/@openzeppelin-contracts-5.7.0/governance/extensions/GovernorCountingFractional.sol similarity index 100% rename from dependencies/@openzeppelin-contracts-5.5.0/governance/extensions/GovernorCountingFractional.sol rename to dependencies/@openzeppelin-contracts-5.7.0/governance/extensions/GovernorCountingFractional.sol diff --git a/dependencies/@openzeppelin-contracts-5.5.0/governance/extensions/GovernorCountingOverridable.sol b/dependencies/@openzeppelin-contracts-5.7.0/governance/extensions/GovernorCountingOverridable.sol similarity index 96% rename from dependencies/@openzeppelin-contracts-5.5.0/governance/extensions/GovernorCountingOverridable.sol rename to dependencies/@openzeppelin-contracts-5.7.0/governance/extensions/GovernorCountingOverridable.sol index 45a72ea..f9a03c1 100644 --- a/dependencies/@openzeppelin-contracts-5.5.0/governance/extensions/GovernorCountingOverridable.sol +++ b/dependencies/@openzeppelin-contracts-5.7.0/governance/extensions/GovernorCountingOverridable.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -// OpenZeppelin Contracts (last updated v5.4.0) (governance/extensions/GovernorCountingOverridable.sol) +// OpenZeppelin Contracts (last updated v5.7.0) (governance/extensions/GovernorCountingOverridable.sol) pragma solidity ^0.8.24; @@ -12,6 +12,10 @@ 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}. + * + * NOTE: Override votes can only be cast while the proposal is active. Mechanisms that shorten the voting duration, + * such as the early closure implemented in {GovernorSuperQuorum}, may therefore prevent token holders from overriding + * the votes cast with their tokens by their delegates. */ abstract contract GovernorCountingOverridable is GovernorVotes { bytes32 public constant OVERRIDE_BALLOT_TYPEHASH = diff --git a/dependencies/@openzeppelin-contracts-5.5.0/governance/extensions/GovernorCountingSimple.sol b/dependencies/@openzeppelin-contracts-5.7.0/governance/extensions/GovernorCountingSimple.sol similarity index 100% rename from dependencies/@openzeppelin-contracts-5.5.0/governance/extensions/GovernorCountingSimple.sol rename to dependencies/@openzeppelin-contracts-5.7.0/governance/extensions/GovernorCountingSimple.sol diff --git a/dependencies/@openzeppelin-contracts-5.7.0/governance/extensions/GovernorCrosschain.sol b/dependencies/@openzeppelin-contracts-5.7.0/governance/extensions/GovernorCrosschain.sol new file mode 100644 index 0000000..5c9e28f --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.7.0/governance/extensions/GovernorCrosschain.sol @@ -0,0 +1,31 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v5.7.0) (governance/extensions/GovernorCrosschain.sol) + +pragma solidity ^0.8.26; + +import {Governor} from "../Governor.sol"; +import {Mode} from "../../account/utils/draft-ERC7579Utils.sol"; +import {IERC7786GatewaySource} from "../../interfaces/draft-IERC7786.sol"; + +/// @dev Extension of {Governor} for cross-chain governance through ERC-7786 gateways and {CrosschainRemoteExecutor}. +abstract contract GovernorCrosschain is Governor { + /// @dev Send crosschain instruction to an arbitrary remote executor via an arbitrary ERC-7786 gateway. + function relayCrosschain( + address gateway, + bytes memory executor, + Mode mode, + bytes memory executionCalldata + ) public virtual onlyGovernance { + _crosschainExecute(gateway, executor, mode, executionCalldata); + } + + /// @dev Send crosschain instruction to an arbitrary remote executor via an arbitrary ERC-7786 gateway. + function _crosschainExecute( + address gateway, + bytes memory executor, + Mode mode, + bytes memory executionCalldata + ) internal virtual { + IERC7786GatewaySource(gateway).sendMessage(executor, abi.encodePacked(mode, executionCalldata), new bytes[](0)); + } +} diff --git a/dependencies/@openzeppelin-contracts-5.5.0/governance/extensions/GovernorNoncesKeyed.sol b/dependencies/@openzeppelin-contracts-5.7.0/governance/extensions/GovernorNoncesKeyed.sol similarity index 100% rename from dependencies/@openzeppelin-contracts-5.5.0/governance/extensions/GovernorNoncesKeyed.sol rename to dependencies/@openzeppelin-contracts-5.7.0/governance/extensions/GovernorNoncesKeyed.sol diff --git a/dependencies/@openzeppelin-contracts-5.5.0/governance/extensions/GovernorPreventLateQuorum.sol b/dependencies/@openzeppelin-contracts-5.7.0/governance/extensions/GovernorPreventLateQuorum.sol similarity index 72% rename from dependencies/@openzeppelin-contracts-5.5.0/governance/extensions/GovernorPreventLateQuorum.sol rename to dependencies/@openzeppelin-contracts-5.7.0/governance/extensions/GovernorPreventLateQuorum.sol index 581f96e..3bb8000 100644 --- a/dependencies/@openzeppelin-contracts-5.5.0/governance/extensions/GovernorPreventLateQuorum.sol +++ b/dependencies/@openzeppelin-contracts-5.7.0/governance/extensions/GovernorPreventLateQuorum.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -// OpenZeppelin Contracts (last updated v5.4.0) (governance/extensions/GovernorPreventLateQuorum.sol) +// OpenZeppelin Contracts (last updated v5.7.0) (governance/extensions/GovernorPreventLateQuorum.sol) pragma solidity ^0.8.24; @@ -26,6 +26,9 @@ abstract contract GovernorPreventLateQuorum is Governor { /// @dev Emitted when the {lateQuorumVoteExtension} parameter is changed. event LateQuorumVoteExtensionSet(uint64 oldVoteExtension, uint64 newVoteExtension); + /// @dev Thrown when the {lateQuorumVoteExtension} parameter is set to a value larger than {_maxLateQuorumVoteExtension}. + error GovernorPreventLateQuorumVoteExtensionTooLarge(uint256 newVoteExtension, uint256 maxVoteExtension); + /** * @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 @@ -46,6 +49,10 @@ abstract contract GovernorPreventLateQuorum is Governor { /** * @dev Vote tally updated and detects if it caused quorum to be reached, potentially extending the voting period. * + * The extended deadline is computed as `clock() + lateQuorumVoteExtension()`. Since {lateQuorumVoteExtension} + * is bounded by {_maxLateQuorumVoteExtension} when set, this addition cannot overflow in practice and brick + * governance mid-vote. + * * May emit a {ProposalExtended} event. */ function _tallyUpdated(uint256 proposalId) internal virtual override { @@ -69,6 +76,19 @@ abstract contract GovernorPreventLateQuorum is Governor { return _voteExtension; } + /** + * @dev Upper bound applied to {lateQuorumVoteExtension} when it is set. Defaults to the voting period, + * resulting in a total maximum voting period of twice the governor's documented voting period. + * Can be overridden to provide a different upper bound. + * + * NOTE: {_tallyUpdated} adds `lateQuorumVoteExtension()` to `clock()` using `uint48` arithmetic, which is + * safe under the default bound. Overriding this to a value close to (or greater than) `type(uint48).max` + * can make that addition overflow and revert the quorum-reaching vote, bricking governance. + */ + function _maxLateQuorumVoteExtension() internal view virtual returns (uint256) { + return votingPeriod(); + } + /** * @dev Changes the {lateQuorumVoteExtension}. This operation can only be performed by the governance executor, * generally through a governance proposal. @@ -86,6 +106,10 @@ abstract contract GovernorPreventLateQuorum is Governor { * Emits a {LateQuorumVoteExtensionSet} event. */ function _setLateQuorumVoteExtension(uint48 newVoteExtension) internal virtual { + uint256 maxVoteExtension = _maxLateQuorumVoteExtension(); + if (newVoteExtension > maxVoteExtension) { + revert GovernorPreventLateQuorumVoteExtensionTooLarge(newVoteExtension, maxVoteExtension); + } emit LateQuorumVoteExtensionSet(_voteExtension, newVoteExtension); _voteExtension = newVoteExtension; } diff --git a/dependencies/@openzeppelin-contracts-5.5.0/governance/extensions/GovernorProposalGuardian.sol b/dependencies/@openzeppelin-contracts-5.7.0/governance/extensions/GovernorProposalGuardian.sol similarity index 100% rename from dependencies/@openzeppelin-contracts-5.5.0/governance/extensions/GovernorProposalGuardian.sol rename to dependencies/@openzeppelin-contracts-5.7.0/governance/extensions/GovernorProposalGuardian.sol diff --git a/dependencies/@openzeppelin-contracts-5.5.0/governance/extensions/GovernorSequentialProposalId.sol b/dependencies/@openzeppelin-contracts-5.7.0/governance/extensions/GovernorSequentialProposalId.sol similarity index 100% rename from dependencies/@openzeppelin-contracts-5.5.0/governance/extensions/GovernorSequentialProposalId.sol rename to dependencies/@openzeppelin-contracts-5.7.0/governance/extensions/GovernorSequentialProposalId.sol diff --git a/dependencies/@openzeppelin-contracts-5.5.0/governance/extensions/GovernorSettings.sol b/dependencies/@openzeppelin-contracts-5.7.0/governance/extensions/GovernorSettings.sol similarity index 100% rename from dependencies/@openzeppelin-contracts-5.5.0/governance/extensions/GovernorSettings.sol rename to dependencies/@openzeppelin-contracts-5.7.0/governance/extensions/GovernorSettings.sol diff --git a/dependencies/@openzeppelin-contracts-5.5.0/governance/extensions/GovernorStorage.sol b/dependencies/@openzeppelin-contracts-5.7.0/governance/extensions/GovernorStorage.sol similarity index 91% rename from dependencies/@openzeppelin-contracts-5.5.0/governance/extensions/GovernorStorage.sol rename to dependencies/@openzeppelin-contracts-5.7.0/governance/extensions/GovernorStorage.sol index b93a406..d833c5d 100644 --- a/dependencies/@openzeppelin-contracts-5.5.0/governance/extensions/GovernorStorage.sol +++ b/dependencies/@openzeppelin-contracts-5.7.0/governance/extensions/GovernorStorage.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -// OpenZeppelin Contracts (last updated v5.5.0) (governance/extensions/GovernorStorage.sol) +// OpenZeppelin Contracts (last updated v5.6.0) (governance/extensions/GovernorStorage.sol) pragma solidity ^0.8.24; @@ -55,6 +55,9 @@ abstract contract GovernorStorage is Governor { function queue(uint256 proposalId) public virtual { // here, using storage is more efficient than memory ProposalDetails storage details = _proposalDetails[proposalId]; + if (details.descriptionHash == 0) { + revert GovernorNonexistentProposal(proposalId); + } queue(details.targets, details.values, details.calldatas, details.descriptionHash); } @@ -64,6 +67,9 @@ abstract contract GovernorStorage is Governor { function execute(uint256 proposalId) public payable virtual { // here, using storage is more efficient than memory ProposalDetails storage details = _proposalDetails[proposalId]; + if (details.descriptionHash == 0) { + revert GovernorNonexistentProposal(proposalId); + } execute(details.targets, details.values, details.calldatas, details.descriptionHash); } @@ -73,6 +79,9 @@ abstract contract GovernorStorage is Governor { function cancel(uint256 proposalId) public virtual { // here, using storage is more efficient than memory ProposalDetails storage details = _proposalDetails[proposalId]; + if (details.descriptionHash == 0) { + revert GovernorNonexistentProposal(proposalId); + } cancel(details.targets, details.values, details.calldatas, details.descriptionHash); } diff --git a/dependencies/@openzeppelin-contracts-5.5.0/governance/extensions/GovernorSuperQuorum.sol b/dependencies/@openzeppelin-contracts-5.7.0/governance/extensions/GovernorSuperQuorum.sol similarity index 100% rename from dependencies/@openzeppelin-contracts-5.5.0/governance/extensions/GovernorSuperQuorum.sol rename to dependencies/@openzeppelin-contracts-5.7.0/governance/extensions/GovernorSuperQuorum.sol diff --git a/dependencies/@openzeppelin-contracts-5.5.0/governance/extensions/GovernorTimelockAccess.sol b/dependencies/@openzeppelin-contracts-5.7.0/governance/extensions/GovernorTimelockAccess.sol similarity index 100% rename from dependencies/@openzeppelin-contracts-5.5.0/governance/extensions/GovernorTimelockAccess.sol rename to dependencies/@openzeppelin-contracts-5.7.0/governance/extensions/GovernorTimelockAccess.sol diff --git a/dependencies/@openzeppelin-contracts-5.5.0/governance/extensions/GovernorTimelockCompound.sol b/dependencies/@openzeppelin-contracts-5.7.0/governance/extensions/GovernorTimelockCompound.sol similarity index 93% rename from dependencies/@openzeppelin-contracts-5.5.0/governance/extensions/GovernorTimelockCompound.sol rename to dependencies/@openzeppelin-contracts-5.7.0/governance/extensions/GovernorTimelockCompound.sol index 8f6183e..ba25b77 100644 --- a/dependencies/@openzeppelin-contracts-5.5.0/governance/extensions/GovernorTimelockCompound.sol +++ b/dependencies/@openzeppelin-contracts-5.7.0/governance/extensions/GovernorTimelockCompound.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -// OpenZeppelin Contracts (last updated v5.5.0) (governance/extensions/GovernorTimelockCompound.sol) +// OpenZeppelin Contracts (last updated v5.7.0) (governance/extensions/GovernorTimelockCompound.sol) pragma solidity ^0.8.24; @@ -14,15 +14,15 @@ import {SafeCast} from "../../utils/math/SafeCast.sol"; * 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 + * Using this model means the proposal will be operated by the {ICompoundTimelock} and not by the {Governor}. Thus, + * the assets and permissions must be attached to the {ICompoundTimelock}. 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. + * @dev Emitted when the timelock used for proposal execution is modified. */ event TimelockChange(address oldTimelock, address newTimelock); @@ -94,9 +94,6 @@ abstract contract GovernorTimelockCompound is Governor { 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); diff --git a/dependencies/@openzeppelin-contracts-5.5.0/governance/extensions/GovernorTimelockControl.sol b/dependencies/@openzeppelin-contracts-5.7.0/governance/extensions/GovernorTimelockControl.sol similarity index 100% rename from dependencies/@openzeppelin-contracts-5.5.0/governance/extensions/GovernorTimelockControl.sol rename to dependencies/@openzeppelin-contracts-5.7.0/governance/extensions/GovernorTimelockControl.sol diff --git a/dependencies/@openzeppelin-contracts-5.5.0/governance/extensions/GovernorVotes.sol b/dependencies/@openzeppelin-contracts-5.7.0/governance/extensions/GovernorVotes.sol similarity index 91% rename from dependencies/@openzeppelin-contracts-5.5.0/governance/extensions/GovernorVotes.sol rename to dependencies/@openzeppelin-contracts-5.7.0/governance/extensions/GovernorVotes.sol index 4ad5870..058f111 100644 --- a/dependencies/@openzeppelin-contracts-5.5.0/governance/extensions/GovernorVotes.sol +++ b/dependencies/@openzeppelin-contracts-5.7.0/governance/extensions/GovernorVotes.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -// OpenZeppelin Contracts (last updated v5.4.0) (governance/extensions/GovernorVotes.sol) +// OpenZeppelin Contracts (last updated v5.7.0) (governance/extensions/GovernorVotes.sol) pragma solidity ^0.8.24; @@ -7,6 +7,7 @@ import {Governor} from "../Governor.sol"; import {IVotes} from "../utils/IVotes.sol"; import {IERC5805} from "../../interfaces/IERC5805.sol"; import {Time} from "../../utils/types/Time.sol"; +import {ERC6372Utils} from "../../utils/ERC6372Utils.sol"; /** * @dev Extension of {Governor} for voting weight extraction from an {ERC20Votes} token, or since v4.5 an {ERC721Votes} @@ -46,7 +47,7 @@ abstract contract GovernorVotes is Governor { try token().CLOCK_MODE() returns (string memory clockmode) { return clockmode; } catch { - return "mode=blocknumber&from=default"; + return ERC6372Utils.blockNumberClockMode(clock); } } diff --git a/dependencies/@openzeppelin-contracts-5.5.0/governance/extensions/GovernorVotesQuorumFraction.sol b/dependencies/@openzeppelin-contracts-5.7.0/governance/extensions/GovernorVotesQuorumFraction.sol similarity index 100% rename from dependencies/@openzeppelin-contracts-5.5.0/governance/extensions/GovernorVotesQuorumFraction.sol rename to dependencies/@openzeppelin-contracts-5.7.0/governance/extensions/GovernorVotesQuorumFraction.sol diff --git a/dependencies/@openzeppelin-contracts-5.5.0/governance/extensions/GovernorVotesSuperQuorumFraction.sol b/dependencies/@openzeppelin-contracts-5.7.0/governance/extensions/GovernorVotesSuperQuorumFraction.sol similarity index 96% rename from dependencies/@openzeppelin-contracts-5.5.0/governance/extensions/GovernorVotesSuperQuorumFraction.sol rename to dependencies/@openzeppelin-contracts-5.7.0/governance/extensions/GovernorVotesSuperQuorumFraction.sol index 53a7049..4630e3c 100644 --- a/dependencies/@openzeppelin-contracts-5.5.0/governance/extensions/GovernorVotesSuperQuorumFraction.sol +++ b/dependencies/@openzeppelin-contracts-5.7.0/governance/extensions/GovernorVotesSuperQuorumFraction.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -// OpenZeppelin Contracts (last updated v5.5.0) (governance/extensions/GovernorVotesSuperQuorumFraction.sol) +// OpenZeppelin Contracts (last updated v5.7.0) (governance/extensions/GovernorVotesSuperQuorumFraction.sol) pragma solidity ^0.8.24; @@ -28,7 +28,7 @@ abstract contract GovernorVotesSuperQuorumFraction is GovernorVotesQuorumFractio error GovernorInvalidSuperQuorumFraction(uint256 superQuorumNumerator, uint256 denominator); /** - * @dev The super quorum set is not valid as it is smaller or equal to the quorum. + * @dev The super quorum set is not valid as it is smaller than the quorum. */ error GovernorInvalidSuperQuorumTooSmall(uint256 superQuorumNumerator, uint256 quorumNumerator); @@ -41,7 +41,7 @@ abstract contract GovernorVotesSuperQuorumFraction is GovernorVotesQuorumFractio * @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. + * be greater than or equal to the quorum. */ constructor(uint256 superQuorumNumeratorValue) { _updateSuperQuorumNumerator(superQuorumNumeratorValue); diff --git a/dependencies/@openzeppelin-contracts-5.5.0/governance/utils/IVotes.sol b/dependencies/@openzeppelin-contracts-5.7.0/governance/utils/IVotes.sol similarity index 100% rename from dependencies/@openzeppelin-contracts-5.5.0/governance/utils/IVotes.sol rename to dependencies/@openzeppelin-contracts-5.7.0/governance/utils/IVotes.sol diff --git a/dependencies/@openzeppelin-contracts-5.5.0/governance/utils/Votes.sol b/dependencies/@openzeppelin-contracts-5.7.0/governance/utils/Votes.sol similarity index 95% rename from dependencies/@openzeppelin-contracts-5.5.0/governance/utils/Votes.sol rename to dependencies/@openzeppelin-contracts-5.7.0/governance/utils/Votes.sol index d1a2369..0671852 100644 --- a/dependencies/@openzeppelin-contracts-5.5.0/governance/utils/Votes.sol +++ b/dependencies/@openzeppelin-contracts-5.7.0/governance/utils/Votes.sol @@ -1,5 +1,6 @@ // SPDX-License-Identifier: MIT -// OpenZeppelin Contracts (last updated v5.5.0) (governance/utils/Votes.sol) +// OpenZeppelin Contracts (last updated v5.7.0) (governance/utils/Votes.sol) + pragma solidity ^0.8.24; import {IERC5805} from "../../interfaces/IERC5805.sol"; @@ -10,6 +11,7 @@ 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"; +import {ERC6372Utils} from "../../utils/ERC6372Utils.sol"; /** * @dev This is a base abstract contract that tracks voting units, which are a measure of voting power that can be @@ -41,11 +43,6 @@ abstract contract Votes is Context, EIP712, Nonces, IERC5805 { Checkpoints.Trace208 private _totalCheckpoints; - /** - * @dev The clock was incorrectly modified. - */ - error ERC6372InconsistentClock(); - /** * @dev Lookup to future votes is not available. */ @@ -64,11 +61,7 @@ abstract contract Votes is Context, EIP712, Nonces, IERC5805 { */ // 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"; + return ERC6372Utils.blockNumberClockMode(clock); } /** @@ -224,9 +217,9 @@ abstract contract Votes is Context, EIP712, Nonces, IERC5805 { */ function _checkpoints( address account, - uint32 pos + uint32 index ) internal view virtual returns (Checkpoints.Checkpoint208 memory) { - return _delegateCheckpoints[account].at(pos); + return _delegateCheckpoints[account].pos(index); } function _push( diff --git a/dependencies/@openzeppelin-contracts-5.5.0/governance/utils/VotesExtended.sol b/dependencies/@openzeppelin-contracts-5.7.0/governance/utils/VotesExtended.sol similarity index 98% rename from dependencies/@openzeppelin-contracts-5.5.0/governance/utils/VotesExtended.sol rename to dependencies/@openzeppelin-contracts-5.7.0/governance/utils/VotesExtended.sol index 3585c9b..4e976ac 100644 --- a/dependencies/@openzeppelin-contracts-5.5.0/governance/utils/VotesExtended.sol +++ b/dependencies/@openzeppelin-contracts-5.7.0/governance/utils/VotesExtended.sol @@ -1,5 +1,6 @@ // SPDX-License-Identifier: MIT -// OpenZeppelin Contracts (last updated v5.5.0) (governance/utils/VotesExtended.sol) +// OpenZeppelin Contracts (last updated v5.6.0) (governance/utils/VotesExtended.sol) + pragma solidity ^0.8.24; import {Checkpoints} from "../../utils/structs/Checkpoints.sol"; diff --git a/dependencies/@openzeppelin-contracts-5.5.0/interfaces/IERC1155.sol b/dependencies/@openzeppelin-contracts-5.7.0/interfaces/IERC1155.sol similarity index 100% rename from dependencies/@openzeppelin-contracts-5.5.0/interfaces/IERC1155.sol rename to dependencies/@openzeppelin-contracts-5.7.0/interfaces/IERC1155.sol diff --git a/dependencies/@openzeppelin-contracts-5.5.0/interfaces/IERC1155MetadataURI.sol b/dependencies/@openzeppelin-contracts-5.7.0/interfaces/IERC1155MetadataURI.sol similarity index 100% rename from dependencies/@openzeppelin-contracts-5.5.0/interfaces/IERC1155MetadataURI.sol rename to dependencies/@openzeppelin-contracts-5.7.0/interfaces/IERC1155MetadataURI.sol diff --git a/dependencies/@openzeppelin-contracts-5.5.0/interfaces/IERC1155Receiver.sol b/dependencies/@openzeppelin-contracts-5.7.0/interfaces/IERC1155Receiver.sol similarity index 100% rename from dependencies/@openzeppelin-contracts-5.5.0/interfaces/IERC1155Receiver.sol rename to dependencies/@openzeppelin-contracts-5.7.0/interfaces/IERC1155Receiver.sol diff --git a/dependencies/@openzeppelin-contracts-5.5.0/interfaces/IERC1271.sol b/dependencies/@openzeppelin-contracts-5.7.0/interfaces/IERC1271.sol similarity index 100% rename from dependencies/@openzeppelin-contracts-5.5.0/interfaces/IERC1271.sol rename to dependencies/@openzeppelin-contracts-5.7.0/interfaces/IERC1271.sol diff --git a/dependencies/@openzeppelin-contracts-5.5.0/interfaces/IERC1363.sol b/dependencies/@openzeppelin-contracts-5.7.0/interfaces/IERC1363.sol similarity index 100% rename from dependencies/@openzeppelin-contracts-5.5.0/interfaces/IERC1363.sol rename to dependencies/@openzeppelin-contracts-5.7.0/interfaces/IERC1363.sol diff --git a/dependencies/@openzeppelin-contracts-5.5.0/interfaces/IERC1363Receiver.sol b/dependencies/@openzeppelin-contracts-5.7.0/interfaces/IERC1363Receiver.sol similarity index 100% rename from dependencies/@openzeppelin-contracts-5.5.0/interfaces/IERC1363Receiver.sol rename to dependencies/@openzeppelin-contracts-5.7.0/interfaces/IERC1363Receiver.sol diff --git a/dependencies/@openzeppelin-contracts-5.5.0/interfaces/IERC1363Spender.sol b/dependencies/@openzeppelin-contracts-5.7.0/interfaces/IERC1363Spender.sol similarity index 100% rename from dependencies/@openzeppelin-contracts-5.5.0/interfaces/IERC1363Spender.sol rename to dependencies/@openzeppelin-contracts-5.7.0/interfaces/IERC1363Spender.sol diff --git a/dependencies/@openzeppelin-contracts-5.5.0/interfaces/IERC165.sol b/dependencies/@openzeppelin-contracts-5.7.0/interfaces/IERC165.sol similarity index 100% rename from dependencies/@openzeppelin-contracts-5.5.0/interfaces/IERC165.sol rename to dependencies/@openzeppelin-contracts-5.7.0/interfaces/IERC165.sol diff --git a/dependencies/@openzeppelin-contracts-5.5.0/interfaces/IERC1820Implementer.sol b/dependencies/@openzeppelin-contracts-5.7.0/interfaces/IERC1820Implementer.sol similarity index 100% rename from dependencies/@openzeppelin-contracts-5.5.0/interfaces/IERC1820Implementer.sol rename to dependencies/@openzeppelin-contracts-5.7.0/interfaces/IERC1820Implementer.sol diff --git a/dependencies/@openzeppelin-contracts-5.5.0/interfaces/IERC1820Registry.sol b/dependencies/@openzeppelin-contracts-5.7.0/interfaces/IERC1820Registry.sol similarity index 100% rename from dependencies/@openzeppelin-contracts-5.5.0/interfaces/IERC1820Registry.sol rename to dependencies/@openzeppelin-contracts-5.7.0/interfaces/IERC1820Registry.sol diff --git a/dependencies/@openzeppelin-contracts-5.5.0/interfaces/IERC1967.sol b/dependencies/@openzeppelin-contracts-5.7.0/interfaces/IERC1967.sol similarity index 100% rename from dependencies/@openzeppelin-contracts-5.5.0/interfaces/IERC1967.sol rename to dependencies/@openzeppelin-contracts-5.7.0/interfaces/IERC1967.sol diff --git a/dependencies/@openzeppelin-contracts-5.5.0/interfaces/IERC20.sol b/dependencies/@openzeppelin-contracts-5.7.0/interfaces/IERC20.sol similarity index 100% rename from dependencies/@openzeppelin-contracts-5.5.0/interfaces/IERC20.sol rename to dependencies/@openzeppelin-contracts-5.7.0/interfaces/IERC20.sol diff --git a/dependencies/@openzeppelin-contracts-5.5.0/interfaces/IERC20Metadata.sol b/dependencies/@openzeppelin-contracts-5.7.0/interfaces/IERC20Metadata.sol similarity index 100% rename from dependencies/@openzeppelin-contracts-5.5.0/interfaces/IERC20Metadata.sol rename to dependencies/@openzeppelin-contracts-5.7.0/interfaces/IERC20Metadata.sol diff --git a/dependencies/@openzeppelin-contracts-5.5.0/interfaces/IERC2309.sol b/dependencies/@openzeppelin-contracts-5.7.0/interfaces/IERC2309.sol similarity index 100% rename from dependencies/@openzeppelin-contracts-5.5.0/interfaces/IERC2309.sol rename to dependencies/@openzeppelin-contracts-5.7.0/interfaces/IERC2309.sol diff --git a/dependencies/@openzeppelin-contracts-5.5.0/interfaces/IERC2612.sol b/dependencies/@openzeppelin-contracts-5.7.0/interfaces/IERC2612.sol similarity index 100% rename from dependencies/@openzeppelin-contracts-5.5.0/interfaces/IERC2612.sol rename to dependencies/@openzeppelin-contracts-5.7.0/interfaces/IERC2612.sol diff --git a/dependencies/@openzeppelin-contracts-5.5.0/interfaces/IERC2981.sol b/dependencies/@openzeppelin-contracts-5.7.0/interfaces/IERC2981.sol similarity index 100% rename from dependencies/@openzeppelin-contracts-5.5.0/interfaces/IERC2981.sol rename to dependencies/@openzeppelin-contracts-5.7.0/interfaces/IERC2981.sol diff --git a/dependencies/@openzeppelin-contracts-5.5.0/interfaces/IERC3156.sol b/dependencies/@openzeppelin-contracts-5.7.0/interfaces/IERC3156.sol similarity index 100% rename from dependencies/@openzeppelin-contracts-5.5.0/interfaces/IERC3156.sol rename to dependencies/@openzeppelin-contracts-5.7.0/interfaces/IERC3156.sol diff --git a/dependencies/@openzeppelin-contracts-5.5.0/interfaces/IERC3156FlashBorrower.sol b/dependencies/@openzeppelin-contracts-5.7.0/interfaces/IERC3156FlashBorrower.sol similarity index 100% rename from dependencies/@openzeppelin-contracts-5.5.0/interfaces/IERC3156FlashBorrower.sol rename to dependencies/@openzeppelin-contracts-5.7.0/interfaces/IERC3156FlashBorrower.sol diff --git a/dependencies/@openzeppelin-contracts-5.5.0/interfaces/IERC3156FlashLender.sol b/dependencies/@openzeppelin-contracts-5.7.0/interfaces/IERC3156FlashLender.sol similarity index 100% rename from dependencies/@openzeppelin-contracts-5.5.0/interfaces/IERC3156FlashLender.sol rename to dependencies/@openzeppelin-contracts-5.7.0/interfaces/IERC3156FlashLender.sol diff --git a/dependencies/@openzeppelin-contracts-5.5.0/interfaces/draft-IERC4337.sol b/dependencies/@openzeppelin-contracts-5.7.0/interfaces/IERC4337.sol similarity index 95% rename from dependencies/@openzeppelin-contracts-5.5.0/interfaces/draft-IERC4337.sol rename to dependencies/@openzeppelin-contracts-5.7.0/interfaces/IERC4337.sol index 752e4e4..4aa041d 100644 --- a/dependencies/@openzeppelin-contracts-5.5.0/interfaces/draft-IERC4337.sol +++ b/dependencies/@openzeppelin-contracts-5.7.0/interfaces/IERC4337.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -// OpenZeppelin Contracts (last updated v5.4.0) (interfaces/draft-IERC4337.sol) +// OpenZeppelin Contracts (last updated v5.7.0) (interfaces/IERC4337.sol) pragma solidity >=0.8.4; @@ -30,6 +30,8 @@ pragma solidity >=0.8.4; * - `preVerificationGas` (`uint256`) * - `gasFees` (`bytes32`): concatenation of maxPriorityFeePerGas (16 bytes) and maxFeePerGas (16 bytes) * - `paymasterAndData` (`bytes`): concatenation of paymaster fields (or empty) + * For EntryPoint v0.9+, may optionally include `paymasterSignature` at the end: + * `paymaster || paymasterVerificationGasLimit || paymasterPostOpGasLimit || paymasterData || paymasterSignature || paymasterSignatureSize || PAYMASTER_SIG_MAGIC` * - `signature` (`bytes`) */ struct PackedUserOperation { @@ -40,7 +42,7 @@ struct PackedUserOperation { 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 paymasterAndData; // `abi.encodePacked(paymaster, paymasterVerificationGasLimit, paymasterPostOpGasLimit, paymasterData[, paymasterSignature, paymasterSignatureSize, PAYMASTER_SIG_MAGIC])` (20 bytes, 16 bytes, 16 bytes, dynamic[, dynamic, 2 bytes, 8 bytes]) bytes signature; } diff --git a/dependencies/@openzeppelin-contracts-5.5.0/interfaces/IERC4626.sol b/dependencies/@openzeppelin-contracts-5.7.0/interfaces/IERC4626.sol similarity index 100% rename from dependencies/@openzeppelin-contracts-5.5.0/interfaces/IERC4626.sol rename to dependencies/@openzeppelin-contracts-5.7.0/interfaces/IERC4626.sol diff --git a/dependencies/@openzeppelin-contracts-5.5.0/interfaces/IERC4906.sol b/dependencies/@openzeppelin-contracts-5.7.0/interfaces/IERC4906.sol similarity index 100% rename from dependencies/@openzeppelin-contracts-5.5.0/interfaces/IERC4906.sol rename to dependencies/@openzeppelin-contracts-5.7.0/interfaces/IERC4906.sol diff --git a/dependencies/@openzeppelin-contracts-5.5.0/interfaces/IERC5267.sol b/dependencies/@openzeppelin-contracts-5.7.0/interfaces/IERC5267.sol similarity index 100% rename from dependencies/@openzeppelin-contracts-5.5.0/interfaces/IERC5267.sol rename to dependencies/@openzeppelin-contracts-5.7.0/interfaces/IERC5267.sol diff --git a/dependencies/@openzeppelin-contracts-5.5.0/interfaces/IERC5313.sol b/dependencies/@openzeppelin-contracts-5.7.0/interfaces/IERC5313.sol similarity index 100% rename from dependencies/@openzeppelin-contracts-5.5.0/interfaces/IERC5313.sol rename to dependencies/@openzeppelin-contracts-5.7.0/interfaces/IERC5313.sol diff --git a/dependencies/@openzeppelin-contracts-5.5.0/interfaces/IERC5805.sol b/dependencies/@openzeppelin-contracts-5.7.0/interfaces/IERC5805.sol similarity index 100% rename from dependencies/@openzeppelin-contracts-5.5.0/interfaces/IERC5805.sol rename to dependencies/@openzeppelin-contracts-5.7.0/interfaces/IERC5805.sol diff --git a/dependencies/@openzeppelin-contracts-5.5.0/interfaces/IERC6372.sol b/dependencies/@openzeppelin-contracts-5.7.0/interfaces/IERC6372.sol similarity index 80% rename from dependencies/@openzeppelin-contracts-5.5.0/interfaces/IERC6372.sol rename to dependencies/@openzeppelin-contracts-5.7.0/interfaces/IERC6372.sol index 447a8ea..6fa6f12 100644 --- a/dependencies/@openzeppelin-contracts-5.5.0/interfaces/IERC6372.sol +++ b/dependencies/@openzeppelin-contracts-5.7.0/interfaces/IERC6372.sol @@ -1,11 +1,13 @@ // SPDX-License-Identifier: MIT -// OpenZeppelin Contracts (last updated v5.4.0) (interfaces/IERC6372.sol) +// OpenZeppelin Contracts (last updated v5.7.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). + * + * NOTE: Clock must not return 0. */ function clock() external view returns (uint48); diff --git a/dependencies/@openzeppelin-contracts-5.5.0/interfaces/IERC6909.sol b/dependencies/@openzeppelin-contracts-5.7.0/interfaces/IERC6909.sol similarity index 88% rename from dependencies/@openzeppelin-contracts-5.5.0/interfaces/IERC6909.sol rename to dependencies/@openzeppelin-contracts-5.7.0/interfaces/IERC6909.sol index dd90d62..7e79890 100644 --- a/dependencies/@openzeppelin-contracts-5.5.0/interfaces/IERC6909.sol +++ b/dependencies/@openzeppelin-contracts-5.7.0/interfaces/IERC6909.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -// OpenZeppelin Contracts (last updated v5.5.0) (interfaces/IERC6909.sol) +// OpenZeppelin Contracts (last updated v5.7.0) (interfaces/IERC6909.sol) pragma solidity >=0.6.2; @@ -54,6 +54,12 @@ interface IERC6909 is IERC165 { * `type(uint256).max` signifies an unlimited approval. * * Must return true. + * + * WARNING: This function is subject to the same race condition risks as {IERC20-approve}. + * Changing an allowance with this method brings the risk that `spender` may use both the + * old and the new allowance by spending the previous allowance while the new one is in-flight. + * One possible solution to mitigate this race condition is to first reduce `spender`'s + * allowance to 0 and then set the desired value afterwards. */ function approve(address spender, uint256 id, uint256 amount) external returns (bool); diff --git a/dependencies/@openzeppelin-contracts-5.5.0/interfaces/IERC721.sol b/dependencies/@openzeppelin-contracts-5.7.0/interfaces/IERC721.sol similarity index 100% rename from dependencies/@openzeppelin-contracts-5.5.0/interfaces/IERC721.sol rename to dependencies/@openzeppelin-contracts-5.7.0/interfaces/IERC721.sol diff --git a/dependencies/@openzeppelin-contracts-5.5.0/interfaces/IERC721Enumerable.sol b/dependencies/@openzeppelin-contracts-5.7.0/interfaces/IERC721Enumerable.sol similarity index 100% rename from dependencies/@openzeppelin-contracts-5.5.0/interfaces/IERC721Enumerable.sol rename to dependencies/@openzeppelin-contracts-5.7.0/interfaces/IERC721Enumerable.sol diff --git a/dependencies/@openzeppelin-contracts-5.5.0/interfaces/IERC721Metadata.sol b/dependencies/@openzeppelin-contracts-5.7.0/interfaces/IERC721Metadata.sol similarity index 100% rename from dependencies/@openzeppelin-contracts-5.5.0/interfaces/IERC721Metadata.sol rename to dependencies/@openzeppelin-contracts-5.7.0/interfaces/IERC721Metadata.sol diff --git a/dependencies/@openzeppelin-contracts-5.5.0/interfaces/IERC721Receiver.sol b/dependencies/@openzeppelin-contracts-5.7.0/interfaces/IERC721Receiver.sol similarity index 100% rename from dependencies/@openzeppelin-contracts-5.5.0/interfaces/IERC721Receiver.sol rename to dependencies/@openzeppelin-contracts-5.7.0/interfaces/IERC721Receiver.sol diff --git a/dependencies/@openzeppelin-contracts-5.5.0/interfaces/IERC7751.sol b/dependencies/@openzeppelin-contracts-5.7.0/interfaces/IERC7751.sol similarity index 100% rename from dependencies/@openzeppelin-contracts-5.5.0/interfaces/IERC7751.sol rename to dependencies/@openzeppelin-contracts-5.7.0/interfaces/IERC7751.sol diff --git a/dependencies/@openzeppelin-contracts-5.5.0/interfaces/IERC777.sol b/dependencies/@openzeppelin-contracts-5.7.0/interfaces/IERC777.sol similarity index 100% rename from dependencies/@openzeppelin-contracts-5.5.0/interfaces/IERC777.sol rename to dependencies/@openzeppelin-contracts-5.7.0/interfaces/IERC777.sol diff --git a/dependencies/@openzeppelin-contracts-5.5.0/interfaces/IERC777Recipient.sol b/dependencies/@openzeppelin-contracts-5.7.0/interfaces/IERC777Recipient.sol similarity index 100% rename from dependencies/@openzeppelin-contracts-5.5.0/interfaces/IERC777Recipient.sol rename to dependencies/@openzeppelin-contracts-5.7.0/interfaces/IERC777Recipient.sol diff --git a/dependencies/@openzeppelin-contracts-5.5.0/interfaces/IERC777Sender.sol b/dependencies/@openzeppelin-contracts-5.7.0/interfaces/IERC777Sender.sol similarity index 100% rename from dependencies/@openzeppelin-contracts-5.5.0/interfaces/IERC777Sender.sol rename to dependencies/@openzeppelin-contracts-5.7.0/interfaces/IERC777Sender.sol diff --git a/dependencies/@openzeppelin-contracts-5.5.0/interfaces/IERC7913.sol b/dependencies/@openzeppelin-contracts-5.7.0/interfaces/IERC7913.sol similarity index 100% rename from dependencies/@openzeppelin-contracts-5.5.0/interfaces/IERC7913.sol rename to dependencies/@openzeppelin-contracts-5.7.0/interfaces/IERC7913.sol diff --git a/dependencies/@openzeppelin-contracts-5.5.0/interfaces/draft-IERC1822.sol b/dependencies/@openzeppelin-contracts-5.7.0/interfaces/draft-IERC1822.sol similarity index 100% rename from dependencies/@openzeppelin-contracts-5.5.0/interfaces/draft-IERC1822.sol rename to dependencies/@openzeppelin-contracts-5.7.0/interfaces/draft-IERC1822.sol diff --git a/dependencies/@openzeppelin-contracts-5.7.0/interfaces/draft-IERC3009.sol b/dependencies/@openzeppelin-contracts-5.7.0/interfaces/draft-IERC3009.sol new file mode 100644 index 0000000..ce37fe9 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.7.0/interfaces/draft-IERC3009.sol @@ -0,0 +1,87 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v5.7.0) (interfaces/draft-IERC3009.sol) + +pragma solidity >=0.4.16; + +/** + * @dev Interface of the ERC-3009 standard as defined in https://eips.ethereum.org/EIPS/eip-3009[ERC-3009]. + */ +interface IERC3009 { + /// @dev Emitted when an authorization is used. + event AuthorizationUsed(address indexed authorizer, bytes32 indexed nonce); + + /** + * @dev Returns whether the `nonce` has been used by `authorizer`. A `true` value means the authorization + * has already been consumed (either transferred or canceled) and can no longer be used; a `false` value + * means the nonce is still available. + * + * Nonces are randomly generated 32-byte values unique to the authorizer's address. + */ + function authorizationState(address authorizer, bytes32 nonce) external view returns (bool); + + /** + * @dev Executes a transfer with a signed authorization. + * + * Requirements: + * + * * `validAfter` must be less than the current block timestamp. + * * `validBefore` must be greater than the current block timestamp. + * * `nonce` must not have been used by the `from` account. + * * the signature must be valid for the authorization. + */ + function transferWithAuthorization( + address from, + address to, + uint256 value, + uint256 validAfter, + uint256 validBefore, + bytes32 nonce, + uint8 v, + bytes32 r, + bytes32 s + ) external; + + /** + * @dev Receives a transfer with a signed authorization from the payer. + * + * Includes an additional check to ensure that the payee's address (`to`) matches the caller + * to prevent front-running attacks. + * + * Requirements: + * + * * `to` must be the caller of this function. + * * `validAfter` must be less than the current block timestamp. + * * `validBefore` must be greater than the current block timestamp. + * * `nonce` must not have been used by the `from` account. + * * the signature must be valid for the authorization. + */ + function receiveWithAuthorization( + address from, + address to, + uint256 value, + uint256 validAfter, + uint256 validBefore, + bytes32 nonce, + uint8 v, + bytes32 r, + bytes32 s + ) external; +} + +/** + * @dev Extension of {IERC3009} that adds the ability to cancel authorizations. + */ +interface IERC3009Cancel { + /// @dev Emitted when an authorization is canceled. + event AuthorizationCanceled(address indexed authorizer, bytes32 indexed nonce); + + /** + * @dev Cancels an authorization. + * + * Requirements: + * + * * `nonce` must not have been used by the `authorizer` account. + * * the signature must be valid for the cancellation. + */ + function cancelAuthorization(address authorizer, bytes32 nonce, uint8 v, bytes32 r, bytes32 s) external; +} diff --git a/dependencies/@openzeppelin-contracts-5.5.0/interfaces/draft-IERC6093.sol b/dependencies/@openzeppelin-contracts-5.7.0/interfaces/draft-IERC6093.sol similarity index 100% rename from dependencies/@openzeppelin-contracts-5.5.0/interfaces/draft-IERC6093.sol rename to dependencies/@openzeppelin-contracts-5.7.0/interfaces/draft-IERC6093.sol diff --git a/dependencies/@openzeppelin-contracts-5.5.0/interfaces/draft-IERC7579.sol b/dependencies/@openzeppelin-contracts-5.7.0/interfaces/draft-IERC7579.sol similarity index 96% rename from dependencies/@openzeppelin-contracts-5.5.0/interfaces/draft-IERC7579.sol rename to dependencies/@openzeppelin-contracts-5.7.0/interfaces/draft-IERC7579.sol index 7688dbc..601981a 100644 --- a/dependencies/@openzeppelin-contracts-5.5.0/interfaces/draft-IERC7579.sol +++ b/dependencies/@openzeppelin-contracts-5.7.0/interfaces/draft-IERC7579.sol @@ -1,9 +1,9 @@ // SPDX-License-Identifier: MIT -// OpenZeppelin Contracts (last updated v5.5.0) (interfaces/draft-IERC7579.sol) +// OpenZeppelin Contracts (last updated v5.7.0) (interfaces/draft-IERC7579.sol) pragma solidity >=0.8.4; -import {PackedUserOperation} from "./draft-IERC4337.sol"; +import {PackedUserOperation} from "./IERC4337.sol"; uint256 constant VALIDATION_SUCCESS = 0; uint256 constant VALIDATION_FAILED = 1; @@ -116,7 +116,7 @@ struct Execution { 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 mode The encoded execution mode of the transaction. See account/utils/draft-ERC7579Utils.sol (Mode encoding via encodeMode/decodeMode) for details * @param executionCalldata The encoded execution call data * * MUST ensure adequate authorization control: e.g. onlyEntryPointOrSelf if used with ERC-4337 @@ -127,7 +127,7 @@ interface IERC7579Execution { /** * @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 mode The encoded execution mode of the transaction. See account/utils/draft-ERC7579Utils.sol (Mode encoding via encodeMode/decodeMode) for details * @param executionCalldata The encoded execution call data * @return returnData An array with the returned data of each executed subcall * diff --git a/dependencies/@openzeppelin-contracts-5.5.0/interfaces/draft-IERC7674.sol b/dependencies/@openzeppelin-contracts-5.7.0/interfaces/draft-IERC7674.sol similarity index 100% rename from dependencies/@openzeppelin-contracts-5.5.0/interfaces/draft-IERC7674.sol rename to dependencies/@openzeppelin-contracts-5.7.0/interfaces/draft-IERC7674.sol diff --git a/dependencies/@openzeppelin-contracts-5.5.0/interfaces/draft-IERC7786.sol b/dependencies/@openzeppelin-contracts-5.7.0/interfaces/draft-IERC7786.sol similarity index 100% rename from dependencies/@openzeppelin-contracts-5.5.0/interfaces/draft-IERC7786.sol rename to dependencies/@openzeppelin-contracts-5.7.0/interfaces/draft-IERC7786.sol diff --git a/dependencies/@openzeppelin-contracts-5.5.0/interfaces/draft-IERC7802.sol b/dependencies/@openzeppelin-contracts-5.7.0/interfaces/draft-IERC7802.sol similarity index 100% rename from dependencies/@openzeppelin-contracts-5.5.0/interfaces/draft-IERC7802.sol rename to dependencies/@openzeppelin-contracts-5.7.0/interfaces/draft-IERC7802.sol diff --git a/dependencies/@openzeppelin-contracts-5.5.0/interfaces/draft-IERC7821.sol b/dependencies/@openzeppelin-contracts-5.7.0/interfaces/draft-IERC7821.sol similarity index 100% rename from dependencies/@openzeppelin-contracts-5.5.0/interfaces/draft-IERC7821.sol rename to dependencies/@openzeppelin-contracts-5.7.0/interfaces/draft-IERC7821.sol diff --git a/dependencies/@openzeppelin-contracts-5.5.0/metatx/ERC2771Context.sol b/dependencies/@openzeppelin-contracts-5.7.0/metatx/ERC2771Context.sol similarity index 95% rename from dependencies/@openzeppelin-contracts-5.5.0/metatx/ERC2771Context.sol rename to dependencies/@openzeppelin-contracts-5.7.0/metatx/ERC2771Context.sol index ce6eca8..68ca9c5 100644 --- a/dependencies/@openzeppelin-contracts-5.5.0/metatx/ERC2771Context.sol +++ b/dependencies/@openzeppelin-contracts-5.7.0/metatx/ERC2771Context.sol @@ -1,12 +1,12 @@ // SPDX-License-Identifier: MIT -// OpenZeppelin Contracts (last updated v5.5.0) (metatx/ERC2771Context.sol) +// OpenZeppelin Contracts (last updated v5.6.0) (metatx/ERC2771Context.sol) pragma solidity ^0.8.20; import {Context} from "../utils/Context.sol"; /** - * @dev Context variant with ERC-2771 support. + * @dev Context variant with ERC-2771 support. See {_msgSender} for the calldata format. * * WARNING: Avoid using this pattern in contracts that rely on 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 diff --git a/dependencies/@openzeppelin-contracts-5.5.0/metatx/ERC2771Forwarder.sol b/dependencies/@openzeppelin-contracts-5.7.0/metatx/ERC2771Forwarder.sol similarity index 92% rename from dependencies/@openzeppelin-contracts-5.5.0/metatx/ERC2771Forwarder.sol rename to dependencies/@openzeppelin-contracts-5.7.0/metatx/ERC2771Forwarder.sol index 0ad433d..43e120a 100644 --- a/dependencies/@openzeppelin-contracts-5.5.0/metatx/ERC2771Forwarder.sol +++ b/dependencies/@openzeppelin-contracts-5.7.0/metatx/ERC2771Forwarder.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -// OpenZeppelin Contracts (last updated v5.5.0) (metatx/ERC2771Forwarder.sol) +// OpenZeppelin Contracts (last updated v5.7.0) (metatx/ERC2771Forwarder.sol) pragma solidity ^0.8.24; @@ -19,7 +19,7 @@ import {Errors} from "../utils/Errors.sol"; * * `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. + * * `nonce` (implicit): Taken from {Nonces} for `from` and included in the signed typed data. * * `deadline`: A timestamp after which the request is not executable anymore. * * `data`: Encoded `msg.data` to send with the requested call. * @@ -75,6 +75,11 @@ contract ERC2771Forwarder is EIP712, Nonces { */ event ExecutedForwardRequest(address indexed signer, uint256 nonce, bool success); + /** + * @dev A request in the batch failed and no `refundReceiver` was set to handle the leftover value. + */ + error ERC2771ForwarderNoRefundReceiver(); + /** * @dev The request `from` doesn't match with the recovered `signer`. */ @@ -138,40 +143,37 @@ contract ERC2771Forwarder is EIP712, Nonces { } /** - * @dev Batch version of {execute} with optional refunding and atomic execution. + * @dev Batch version of {execute} with optional refunding. * * 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. + * If the `refundReceiver` is `address(0)`, the function will revert + * when any request is invalid or when a valid request's forwarded call fails while + * carrying value (since there is no receiver to refund the leftover ETH to). * * 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. + * NOTE: Setting a zero `refundReceiver` reverts the whole batch if any request is invalid or a value-bearing + * call fails, so it should only be used when transaction inclusion is under the caller's control. */ function executeBatch( ForwardRequestData[] calldata requests, address payable refundReceiver ) public payable virtual { - bool atomic = refundReceiver == address(0); + bool requireValidRequests = refundReceiver == address(0); uint256 requestsValue; uint256 refundValue; for (uint256 i; i < requests.length; ++i) { requestsValue += requests[i].value; - bool success = _execute(requests[i], atomic); + bool success = _execute(requests[i], requireValidRequests); if (!success) { refundValue += requests[i].value; } @@ -184,8 +186,10 @@ contract ERC2771Forwarder is EIP712, Nonces { } // Some requests with value were invalid (possibly due to frontrunning). - // To avoid leaving ETH in the contract this value is refunded. + // To avoid leaving ETH in the contract, this value is refunded. if (refundValue != 0) { + if (requireValidRequests) revert ERC2771ForwarderNoRefundReceiver(); + // 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. @@ -195,7 +199,7 @@ contract ERC2771Forwarder is EIP712, Nonces { /** * @dev Validates if the provided request can be executed at current block timestamp with - * the given `request.signature` on behalf of `request.signer`. + * the given `request.signature` on behalf of `request.from`. */ function _validate( ForwardRequestData calldata request @@ -214,7 +218,7 @@ contract ERC2771Forwarder is EIP712, Nonces { * @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. + * NOTE: The signature is considered valid if {ECDSA-tryRecoverCalldata} indicates no recover error for it. */ function _recoverForwardRequestSigner( ForwardRequestData calldata request @@ -232,7 +236,7 @@ contract ERC2771Forwarder is EIP712, Nonces { keccak256(request.data) ) ) - ).tryRecover(request.signature); + ).tryRecoverCalldata(request.signature); return (err == ECDSA.RecoverError.NoError, recovered); } diff --git a/dependencies/@openzeppelin-contracts-5.5.0/proxy/Clones.sol b/dependencies/@openzeppelin-contracts-5.7.0/proxy/Clones.sol similarity index 100% rename from dependencies/@openzeppelin-contracts-5.5.0/proxy/Clones.sol rename to dependencies/@openzeppelin-contracts-5.7.0/proxy/Clones.sol diff --git a/dependencies/@openzeppelin-contracts-5.7.0/proxy/ERC1967/ERC1967Clones.sol b/dependencies/@openzeppelin-contracts-5.7.0/proxy/ERC1967/ERC1967Clones.sol new file mode 100644 index 0000000..ff1d1e4 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.7.0/proxy/ERC1967/ERC1967Clones.sol @@ -0,0 +1,219 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v5.7.0) (proxy/ERC1967/ERC1967Clones.sol) + +pragma solidity ^0.8.26; + +import {Create2} from "../../utils/Create2.sol"; +import {Errors} from "../../utils/Errors.sol"; +import {ERC1967Utils} from "./ERC1967Utils.sol"; +import {IERC1967} from "../../interfaces/IERC1967.sol"; + +/** + * @dev https://eips.ethereum.org/EIPS/eip-1967[ERC-1967] is the standard for upgradeable proxies that + * store the implementation address in a fixed storage slot. This library deploys minimal proxies that + * mimic the behavior of {ERC1967Proxy} with a bytecode optimized for cheap deployment and usage. The + * deployment emits {IERC1967-Upgraded} from the proxy address, so on-chain tooling and indexers can + * track the new instance from the block it was created in. + * + * The library includes functions to deploy a proxy using either `create` (traditional deployment) or + * `create2` (salted deterministic deployment). It also includes a function to predict the addresses of + * proxies deployed using the deterministic method. + * + * IMPORTANT: Unlike {ERC1967Proxy}, this proxy does not run an initialization call at construction and + * does not check that `implementation` has code. Calls forwarded to a non-contract `implementation` + * succeed silently and return empty data, which an uninitialized clone cannot distinguish from a + * legitimate response. Factories using this library are expected to invoke the initializer on the + * returned address in the same transaction as the deployment. + */ +library ERC1967Clones { + /** + * ========================================[ PROXY CODE ]======================================== + * Offset | Opcode | Mnemonic | Stack | Memory + * -------|-------------|------------------|----------------------------|------------------------ + * 0x00 | 36 | CALLDATASIZE | cds | + * 0x01 | 5f | PUSH0 | 0 cds | + * 0x02 | 5f | PUSH0 | 0 0 cds | + * 0x03 | 37 | CALLDATACOPY | | [0..cds): calldata + * 0x04 | 5f | PUSH0 | 0 | [0..cds): calldata + * 0x05 | 5f | PUSH0 | 0 0 | [0..cds): calldata + * 0x06 | 36 | CALLDATASIZE | cds 0 0 | [0..cds): calldata + * 0x07 | 5f | PUSH0 | 0 cds 0 0 | [0..cds): calldata + * 0x08 | 7f | PUSH32 slot | slot 0 cds 0 0 | [0..cds): calldata + * 0x29 | 54 | SLOAD | addr 0 cds 0 0 | [0..cds): calldata + * 0x2A | 5a | GAS | gas addr 0 cds 0 0 | [0..cds): calldata + * 0x2B | f4 | DELEGATECALL | success | + * 0x2C | 3d | RETURNDATASIZE | rds success | + * 0x2D | 5f | PUSH0 | 0 rds success | + * 0x2E | 5f | PUSH0 | 0 0 rds success | + * 0x2F | 3e | RETURNDATACOPY | success | [0...rds): returndata + * 0x30 | 6036 | PUSH1 0x36 | 0x36 success | [0...rds): returndata + * 0x32 | 57 | JUMPI | | [0...rds): returndata + * 0x33 | 3d | RETURNDATASIZE | rds | [0...rds): returndata + * 0x34 | 5f | PUSH0 | 0 rds | [0...rds): returndata + * 0x35 | fd | REVERT | | + * 0x36 | 5b | JUMPDEST | | [0...rds): returndata + * 0x37 | 3d | RETURNDATASIZE | rds | [0...rds): returndata + * 0x38 | 5f | PUSH0 | 0 rds | [0...rds): returndata + * 0x39 | f3 | RETURN | | + * + * =====================================[ DEPLOYMENT CODE ]===================================== + * Offset | Opcode | Mnemonic | Stack | Memory + * -------|-------------|------------------|----------------------------|------------------------ + * 0x00 | 603a | PUSH1 0x3a | 0x3a | + * 0x02 | 5f | PUSH0 | 0 0x3a | + * 0x03 | 81 | DUP2 | 0x3a 0 0x3a | + * 0x04 | 6047 | PUSH1 0x47 | 0x47 0x3a 0 0x3a | + * 0x06 | 5f | PUSH0 | 0 0x47 0x3a 0 0x3a | + * 0x07 | 39 | CODECOPY | 0 0x3a | [0...0x3a): proxycode + * 0x08 | 73 | PUSH20 impl | impl 0 0x3a | [0...0x3a): proxycode + * 0x1d | 80 | DUP1 | impl impl 0 0x3a | [0...0x3a): proxycode + * 0x1e | 7f | PUSH32 topic | topic impl impl 0 0x3a | [0...0x3a): proxycode + * 0x3f | 5f | PUSH0 | 0 topic impl impl 0 0x3a | [0...0x3a): proxycode + * 0x40 | 5f | PUSH0 | 0 0 topic impl impl 0 0x3a | [0...0x3a): proxycode + * 0x41 | a2 | LOG2 | impl 0 0x3a | [0...0x3a): proxycode + * 0x42 | 6009 | PUSH1 0x09 | 0x09 impl 0 0x3a | [0...0x3a): proxycode + * 0x44 | 51 | MLOAD | slot impl 0 0x3a | [0...0x3a): proxycode + * 0x45 | 55 | SSTORE | 0 0x3a | [0...0x3a): proxycode + * 0x46 | f3 | RETURN | | + * + * NOTE: + * - 0x3a: length of the proxy code + * - 0x47: length of the deployment code, since the proxy code is just after the deployment code, that is also the offset of the proxy code + * - 0x09: position of the ERC1967 implementation slot in the proxy code. + */ + + /** + * @dev Deploys and returns the address of a minimal ERC-1967 proxy that delegates to `implementation`. + * + * This function uses the create opcode, which should never revert. + * + * Emits an {IERC1967-Upgraded} event from the deployed proxy. + * + * WARNING: This function does not check if `implementation` has code, and the deployed proxy does not run + * any initialization call at construction. + */ + function clone(address implementation) internal returns (address) { + return clone(implementation, 0); + } + + /** + * @dev Same as {xref-ERC1967Clones-clone-address-}[clone], but with a `value` parameter to send native + * currency to the new contract. + * + * Emits an {IERC1967-Upgraded} event from the deployed proxy. + * + * WARNING: This function does not check if `implementation` has code, and the deployed proxy does not run + * any initialization call at construction. + * + * 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) { + require(address(this).balance >= value, Errors.InsufficientBalance(address(this).balance, value)); + bytes32 implementationSlot = ERC1967Utils.IMPLEMENTATION_SLOT; + bytes32 topic1 = IERC1967.Upgraded.selector; + assembly ("memory-safe") { + // Set code in memory + let ptr := mload(0x40) + mstore(add(ptr, 0x78), 0x545af43d5f5f3e6036573d5ffd5b3d5ff3) + mstore(add(ptr, 0x67), implementationSlot) + mstore(add(ptr, 0x47), 0x5f5fa260095155f3365f5f375f5f365f7f) + mstore(add(ptr, 0x36), topic1) + mstore(add(ptr, 0x16), 0x807f) + mstore(add(ptr, 0x14), implementation) + mstore(ptr, 0x603a5f8160475f3973) + + // Call create + instance := create(value, add(ptr, 0x17), 0x81) + } + + // deployment code doesn't have a revert, so no need to handle returndata + require(instance != address(0), Errors.FailedDeployment()); + } + + /** + * @dev Deploys and returns the address of a minimal ERC-1967 proxy that delegates to `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. + * + * Emits an {IERC1967-Upgraded} event from the deployed proxy. + * + * WARNING: This function does not check if `implementation` has code, and the deployed proxy does not run + * any initialization call at construction. + */ + function cloneDeterministic(address implementation, bytes32 salt) internal returns (address) { + return cloneDeterministic(implementation, salt, 0); + } + + /** + * @dev Same as {xref-ERC1967Clones-cloneDeterministic-address-bytes32-}[cloneDeterministic], but with a + * `value` parameter to send native currency to the new contract. + * + * Emits an {IERC1967-Upgraded} event from the deployed proxy. + * + * WARNING: This function does not check if `implementation` has code, and the deployed proxy does not run + * any initialization call at construction. + * + * 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) { + require(address(this).balance >= value, Errors.InsufficientBalance(address(this).balance, value)); + bytes32 implementationSlot = ERC1967Utils.IMPLEMENTATION_SLOT; + bytes32 topic1 = IERC1967.Upgraded.selector; + assembly ("memory-safe") { + // Set code in memory + let ptr := mload(0x40) + mstore(add(ptr, 0x78), 0x545af43d5f5f3e6036573d5ffd5b3d5ff3) + mstore(add(ptr, 0x67), implementationSlot) + mstore(add(ptr, 0x47), 0x5f5fa260095155f3365f5f375f5f365f7f) + mstore(add(ptr, 0x36), topic1) + mstore(add(ptr, 0x16), 0x807f) + mstore(add(ptr, 0x14), implementation) + mstore(ptr, 0x603a5f8160475f3973) + + // Call create2 + instance := create2(value, add(ptr, 0x17), 0x81, salt) + } + require(instance != address(0), Errors.FailedDeployment()); + } + + /// @dev Computes the address of a clone deployed using {ERC1967Clones-cloneDeterministic}. + function predictDeterministicAddress(address implementation, bytes32 salt) internal view returns (address) { + return predictDeterministicAddress(implementation, salt, address(this)); + } + + /// @dev Computes the address of a clone deployed using {ERC1967Clones-cloneDeterministic}. + function predictDeterministicAddress( + address implementation, + bytes32 salt, + address deployer + ) internal pure returns (address) { + return Create2.computeAddress(salt, _getCloneHash(implementation), deployer); + } + + function _getCloneHash(address implementation) private pure returns (bytes32 bytecodeHash) { + bytes32 implementationSlot = ERC1967Utils.IMPLEMENTATION_SLOT; + bytes32 topic1 = IERC1967.Upgraded.selector; + assembly ("memory-safe") { + // Set code in memory + let ptr := mload(0x40) + mstore(add(ptr, 0x78), 0x545af43d5f5f3e6036573d5ffd5b3d5ff3) + mstore(add(ptr, 0x67), implementationSlot) + mstore(add(ptr, 0x47), 0x5f5fa260095155f3365f5f375f5f365f7f) + mstore(add(ptr, 0x36), topic1) + mstore(add(ptr, 0x16), 0x807f) + mstore(add(ptr, 0x14), implementation) + mstore(ptr, 0x603a5f8160475f3973) + + // Compute hash + bytecodeHash := keccak256(add(ptr, 0x17), 0x81) + } + } +} diff --git a/dependencies/@openzeppelin-contracts-5.5.0/proxy/ERC1967/ERC1967Proxy.sol b/dependencies/@openzeppelin-contracts-5.7.0/proxy/ERC1967/ERC1967Proxy.sol similarity index 54% rename from dependencies/@openzeppelin-contracts-5.5.0/proxy/ERC1967/ERC1967Proxy.sol rename to dependencies/@openzeppelin-contracts-5.7.0/proxy/ERC1967/ERC1967Proxy.sol index eb482f6..284c921 100644 --- a/dependencies/@openzeppelin-contracts-5.5.0/proxy/ERC1967/ERC1967Proxy.sol +++ b/dependencies/@openzeppelin-contracts-5.7.0/proxy/ERC1967/ERC1967Proxy.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -// OpenZeppelin Contracts (last updated v5.2.0) (proxy/ERC1967/ERC1967Proxy.sol) +// OpenZeppelin Contracts (last updated v5.6.0) (proxy/ERC1967/ERC1967Proxy.sol) pragma solidity ^0.8.22; @@ -13,17 +13,28 @@ import {ERC1967Utils} from "./ERC1967Utils.sol"; * implementation behind the proxy. */ contract ERC1967Proxy is Proxy { + /** + * @dev The proxy is left uninitialized. + */ + error ERC1967ProxyUninitialized(); + /** * @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. + * Provided `_data` is passed 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. By default construction + * will fail if `_data` is empty. This behavior can be overridden using a custom {_unsafeAllowUninitialized} that + * returns true. In that case, empty `_data` is ignored and no delegate call to the implementation is performed + * during construction. * * Requirements: * * - If `data` is empty, `msg.value` must be zero. */ constructor(address implementation, bytes memory _data) payable { + if (!_unsafeAllowUninitialized() && _data.length == 0) { + revert ERC1967ProxyUninitialized(); + } ERC1967Utils.upgradeToAndCall(implementation, _data); } @@ -37,4 +48,15 @@ contract ERC1967Proxy is Proxy { function _implementation() internal view virtual override returns (address) { return ERC1967Utils.getImplementation(); } + + /** + * @dev Returns whether the proxy can be left uninitialized. + * + * NOTE: Override this function to allow the proxy to be left uninitialized. + * Consider uninitialized proxies might be susceptible to man-in-the-middle threats + * where the proxy is replaced with a malicious one. + */ + function _unsafeAllowUninitialized() internal pure virtual returns (bool) { + return false; + } } diff --git a/dependencies/@openzeppelin-contracts-5.5.0/proxy/ERC1967/ERC1967Utils.sol b/dependencies/@openzeppelin-contracts-5.7.0/proxy/ERC1967/ERC1967Utils.sol similarity index 97% rename from dependencies/@openzeppelin-contracts-5.5.0/proxy/ERC1967/ERC1967Utils.sol rename to dependencies/@openzeppelin-contracts-5.7.0/proxy/ERC1967/ERC1967Utils.sol index ffa77cc..6059361 100644 --- a/dependencies/@openzeppelin-contracts-5.5.0/proxy/ERC1967/ERC1967Utils.sol +++ b/dependencies/@openzeppelin-contracts-5.7.0/proxy/ERC1967/ERC1967Utils.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -// OpenZeppelin Contracts (last updated v5.4.0) (proxy/ERC1967/ERC1967Utils.sol) +// OpenZeppelin Contracts (last updated v5.6.0) (proxy/ERC1967/ERC1967Utils.sol) pragma solidity ^0.8.21; @@ -86,7 +86,7 @@ library ERC1967Utils { * @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. + * the https://ethereum.org/developers/docs/apis/json-rpc/#eth_getstorageat[`eth_getStorageAt`] RPC call. * `0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103` */ function getAdmin() internal view returns (address) { diff --git a/dependencies/@openzeppelin-contracts-5.5.0/proxy/Proxy.sol b/dependencies/@openzeppelin-contracts-5.7.0/proxy/Proxy.sol similarity index 100% rename from dependencies/@openzeppelin-contracts-5.5.0/proxy/Proxy.sol rename to dependencies/@openzeppelin-contracts-5.7.0/proxy/Proxy.sol diff --git a/dependencies/@openzeppelin-contracts-5.5.0/proxy/beacon/BeaconProxy.sol b/dependencies/@openzeppelin-contracts-5.7.0/proxy/beacon/BeaconProxy.sol similarity index 100% rename from dependencies/@openzeppelin-contracts-5.5.0/proxy/beacon/BeaconProxy.sol rename to dependencies/@openzeppelin-contracts-5.7.0/proxy/beacon/BeaconProxy.sol diff --git a/dependencies/@openzeppelin-contracts-5.5.0/proxy/beacon/IBeacon.sol b/dependencies/@openzeppelin-contracts-5.7.0/proxy/beacon/IBeacon.sol similarity index 100% rename from dependencies/@openzeppelin-contracts-5.5.0/proxy/beacon/IBeacon.sol rename to dependencies/@openzeppelin-contracts-5.7.0/proxy/beacon/IBeacon.sol diff --git a/dependencies/@openzeppelin-contracts-5.5.0/proxy/beacon/UpgradeableBeacon.sol b/dependencies/@openzeppelin-contracts-5.7.0/proxy/beacon/UpgradeableBeacon.sol similarity index 100% rename from dependencies/@openzeppelin-contracts-5.5.0/proxy/beacon/UpgradeableBeacon.sol rename to dependencies/@openzeppelin-contracts-5.7.0/proxy/beacon/UpgradeableBeacon.sol diff --git a/dependencies/@openzeppelin-contracts-5.5.0/proxy/transparent/ProxyAdmin.sol b/dependencies/@openzeppelin-contracts-5.7.0/proxy/transparent/ProxyAdmin.sol similarity index 100% rename from dependencies/@openzeppelin-contracts-5.5.0/proxy/transparent/ProxyAdmin.sol rename to dependencies/@openzeppelin-contracts-5.7.0/proxy/transparent/ProxyAdmin.sol diff --git a/dependencies/@openzeppelin-contracts-5.5.0/proxy/transparent/TransparentUpgradeableProxy.sol b/dependencies/@openzeppelin-contracts-5.7.0/proxy/transparent/TransparentUpgradeableProxy.sol similarity index 100% rename from dependencies/@openzeppelin-contracts-5.5.0/proxy/transparent/TransparentUpgradeableProxy.sol rename to dependencies/@openzeppelin-contracts-5.7.0/proxy/transparent/TransparentUpgradeableProxy.sol diff --git a/dependencies/@openzeppelin-contracts-5.5.0/proxy/utils/Initializable.sol b/dependencies/@openzeppelin-contracts-5.7.0/proxy/utils/Initializable.sol similarity index 100% rename from dependencies/@openzeppelin-contracts-5.5.0/proxy/utils/Initializable.sol rename to dependencies/@openzeppelin-contracts-5.7.0/proxy/utils/Initializable.sol diff --git a/dependencies/@openzeppelin-contracts-5.5.0/proxy/utils/UUPSUpgradeable.sol b/dependencies/@openzeppelin-contracts-5.7.0/proxy/utils/UUPSUpgradeable.sol similarity index 100% rename from dependencies/@openzeppelin-contracts-5.5.0/proxy/utils/UUPSUpgradeable.sol rename to dependencies/@openzeppelin-contracts-5.7.0/proxy/utils/UUPSUpgradeable.sol diff --git a/dependencies/@openzeppelin-contracts-5.5.0/token/ERC1155/ERC1155.sol b/dependencies/@openzeppelin-contracts-5.7.0/token/ERC1155/ERC1155.sol similarity index 87% rename from dependencies/@openzeppelin-contracts-5.5.0/token/ERC1155/ERC1155.sol rename to dependencies/@openzeppelin-contracts-5.7.0/token/ERC1155/ERC1155.sol index 1af455c..79a31cb 100644 --- a/dependencies/@openzeppelin-contracts-5.5.0/token/ERC1155/ERC1155.sol +++ b/dependencies/@openzeppelin-contracts-5.7.0/token/ERC1155/ERC1155.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -// OpenZeppelin Contracts (last updated v5.5.0) (token/ERC1155/ERC1155.sol) +// OpenZeppelin Contracts (last updated v5.6.0) (token/ERC1155/ERC1155.sol) pragma solidity ^0.8.24; @@ -97,10 +97,7 @@ abstract contract ERC1155 is Context, ERC165, IERC1155, IERC1155MetadataURI, IER /// @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); - } + _checkAuthorized(_msgSender(), from); _safeTransferFrom(from, to, id, value, data); } @@ -112,13 +109,17 @@ abstract contract ERC1155 is Context, ERC165, IERC1155, IERC1155MetadataURI, IER uint256[] memory values, bytes memory data ) public virtual { - address sender = _msgSender(); - if (from != sender && !isApprovedForAll(from, sender)) { - revert ERC1155MissingApprovalForAll(sender, from); - } + _checkAuthorized(_msgSender(), from); _safeBatchTransferFrom(from, to, ids, values, data); } + /// @dev Checks if `operator` is authorized to transfer tokens owned by `owner`. Reverts with {ERC1155MissingApprovalForAll} if not. + function _checkAuthorized(address operator, address owner) internal view virtual { + if (owner != operator && !isApprovedForAll(owner, operator)) { + revert ERC1155MissingApprovalForAll(operator, owner); + } + } + /** * @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. @@ -177,6 +178,9 @@ abstract contract ERC1155 is Context, ERC165, IERC1155, IERC1155MetadataURI, IER * 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. + * + * NOTE: This version is kept for backward compatibility. We recommend calling the alternative version with a boolean + * flag in order to achieve better control over which hook to call. */ function _updateWithAcceptanceCheck( address from, @@ -184,16 +188,36 @@ abstract contract ERC1155 is Context, ERC165, IERC1155, IERC1155MetadataURI, IER uint256[] memory ids, uint256[] memory values, bytes memory data + ) internal virtual { + _updateWithAcceptanceCheck(from, to, ids, values, data, ids.length != 1); + } + + /** + * @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, + bool batch ) internal virtual { _update(from, to, ids, values); if (to != address(0)) { address operator = _msgSender(); - if (ids.length == 1) { + if (batch) { + ERC1155Utils.checkOnERC1155BatchReceived(operator, from, to, ids, values, data); + } else { 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); } } } @@ -218,7 +242,7 @@ abstract contract ERC1155 is Context, ERC165, IERC1155, IERC1155MetadataURI, IER revert ERC1155InvalidSender(address(0)); } (uint256[] memory ids, uint256[] memory values) = _asSingletonArrays(id, value); - _updateWithAcceptanceCheck(from, to, ids, values, data); + _updateWithAcceptanceCheck(from, to, ids, values, data, false); } /** @@ -245,7 +269,7 @@ abstract contract ERC1155 is Context, ERC165, IERC1155, IERC1155MetadataURI, IER if (from == address(0)) { revert ERC1155InvalidSender(address(0)); } - _updateWithAcceptanceCheck(from, to, ids, values, data); + _updateWithAcceptanceCheck(from, to, ids, values, data, true); } /** @@ -287,7 +311,7 @@ abstract contract ERC1155 is Context, ERC165, IERC1155, IERC1155MetadataURI, IER revert ERC1155InvalidReceiver(address(0)); } (uint256[] memory ids, uint256[] memory values) = _asSingletonArrays(id, value); - _updateWithAcceptanceCheck(address(0), to, ids, values, data); + _updateWithAcceptanceCheck(address(0), to, ids, values, data, false); } /** @@ -306,7 +330,7 @@ abstract contract ERC1155 is Context, ERC165, IERC1155, IERC1155MetadataURI, IER if (to == address(0)) { revert ERC1155InvalidReceiver(address(0)); } - _updateWithAcceptanceCheck(address(0), to, ids, values, data); + _updateWithAcceptanceCheck(address(0), to, ids, values, data, true); } /** @@ -324,7 +348,7 @@ abstract contract ERC1155 is Context, ERC165, IERC1155, IERC1155MetadataURI, IER revert ERC1155InvalidSender(address(0)); } (uint256[] memory ids, uint256[] memory values) = _asSingletonArrays(id, value); - _updateWithAcceptanceCheck(from, address(0), ids, values, ""); + _updateWithAcceptanceCheck(from, address(0), ids, values, "", false); } /** @@ -342,7 +366,7 @@ abstract contract ERC1155 is Context, ERC165, IERC1155, IERC1155MetadataURI, IER if (from == address(0)) { revert ERC1155InvalidSender(address(0)); } - _updateWithAcceptanceCheck(from, address(0), ids, values, ""); + _updateWithAcceptanceCheck(from, address(0), ids, values, "", true); } /** @@ -352,9 +376,13 @@ abstract contract ERC1155 is Context, ERC165, IERC1155, IERC1155MetadataURI, IER * * Requirements: * + * - `owner` cannot be the zero address. * - `operator` cannot be the zero address. */ function _setApprovalForAll(address owner, address operator, bool approved) internal virtual { + if (owner == address(0)) { + revert ERC1155InvalidApprover(address(0)); + } if (operator == address(0)) { revert ERC1155InvalidOperator(address(0)); } diff --git a/dependencies/@openzeppelin-contracts-5.5.0/token/ERC1155/IERC1155.sol b/dependencies/@openzeppelin-contracts-5.7.0/token/ERC1155/IERC1155.sol similarity index 100% rename from dependencies/@openzeppelin-contracts-5.5.0/token/ERC1155/IERC1155.sol rename to dependencies/@openzeppelin-contracts-5.7.0/token/ERC1155/IERC1155.sol diff --git a/dependencies/@openzeppelin-contracts-5.5.0/token/ERC1155/IERC1155Receiver.sol b/dependencies/@openzeppelin-contracts-5.7.0/token/ERC1155/IERC1155Receiver.sol similarity index 100% rename from dependencies/@openzeppelin-contracts-5.5.0/token/ERC1155/IERC1155Receiver.sol rename to dependencies/@openzeppelin-contracts-5.7.0/token/ERC1155/IERC1155Receiver.sol diff --git a/dependencies/@openzeppelin-contracts-5.5.0/token/ERC1155/extensions/ERC1155Burnable.sol b/dependencies/@openzeppelin-contracts-5.7.0/token/ERC1155/extensions/ERC1155Burnable.sol similarity index 60% rename from dependencies/@openzeppelin-contracts-5.5.0/token/ERC1155/extensions/ERC1155Burnable.sol rename to dependencies/@openzeppelin-contracts-5.7.0/token/ERC1155/extensions/ERC1155Burnable.sol index 41d36bd..487dbeb 100644 --- a/dependencies/@openzeppelin-contracts-5.5.0/token/ERC1155/extensions/ERC1155Burnable.sol +++ b/dependencies/@openzeppelin-contracts-5.7.0/token/ERC1155/extensions/ERC1155Burnable.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -// OpenZeppelin Contracts (last updated v5.5.0) (token/ERC1155/extensions/ERC1155Burnable.sol) +// OpenZeppelin Contracts (last updated v5.7.0) (token/ERC1155/extensions/ERC1155Burnable.sol) pragma solidity ^0.8.24; @@ -11,18 +11,12 @@ import {ERC1155} from "../ERC1155.sol"; */ 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); - } - + _checkAuthorized(_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); - } - + _checkAuthorized(_msgSender(), account); _burnBatch(account, ids, values); } } diff --git a/dependencies/@openzeppelin-contracts-5.7.0/token/ERC1155/extensions/ERC1155Crosschain.sol b/dependencies/@openzeppelin-contracts-5.7.0/token/ERC1155/extensions/ERC1155Crosschain.sol new file mode 100644 index 0000000..213db7d --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.7.0/token/ERC1155/extensions/ERC1155Crosschain.sol @@ -0,0 +1,87 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v5.7.0) (token/ERC1155/extensions/ERC1155Crosschain.sol) + +pragma solidity ^0.8.26; + +import {ERC1155} from "../ERC1155.sol"; +import {BridgeMultiToken} from "../../../crosschain/bridges/abstract/BridgeMultiToken.sol"; + +/** + * @dev Extension of {ERC1155} that makes it natively cross-chain using the ERC-7786 based {BridgeMultiToken}. + * + * This extension makes the token compatible with: + * * {ERC1155Crosschain} instances on other chains, + * * {ERC1155} instances on other chains that are bridged using {BridgeERC1155}, + */ +// slither-disable-next-line locked-ether +abstract contract ERC1155Crosschain is BridgeMultiToken, ERC1155 { + /// @dev Equivalent to `crosschainTransferFrom(from, to, id, value, "")`. + function crosschainTransferFrom( + address from, + bytes memory to, + uint256 id, + uint256 value + ) public virtual returns (bytes32) { + return crosschainTransferFrom(from, to, id, value, ""); + } + + /** + * @dev TransferFrom variant of {crosschainTransferFrom}, using ERC1155 allowance from the sender to the caller. + * `data` is forwarded to the destination-chain ERC-1155 receiver's acceptance hook. + */ + function crosschainTransferFrom( + address from, + bytes memory to, + uint256 id, + uint256 value, + bytes memory data + ) public virtual returns (bytes32) { + _checkAuthorized(_msgSender(), from); + + uint256[] memory ids = new uint256[](1); + uint256[] memory values = new uint256[](1); + ids[0] = id; + values[0] = value; + return _crosschainTransfer(from, to, ids, values, data); + } + + /// @dev Equivalent to `crosschainTransferFrom(from, to, ids, values, "")`. + function crosschainTransferFrom( + address from, + bytes memory to, + uint256[] memory ids, + uint256[] memory values + ) public virtual returns (bytes32) { + return crosschainTransferFrom(from, to, ids, values, ""); + } + + /** + * @dev TransferFrom variant of {crosschainTransferFrom}, using ERC1155 allowance from the sender to the caller. + * `data` is forwarded to the destination-chain ERC-1155 receiver's acceptance hook. + */ + function crosschainTransferFrom( + address from, + bytes memory to, + uint256[] memory ids, + uint256[] memory values, + bytes memory data + ) public virtual returns (bytes32) { + _checkAuthorized(_msgSender(), from); + return _crosschainTransfer(from, to, ids, values, data); + } + + /// @dev "Locking" tokens is achieved through burning. + function _onSend(address from, uint256[] memory ids, uint256[] memory values) internal virtual override { + _burnBatch(from, ids, values); + } + + /// @dev "Unlocking" tokens is achieved through minting. + function _onReceive( + address to, + uint256[] memory ids, + uint256[] memory values, + bytes memory data + ) internal virtual override { + _mintBatch(to, ids, values, data); + } +} diff --git a/dependencies/@openzeppelin-contracts-5.5.0/token/ERC1155/extensions/ERC1155Pausable.sol b/dependencies/@openzeppelin-contracts-5.7.0/token/ERC1155/extensions/ERC1155Pausable.sol similarity index 100% rename from dependencies/@openzeppelin-contracts-5.5.0/token/ERC1155/extensions/ERC1155Pausable.sol rename to dependencies/@openzeppelin-contracts-5.7.0/token/ERC1155/extensions/ERC1155Pausable.sol diff --git a/dependencies/@openzeppelin-contracts-5.5.0/token/ERC1155/extensions/ERC1155Supply.sol b/dependencies/@openzeppelin-contracts-5.7.0/token/ERC1155/extensions/ERC1155Supply.sol similarity index 87% rename from dependencies/@openzeppelin-contracts-5.5.0/token/ERC1155/extensions/ERC1155Supply.sol rename to dependencies/@openzeppelin-contracts-5.7.0/token/ERC1155/extensions/ERC1155Supply.sol index 54a7fe3..623b14f 100644 --- a/dependencies/@openzeppelin-contracts-5.5.0/token/ERC1155/extensions/ERC1155Supply.sol +++ b/dependencies/@openzeppelin-contracts-5.7.0/token/ERC1155/extensions/ERC1155Supply.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -// OpenZeppelin Contracts (last updated v5.5.0) (token/ERC1155/extensions/ERC1155Supply.sol) +// OpenZeppelin Contracts (last updated v5.6.0) (token/ERC1155/extensions/ERC1155Supply.sol) pragma solidity ^0.8.24; @@ -10,9 +10,9 @@ 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. + * clearly identified. Note: While a `totalSupply` of 1 may mean the + * corresponding token is an NFT, there are no inherent guarantees that + * no more tokens with the same id will be minted in future. * * NOTE: This contract implies a global limit of 2**256 - 1 to the number of tokens * that can be minted. @@ -26,7 +26,7 @@ abstract contract ERC1155Supply is ERC1155 { uint256 private _totalSupplyAll; /** - * @dev Total value of tokens in with a given id. + * @dev Total value of tokens with a given id. */ function totalSupply(uint256 id) public view virtual returns (uint256) { return _totalSupply[id]; @@ -40,7 +40,7 @@ abstract contract ERC1155Supply is ERC1155 { } /** - * @dev Indicates whether any token exist with a given id, or not. + * @dev Indicates whether any tokens exist with a given id, or not. */ function exists(uint256 id) public view virtual returns (bool) { return totalSupply(id) > 0; diff --git a/dependencies/@openzeppelin-contracts-5.5.0/token/ERC1155/extensions/ERC1155URIStorage.sol b/dependencies/@openzeppelin-contracts-5.7.0/token/ERC1155/extensions/ERC1155URIStorage.sol similarity index 92% rename from dependencies/@openzeppelin-contracts-5.5.0/token/ERC1155/extensions/ERC1155URIStorage.sol rename to dependencies/@openzeppelin-contracts-5.7.0/token/ERC1155/extensions/ERC1155URIStorage.sol index 9973b55..ca1978a 100644 --- a/dependencies/@openzeppelin-contracts-5.5.0/token/ERC1155/extensions/ERC1155URIStorage.sol +++ b/dependencies/@openzeppelin-contracts-5.7.0/token/ERC1155/extensions/ERC1155URIStorage.sol @@ -1,9 +1,8 @@ // SPDX-License-Identifier: MIT -// OpenZeppelin Contracts (last updated v5.5.0) (token/ERC1155/extensions/ERC1155URIStorage.sol) +// OpenZeppelin Contracts (last updated v5.6.0) (token/ERC1155/extensions/ERC1155URIStorage.sol) pragma solidity ^0.8.24; -import {Strings} from "../../../utils/Strings.sol"; import {ERC1155} from "../ERC1155.sol"; /** @@ -11,8 +10,6 @@ import {ERC1155} from "../ERC1155.sol"; * Inspired by the {ERC721URIStorage} extension */ abstract contract ERC1155URIStorage is ERC1155 { - using Strings for uint256; - // Optional base URI string private _baseURI = ""; diff --git a/dependencies/@openzeppelin-contracts-5.5.0/token/ERC1155/extensions/IERC1155MetadataURI.sol b/dependencies/@openzeppelin-contracts-5.7.0/token/ERC1155/extensions/IERC1155MetadataURI.sol similarity index 100% rename from dependencies/@openzeppelin-contracts-5.5.0/token/ERC1155/extensions/IERC1155MetadataURI.sol rename to dependencies/@openzeppelin-contracts-5.7.0/token/ERC1155/extensions/IERC1155MetadataURI.sol diff --git a/dependencies/@openzeppelin-contracts-5.5.0/token/ERC1155/utils/ERC1155Holder.sol b/dependencies/@openzeppelin-contracts-5.7.0/token/ERC1155/utils/ERC1155Holder.sol similarity index 100% rename from dependencies/@openzeppelin-contracts-5.5.0/token/ERC1155/utils/ERC1155Holder.sol rename to dependencies/@openzeppelin-contracts-5.7.0/token/ERC1155/utils/ERC1155Holder.sol diff --git a/dependencies/@openzeppelin-contracts-5.5.0/token/ERC1155/utils/ERC1155Utils.sol b/dependencies/@openzeppelin-contracts-5.7.0/token/ERC1155/utils/ERC1155Utils.sol similarity index 96% rename from dependencies/@openzeppelin-contracts-5.5.0/token/ERC1155/utils/ERC1155Utils.sol rename to dependencies/@openzeppelin-contracts-5.7.0/token/ERC1155/utils/ERC1155Utils.sol index 03cb0f0..4ffdcc2 100644 --- a/dependencies/@openzeppelin-contracts-5.5.0/token/ERC1155/utils/ERC1155Utils.sol +++ b/dependencies/@openzeppelin-contracts-5.7.0/token/ERC1155/utils/ERC1155Utils.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -// OpenZeppelin Contracts (last updated v5.4.0) (token/ERC1155/utils/ERC1155Utils.sol) +// OpenZeppelin Contracts (last updated v5.7.0) (token/ERC1155/utils/ERC1155Utils.sol) pragma solidity ^0.8.20; @@ -54,7 +54,7 @@ library ERC1155Utils { * 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 + * Otherwise, the recipient must implement {IERC1155Receiver-onERC1155BatchReceived} and return the acceptance magic value to accept * the transfer. */ function checkOnERC1155BatchReceived( diff --git a/dependencies/@openzeppelin-contracts-5.5.0/token/ERC20/ERC20.sol b/dependencies/@openzeppelin-contracts-5.7.0/token/ERC20/ERC20.sol similarity index 100% rename from dependencies/@openzeppelin-contracts-5.5.0/token/ERC20/ERC20.sol rename to dependencies/@openzeppelin-contracts-5.7.0/token/ERC20/ERC20.sol diff --git a/dependencies/@openzeppelin-contracts-5.5.0/token/ERC20/IERC20.sol b/dependencies/@openzeppelin-contracts-5.7.0/token/ERC20/IERC20.sol similarity index 100% rename from dependencies/@openzeppelin-contracts-5.5.0/token/ERC20/IERC20.sol rename to dependencies/@openzeppelin-contracts-5.7.0/token/ERC20/IERC20.sol diff --git a/dependencies/@openzeppelin-contracts-5.5.0/token/ERC20/extensions/ERC1363.sol b/dependencies/@openzeppelin-contracts-5.7.0/token/ERC20/extensions/ERC1363.sol similarity index 100% rename from dependencies/@openzeppelin-contracts-5.5.0/token/ERC20/extensions/ERC1363.sol rename to dependencies/@openzeppelin-contracts-5.7.0/token/ERC20/extensions/ERC1363.sol diff --git a/dependencies/@openzeppelin-contracts-5.5.0/token/ERC20/extensions/ERC20Burnable.sol b/dependencies/@openzeppelin-contracts-5.7.0/token/ERC20/extensions/ERC20Burnable.sol similarity index 79% rename from dependencies/@openzeppelin-contracts-5.5.0/token/ERC20/extensions/ERC20Burnable.sol rename to dependencies/@openzeppelin-contracts-5.7.0/token/ERC20/extensions/ERC20Burnable.sol index 4d482d8..be5dd35 100644 --- a/dependencies/@openzeppelin-contracts-5.5.0/token/ERC20/extensions/ERC20Burnable.sol +++ b/dependencies/@openzeppelin-contracts-5.7.0/token/ERC20/extensions/ERC20Burnable.sol @@ -1,17 +1,16 @@ // SPDX-License-Identifier: MIT -// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/extensions/ERC20Burnable.sol) +// OpenZeppelin Contracts (last updated v5.7.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 { +abstract contract ERC20Burnable is ERC20 { /** * @dev Destroys a `value` amount of tokens from the caller. * @@ -29,7 +28,7 @@ abstract contract ERC20Burnable is Context, ERC20 { * * Requirements: * - * - the caller must have allowance for ``accounts``'s tokens of at least + * - the caller must have allowance for `account`'s tokens of at least * `value`. */ function burnFrom(address account, uint256 value) public virtual { diff --git a/dependencies/@openzeppelin-contracts-5.5.0/token/ERC20/extensions/ERC20Capped.sol b/dependencies/@openzeppelin-contracts-5.7.0/token/ERC20/extensions/ERC20Capped.sol similarity index 100% rename from dependencies/@openzeppelin-contracts-5.5.0/token/ERC20/extensions/ERC20Capped.sol rename to dependencies/@openzeppelin-contracts-5.7.0/token/ERC20/extensions/ERC20Capped.sol diff --git a/dependencies/@openzeppelin-contracts-5.7.0/token/ERC20/extensions/ERC20Crosschain.sol b/dependencies/@openzeppelin-contracts-5.7.0/token/ERC20/extensions/ERC20Crosschain.sol new file mode 100644 index 0000000..aeada86 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.7.0/token/ERC20/extensions/ERC20Crosschain.sol @@ -0,0 +1,39 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v5.6.0) (token/ERC20/extensions/ERC20Crosschain.sol) + +pragma solidity ^0.8.26; + +import {ERC20} from "../ERC20.sol"; +import {BridgeFungible} from "../../../crosschain/bridges/abstract/BridgeFungible.sol"; + +/** + * @dev Extension of {ERC20} that makes it natively cross-chain using the ERC-7786 based {BridgeFungible}. + * + * This extension makes the token compatible with counterparts on other chains, which can be: + * * {ERC20Crosschain} instances, + * * {ERC20} instances that are bridged using {BridgeERC20}, + * * {ERC20Bridgeable} instances that are bridged using {BridgeERC7802}. + * + * It is mostly equivalent to inheriting from both {ERC20Bridgeable} and {BridgeERC7802}, and configuring them such + * that: + * * `token` (on the {BridgeERC7802} side) is `address(this)`, + * * `_checkTokenBridge` (on the {ERC20Bridgeable} side) is implemented such that it only accepts self-calls. + */ +// slither-disable-next-line locked-ether +abstract contract ERC20Crosschain is ERC20, BridgeFungible { + /// @dev Variant of {crosschainTransfer} that allows an authorized account (using ERC20 allowance) to operate on `from`'s assets. + function crosschainTransferFrom(address from, bytes memory to, uint256 amount) public virtual returns (bytes32) { + _spendAllowance(from, _msgSender(), amount); + return _crosschainTransfer(from, to, amount); + } + + /// @dev "Locking" tokens is achieved through burning + function _onSend(address from, uint256 amount) internal virtual override { + _burn(from, amount); + } + + /// @dev "Unlocking" tokens is achieved through minting + function _onReceive(address to, uint256 amount) internal virtual override { + _mint(to, amount); + } +} diff --git a/dependencies/@openzeppelin-contracts-5.5.0/token/ERC20/extensions/ERC20FlashMint.sol b/dependencies/@openzeppelin-contracts-5.7.0/token/ERC20/extensions/ERC20FlashMint.sol similarity index 87% rename from dependencies/@openzeppelin-contracts-5.5.0/token/ERC20/extensions/ERC20FlashMint.sol rename to dependencies/@openzeppelin-contracts-5.7.0/token/ERC20/extensions/ERC20FlashMint.sol index 4d3a31f..bc2b9ce 100644 --- a/dependencies/@openzeppelin-contracts-5.5.0/token/ERC20/extensions/ERC20FlashMint.sol +++ b/dependencies/@openzeppelin-contracts-5.7.0/token/ERC20/extensions/ERC20FlashMint.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -// OpenZeppelin Contracts (last updated v5.1.0) (token/ERC20/extensions/ERC20FlashMint.sol) +// OpenZeppelin Contracts (last updated v5.7.0) (token/ERC20/extensions/ERC20FlashMint.sol) pragma solidity ^0.8.20; @@ -38,12 +38,13 @@ abstract contract ERC20FlashMint is ERC20, IERC3156FlashLender { /** * @dev Returns the maximum amount of tokens available for loan. + * + * NOTE: This function will not automatically detect any supply cap + * added by other extensions, such as {ERC20Capped}. If necessary, + * override this function to take a supply cap into account. + * * @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; @@ -66,23 +67,18 @@ abstract contract ERC20FlashMint is ERC20, IERC3156FlashLender { /** * @dev Returns the fee applied when doing flash loans. By default this - * implementation has 0 fees. This function can be overloaded to make + * implementation has 0 fees. This function can be overridden 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; + function _flashFee(address /*token*/, uint256 /*value*/) internal view virtual returns (uint256) { 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. + * This function can be overridden to change the fee receiver. * @return The address for which the flash fee will be sent to. */ function _flashFeeReceiver() internal view virtual returns (address) { diff --git a/dependencies/@openzeppelin-contracts-5.5.0/token/ERC20/extensions/ERC20Pausable.sol b/dependencies/@openzeppelin-contracts-5.7.0/token/ERC20/extensions/ERC20Pausable.sol similarity index 100% rename from dependencies/@openzeppelin-contracts-5.5.0/token/ERC20/extensions/ERC20Pausable.sol rename to dependencies/@openzeppelin-contracts-5.7.0/token/ERC20/extensions/ERC20Pausable.sol diff --git a/dependencies/@openzeppelin-contracts-5.5.0/token/ERC20/extensions/ERC20Permit.sol b/dependencies/@openzeppelin-contracts-5.7.0/token/ERC20/extensions/ERC20Permit.sol similarity index 100% rename from dependencies/@openzeppelin-contracts-5.5.0/token/ERC20/extensions/ERC20Permit.sol rename to dependencies/@openzeppelin-contracts-5.7.0/token/ERC20/extensions/ERC20Permit.sol diff --git a/dependencies/@openzeppelin-contracts-5.7.0/token/ERC20/extensions/ERC20TransferAuthorization.sol b/dependencies/@openzeppelin-contracts-5.7.0/token/ERC20/extensions/ERC20TransferAuthorization.sol new file mode 100644 index 0000000..6e65f15 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.7.0/token/ERC20/extensions/ERC20TransferAuthorization.sol @@ -0,0 +1,91 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v5.7.0) (token/ERC20/extensions/ERC20TransferAuthorization.sol) +pragma solidity ^0.8.26; + +import {ERC3009} from "./draft-ERC3009.sol"; +import {SignatureChecker} from "../../../utils/cryptography/SignatureChecker.sol"; +import {NoncesKeyed} from "../../../utils/NoncesKeyed.sol"; + +/** + * @dev Variant of {ERC-3009} that uses keyed sequential nonces as defined in {NoncesKeyed}. + * + * NOTE: This extension uses keyed sequential nonces following the + * https://eips.ethereum.org/EIPS/eip-4337#semi-abstracted-nonce-support[ERC-4337 semi-abstracted nonce system]. + * The {bytes32} nonce field is interpreted as a 192-bit key packed with a 64-bit sequence. Nonces with + * different keys are independent and can be submitted in parallel without ordering constraints, while nonces + * sharing the same key must be used sequentially. This is unlike {ERC20Permit} which uses a single global + * sequential nonce. + */ +abstract contract ERC20TransferAuthorization is ERC3009, NoncesKeyed { + /** + * @dev See {IERC3009-authorizationState}. + * + * NOTE: Returning `false` does not guarantee that the authorization is currently executable. + * With keyed sequential nonces, a nonce may be blocked by a predecessor in the same key's sequence + * that has not yet been consumed. + */ + function authorizationState(address authorizer, bytes32 nonce) public view virtual override returns (bool) { + // Truncating `nonces()` to uint64 is safe: reaching 2^64 sequential uses for a single key is infeasible. + return uint64(nonces(authorizer, uint192(uint256(nonce) >> 64))) > uint64(uint256(nonce)); + } + + /// @dev Same as {transferWithAuthorization} but with a bytes signature. + function transferWithAuthorization( + address from, + address to, + uint256 value, + uint256 validAfter, + uint256 validBefore, + bytes32 nonce, + bytes memory signature + ) public virtual { + bytes32 hash = _hashTypedDataV4( + keccak256(abi.encode(TRANSFER_WITH_AUTHORIZATION_TYPEHASH, from, to, value, validAfter, validBefore, nonce)) + ); + require(SignatureChecker.isValidSignatureNow(from, hash, signature), ERC3009InvalidSignature()); + _transferWithAuthorization(from, to, value, validAfter, validBefore, nonce); + } + + /// @dev Same as {receiveWithAuthorization} but with a bytes signature. + function receiveWithAuthorization( + address from, + address to, + uint256 value, + uint256 validAfter, + uint256 validBefore, + bytes32 nonce, + bytes memory signature + ) public virtual { + bytes32 hash = _hashTypedDataV4( + keccak256(abi.encode(RECEIVE_WITH_AUTHORIZATION_TYPEHASH, from, to, value, validAfter, validBefore, nonce)) + ); + require(SignatureChecker.isValidSignatureNow(from, hash, signature), ERC3009InvalidSignature()); + require(to == _msgSender(), ERC20InvalidReceiver(to)); + _transferWithAuthorization(from, to, value, validAfter, validBefore, nonce); + } + + /** + * @dev Same as {cancelAuthorization} but with a bytes signature. + * + * NOTE: Due to the keyed sequential nonce model, only the next nonce in a given key's sequence + * can be cancelled. It is not possible to directly cancel a future nonce whose predecessors in the + * same key have not yet been consumed or cancelled. To invalidate a future authorization, all + * preceding nonces in the same key must first be consumed or cancelled in order. + */ + function cancelAuthorization(address authorizer, bytes32 nonce, bytes memory signature) public virtual { + bytes32 hash = _hashTypedDataV4(keccak256(abi.encode(CANCEL_AUTHORIZATION_TYPEHASH, authorizer, nonce))); + require(SignatureChecker.isValidSignatureNow(authorizer, hash, signature), ERC3009InvalidSignature()); + _cancelAuthorization(authorizer, nonce); + } + + /** + * @dev Override the internal nonce consumption logic to use the keyed sequential nonces from {NoncesKeyed}. + * + * NOTE: This override does not call `super._consumeNonce`, so any sibling override added by another extension + * is skipped under C3 linearization. Integrators combining this contract with extensions that introduce + * additional side effects through `_consumeNonce` must reintroduce those side effects themselves. + */ + function _consumeNonce(address authorizer, bytes32 nonce) internal virtual override { + _useCheckedNonce(authorizer, uint256(nonce)); + } +} diff --git a/dependencies/@openzeppelin-contracts-5.5.0/token/ERC20/extensions/ERC20Votes.sol b/dependencies/@openzeppelin-contracts-5.7.0/token/ERC20/extensions/ERC20Votes.sol similarity index 100% rename from dependencies/@openzeppelin-contracts-5.5.0/token/ERC20/extensions/ERC20Votes.sol rename to dependencies/@openzeppelin-contracts-5.7.0/token/ERC20/extensions/ERC20Votes.sol diff --git a/dependencies/@openzeppelin-contracts-5.5.0/token/ERC20/extensions/ERC20Wrapper.sol b/dependencies/@openzeppelin-contracts-5.7.0/token/ERC20/extensions/ERC20Wrapper.sol similarity index 79% rename from dependencies/@openzeppelin-contracts-5.5.0/token/ERC20/extensions/ERC20Wrapper.sol rename to dependencies/@openzeppelin-contracts-5.7.0/token/ERC20/extensions/ERC20Wrapper.sol index 8916d1a..670c0cd 100644 --- a/dependencies/@openzeppelin-contracts-5.5.0/token/ERC20/extensions/ERC20Wrapper.sol +++ b/dependencies/@openzeppelin-contracts-5.7.0/token/ERC20/extensions/ERC20Wrapper.sol @@ -1,10 +1,11 @@ // SPDX-License-Identifier: MIT -// OpenZeppelin Contracts (last updated v5.4.0) (token/ERC20/extensions/ERC20Wrapper.sol) +// OpenZeppelin Contracts (last updated v5.7.0) (token/ERC20/extensions/ERC20Wrapper.sol) pragma solidity ^0.8.20; -import {IERC20, IERC20Metadata, ERC20} from "../ERC20.sol"; +import {IERC20, ERC20} from "../ERC20.sol"; import {SafeERC20} from "../utils/SafeERC20.sol"; +import {Math} from "../../../utils/math/Math.sol"; /** * @dev Extension of the ERC-20 token contract to support token wrapping. @@ -27,19 +28,22 @@ abstract contract ERC20Wrapper is ERC20 { error ERC20InvalidUnderlying(address token); constructor(IERC20 underlyingToken) { - if (underlyingToken == this) { + if (address(underlyingToken) == address(this)) { revert ERC20InvalidUnderlying(address(this)); } _underlying = underlyingToken; } - /// @inheritdoc IERC20Metadata + /** + * @dev See {IERC20Metadata}. Uses {Math-ternary} for branchless selection, which evaluates both branches. This is safe + * because the default {ERC20-decimals} is commonly a constant. + * + * NOTE: If a derived contract overrides `super.decimals()` to read from + * storage, it should also override this function and use a conditional ternary instead. + */ function decimals() public view virtual override returns (uint8) { - try IERC20Metadata(address(_underlying)).decimals() returns (uint8 value) { - return value; - } catch { - return super.decimals(); - } + (bool success, uint8 decimals_) = SafeERC20.tryGetDecimals(_underlying); + return uint8(Math.ternary(success, decimals_, super.decimals())); // Safe cast. Both are uint8. } /** diff --git a/dependencies/@openzeppelin-contracts-5.5.0/token/ERC20/extensions/ERC4626.sol b/dependencies/@openzeppelin-contracts-5.7.0/token/ERC20/extensions/ERC4626.sol similarity index 90% rename from dependencies/@openzeppelin-contracts-5.5.0/token/ERC20/extensions/ERC4626.sol rename to dependencies/@openzeppelin-contracts-5.7.0/token/ERC20/extensions/ERC4626.sol index 5054ef4..498ef28 100644 --- a/dependencies/@openzeppelin-contracts-5.5.0/token/ERC20/extensions/ERC4626.sol +++ b/dependencies/@openzeppelin-contracts-5.7.0/token/ERC20/extensions/ERC4626.sol @@ -1,13 +1,11 @@ // SPDX-License-Identifier: MIT -// OpenZeppelin Contracts (last updated v5.5.0) (token/ERC20/extensions/ERC4626.sol) +// OpenZeppelin Contracts (last updated v5.7.0) (token/ERC20/extensions/ERC4626.sol) pragma solidity ^0.8.24; import {IERC20, IERC20Metadata, ERC20} from "../ERC20.sol"; import {SafeERC20} from "../utils/SafeERC20.sol"; import {IERC4626} from "../../../interfaces/IERC4626.sol"; -import {LowLevelCall} from "../../../utils/LowLevelCall.sol"; -import {Memory} from "../../../utils/Memory.sol"; import {Math} from "../../../utils/math/Math.sol"; /** @@ -55,7 +53,7 @@ import {Math} from "../../../utils/math/Math.sol"; * functions. Overriding {_deposit} automatically affects both {deposit} and {mint}. Similarly, overriding {_withdraw} * automatically affects both {withdraw} and {redeem}. Overall it is not recommended to override the public facing * functions since that could lead to inconsistent behaviors between the {deposit} and {mint} or between {withdraw} and - * {redeem}, which is documented to have lead to loss of funds. + * {redeem}, which is documented to have led to loss of funds. * * * Overrides to the deposit or withdraw mechanism must be reflected in the preview functions as well. * @@ -66,6 +64,14 @@ import {Math} from "../../../utils/math/Math.sol"; * * If {previewRedeem} is overridden to revert, {maxWithdraw} must be overridden as necessary to ensure it * always return successfully. * ==== + * + * [CAUTION] + * ==== + * Any mechanism that mints shares without a corresponding increase in the vault's assets (collateral) will alter the + * exchange rate and may open the door to vulnerabilities. In particular, this contract + * must NOT be combined with {ERC20FlashMint}: flash-minting shares temporarily inflates the total supply without + * increasing collateral, corrupting the exchange rate applied during the flash loan. + * ==== */ abstract contract ERC4626 is ERC20, IERC4626 { using Math for uint256; @@ -84,12 +90,12 @@ abstract contract ERC4626 is ERC20, IERC4626 { error ERC4626ExceededMaxMint(address receiver, uint256 shares, uint256 max); /** - * @dev Attempted to withdraw more assets than the max amount for `receiver`. + * @dev Attempted to withdraw more assets than the max amount for `owner`. */ error ERC4626ExceededMaxWithdraw(address owner, uint256 assets, uint256 max); /** - * @dev Attempted to redeem more shares than the max amount for `receiver`. + * @dev Attempted to redeem more shares than the max amount for `owner`. */ error ERC4626ExceededMaxRedeem(address owner, uint256 shares, uint256 max); @@ -97,28 +103,11 @@ abstract contract ERC4626 is ERC20, IERC4626 { * @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_); + (bool success, uint8 assetDecimals) = SafeERC20.tryGetDecimals(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) { - Memory.Pointer ptr = Memory.getFreeMemoryPointer(); - (bool success, bytes32 returnedDecimals, ) = LowLevelCall.staticcallReturn64Bytes( - address(asset_), - abi.encodeCall(IERC20Metadata.decimals, ()) - ); - Memory.setFreeMemoryPointer(ptr); - - return - (success && LowLevelCall.returnDataSize() >= 32 && uint256(returnedDecimals) <= type(uint8).max) - ? (true, uint8(uint256(returnedDecimals))) - : (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 @@ -267,7 +256,7 @@ abstract contract ERC4626 is ERC20, IERC4626 { // 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); + _transferIn(caller, assets); _mint(receiver, shares); emit Deposit(caller, receiver, assets, shares); @@ -294,11 +283,21 @@ abstract contract ERC4626 is ERC20, IERC4626 { // 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); + _transferOut(receiver, assets); emit Withdraw(caller, receiver, owner, assets, shares); } + /// @dev Performs a transfer in of underlying assets. The default implementation uses `SafeERC20`. Used by {_deposit}. + function _transferIn(address from, uint256 assets) internal virtual { + SafeERC20.safeTransferFrom(IERC20(asset()), from, address(this), assets); + } + + /// @dev Performs a transfer out of underlying assets. The default implementation uses `SafeERC20`. Used by {_withdraw}. + function _transferOut(address to, uint256 assets) internal virtual { + SafeERC20.safeTransfer(IERC20(asset()), to, assets); + } + function _decimalsOffset() internal view virtual returns (uint8) { return 0; } diff --git a/dependencies/@openzeppelin-contracts-5.5.0/token/ERC20/extensions/IERC20Metadata.sol b/dependencies/@openzeppelin-contracts-5.7.0/token/ERC20/extensions/IERC20Metadata.sol similarity index 100% rename from dependencies/@openzeppelin-contracts-5.5.0/token/ERC20/extensions/IERC20Metadata.sol rename to dependencies/@openzeppelin-contracts-5.7.0/token/ERC20/extensions/IERC20Metadata.sol diff --git a/dependencies/@openzeppelin-contracts-5.5.0/token/ERC20/extensions/IERC20Permit.sol b/dependencies/@openzeppelin-contracts-5.7.0/token/ERC20/extensions/IERC20Permit.sol similarity index 100% rename from dependencies/@openzeppelin-contracts-5.5.0/token/ERC20/extensions/IERC20Permit.sol rename to dependencies/@openzeppelin-contracts-5.7.0/token/ERC20/extensions/IERC20Permit.sol diff --git a/dependencies/@openzeppelin-contracts-5.5.0/token/ERC20/extensions/draft-ERC20Bridgeable.sol b/dependencies/@openzeppelin-contracts-5.7.0/token/ERC20/extensions/draft-ERC20Bridgeable.sol similarity index 100% rename from dependencies/@openzeppelin-contracts-5.5.0/token/ERC20/extensions/draft-ERC20Bridgeable.sol rename to dependencies/@openzeppelin-contracts-5.7.0/token/ERC20/extensions/draft-ERC20Bridgeable.sol diff --git a/dependencies/@openzeppelin-contracts-5.5.0/token/ERC20/extensions/draft-ERC20TemporaryApproval.sol b/dependencies/@openzeppelin-contracts-5.7.0/token/ERC20/extensions/draft-ERC20TemporaryApproval.sol similarity index 100% rename from dependencies/@openzeppelin-contracts-5.5.0/token/ERC20/extensions/draft-ERC20TemporaryApproval.sol rename to dependencies/@openzeppelin-contracts-5.7.0/token/ERC20/extensions/draft-ERC20TemporaryApproval.sol diff --git a/dependencies/@openzeppelin-contracts-5.7.0/token/ERC20/extensions/draft-ERC3009.sol b/dependencies/@openzeppelin-contracts-5.7.0/token/ERC20/extensions/draft-ERC3009.sol new file mode 100644 index 0000000..8a782d6 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.7.0/token/ERC20/extensions/draft-ERC3009.sol @@ -0,0 +1,152 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v5.7.0) (token/ERC20/extensions/draft-ERC3009.sol) +pragma solidity ^0.8.26; + +import {ERC20} from "../ERC20.sol"; +import {EIP712} from "../../../utils/cryptography/EIP712.sol"; +import {ECDSA} from "../../../utils/cryptography/ECDSA.sol"; +import {IERC3009, IERC3009Cancel} from "../../../interfaces/draft-IERC3009.sol"; +import {Time} from "../../../utils/types/Time.sol"; +import {ERC4337Utils} from "../../../account/utils/ERC4337Utils.sol"; + +/** + * @dev Implementation of the ERC-3009 Transfer With Authorization extension allowing + * transfers to be made via signatures, as defined in https://eips.ethereum.org/EIPS/eip-3009[ERC-3009]. + * + * Adds the {transferWithAuthorization} and {receiveWithAuthorization} methods, which + * can be used to change an account's ERC-20 balance by presenting a message signed + * by the account. By not relying on {IERC20-approve} and {IERC20-transferFrom}, the + * token holder account doesn't need to send a transaction, and thus is not required + * to hold native currency (e.g. ETH) at all. + * + * NOTE: To enable both timestamp-based and block-number-based validity windows, `validAfter` and + * `validBefore` use a dual-clock encoding mirroring {ERC4337Utils}. Bit 47 ({BLOCK_RANGE_FLAG}) acts as a + * clock selector: when *both* `validAfter` and `validBefore` have this bit set, the values are interpreted + * as block numbers; otherwise they are interpreted as Unix timestamps (the default, matching the ERC-3009 + * specification). Since the current clock fits in 48 bits, any bit set at position 47 or above (other than + * the active clock-mode flag) makes the value point to an unreachable future. See {_checkValidity}. + */ +abstract contract ERC3009 is ERC20, EIP712, IERC3009, IERC3009Cancel { + /// @dev The signature is invalid + error ERC3009InvalidSignature(); + + /// @dev The authorization is not valid at the given time + error ERC3009InvalidAuthorizationTime(uint256 validAfter, uint256 validBefore); + + /// @dev The authorization has already been used or canceled + error ERC3009UsedAuthorization(address authorizer, bytes32 nonce); + + bytes32 internal constant TRANSFER_WITH_AUTHORIZATION_TYPEHASH = + keccak256( + "TransferWithAuthorization(address from,address to,uint256 value,uint256 validAfter,uint256 validBefore,bytes32 nonce)" + ); + bytes32 internal constant RECEIVE_WITH_AUTHORIZATION_TYPEHASH = + keccak256( + "ReceiveWithAuthorization(address from,address to,uint256 value,uint256 validAfter,uint256 validBefore,bytes32 nonce)" + ); + bytes32 internal constant CANCEL_AUTHORIZATION_TYPEHASH = + keccak256("CancelAuthorization(address authorizer,bytes32 nonce)"); + + mapping(address account => mapping(bytes32 nonce => bool used)) private _usedNonces; + + /// @inheritdoc IERC3009 + function authorizationState(address authorizer, bytes32 nonce) public view virtual returns (bool) { + return _usedNonces[authorizer][nonce]; + } + + /// @inheritdoc IERC3009 + function transferWithAuthorization( + address from, + address to, + uint256 value, + uint256 validAfter, + uint256 validBefore, + bytes32 nonce, + uint8 v, + bytes32 r, + bytes32 s + ) public virtual { + bytes32 hash = _hashTypedDataV4( + keccak256(abi.encode(TRANSFER_WITH_AUTHORIZATION_TYPEHASH, from, to, value, validAfter, validBefore, nonce)) + ); + require(from == ECDSA.recover(hash, v, r, s), ERC3009InvalidSignature()); + _transferWithAuthorization(from, to, value, validAfter, validBefore, nonce); + } + + /// @inheritdoc IERC3009 + function receiveWithAuthorization( + address from, + address to, + uint256 value, + uint256 validAfter, + uint256 validBefore, + bytes32 nonce, + uint8 v, + bytes32 r, + bytes32 s + ) public virtual { + bytes32 hash = _hashTypedDataV4( + keccak256(abi.encode(RECEIVE_WITH_AUTHORIZATION_TYPEHASH, from, to, value, validAfter, validBefore, nonce)) + ); + require(from == ECDSA.recover(hash, v, r, s), ERC3009InvalidSignature()); + require(to == _msgSender(), ERC20InvalidReceiver(to)); + _transferWithAuthorization(from, to, value, validAfter, validBefore, nonce); + } + + /// @inheritdoc IERC3009Cancel + function cancelAuthorization(address authorizer, bytes32 nonce, uint8 v, bytes32 r, bytes32 s) public virtual { + bytes32 hash = _hashTypedDataV4(keccak256(abi.encode(CANCEL_AUTHORIZATION_TYPEHASH, authorizer, nonce))); + require(authorizer == ECDSA.recover(hash, v, r, s), ERC3009InvalidSignature()); + _cancelAuthorization(authorizer, nonce); + } + + /// @dev Performs the time and nonce checks, then executes the transfer. + function _transferWithAuthorization( + address from, + address to, + uint256 value, + uint256 validAfter, + uint256 validBefore, + bytes32 nonce + ) internal virtual { + _checkValidity(validAfter, validBefore); + _consumeNonce(from, nonce); + emit AuthorizationUsed(from, nonce); + _transfer(from, to, value); + } + + /// @dev Consumes the nonce and emits the cancellation event. + function _cancelAuthorization(address authorizer, bytes32 nonce) internal virtual { + _consumeNonce(authorizer, nonce); + emit AuthorizationCanceled(authorizer, nonce); + } + + /// @dev Marks `nonce` as used for `authorizer`. Reverts with {ERC3009UsedAuthorization} if already consumed. + function _consumeNonce(address authorizer, bytes32 nonce) internal virtual { + require(!_usedNonces[authorizer][nonce], ERC3009UsedAuthorization(authorizer, nonce)); + _usedNonces[authorizer][nonce] = true; + } + + /** + * @dev Checks the validity of the authorization against the current clock. + * + * Following the ERC-4337-style dual-clock encoding, the clock is interpreted as block number only when + * *both* `validAfter` and `validBefore` carry the {BLOCK_RANGE_FLAG}; otherwise it falls back to + * timestamp (matching the ERC-3009 specification's default). Mixed-flag inputs therefore fall back to + * the timestamp clock rather than reverting, mirroring {ERC4337Utils-parseValidationData}. The flag bit + * is masked off the values only when block-mode is engaged; in timestamp mode the full 256-bit value + * participates in the comparison. + * + * NOTE: Any `validAfter` or `validBefore` with a bit set at position 47 or above (other than the active + * clock-mode flag) is interpreted as an unreachable point in the future (i.e. never valid after or + * always valid before, respectively). + */ + function _checkValidity(uint256 validAfter, uint256 validBefore) internal view virtual { + uint256 flag = validAfter & validBefore & ERC4337Utils.BLOCK_RANGE_FLAG; + uint256 current = flag == 0 ? Time.timestamp() : Time.blockNumber(); + require( + current > (validAfter & ~flag) && current < (validBefore & ~flag), + ERC3009InvalidAuthorizationTime(validAfter, validBefore) + ); + } +} diff --git a/dependencies/@openzeppelin-contracts-5.5.0/token/ERC20/utils/ERC1363Utils.sol b/dependencies/@openzeppelin-contracts-5.7.0/token/ERC20/utils/ERC1363Utils.sol similarity index 100% rename from dependencies/@openzeppelin-contracts-5.5.0/token/ERC20/utils/ERC1363Utils.sol rename to dependencies/@openzeppelin-contracts-5.7.0/token/ERC20/utils/ERC1363Utils.sol diff --git a/dependencies/@openzeppelin-contracts-5.5.0/token/ERC20/utils/SafeERC20.sol b/dependencies/@openzeppelin-contracts-5.7.0/token/ERC20/utils/SafeERC20.sol similarity index 93% rename from dependencies/@openzeppelin-contracts-5.5.0/token/ERC20/utils/SafeERC20.sol rename to dependencies/@openzeppelin-contracts-5.7.0/token/ERC20/utils/SafeERC20.sol index b1e4b6e..39f8df5 100644 --- a/dependencies/@openzeppelin-contracts-5.5.0/token/ERC20/utils/SafeERC20.sol +++ b/dependencies/@openzeppelin-contracts-5.7.0/token/ERC20/utils/SafeERC20.sol @@ -1,10 +1,11 @@ // SPDX-License-Identifier: MIT -// OpenZeppelin Contracts (last updated v5.5.0) (token/ERC20/utils/SafeERC20.sol) +// OpenZeppelin Contracts (last updated v5.7.0) (token/ERC20/utils/SafeERC20.sol) pragma solidity ^0.8.20; import {IERC20} from "../IERC20.sol"; import {IERC1363} from "../../../interfaces/IERC1363.sol"; +import {IERC20Metadata} from "../../../interfaces/IERC20Metadata.sol"; /** * @title SafeERC20 @@ -164,6 +165,17 @@ library SafeERC20 { } } + /// @dev Attempts to fetch the token decimals. A return value of false indicates that the attempt failed in some way. + function tryGetDecimals(IERC20 token) internal view returns (bool success, uint8 decimals) { + bytes4 selector = IERC20Metadata.decimals.selector; + assembly ("memory-safe") { + mstore(0x00, selector) + success := staticcall(gas(), token, 0x00, 4, 0x00, 0x20) + success := and(and(success, gt(returndatasize(), 0x1f)), lt(mload(0x00), 0x100)) + decimals := mul(success, mload(0x00)) + } + } + /** * @dev Imitates a Solidity `token.transfer(to, value)` call, relaxing the requirement on the return value: the * return value is optional (but if data is returned, it must not be false). @@ -249,8 +261,8 @@ library SafeERC20 { * * @param token The token targeted by the call. * @param spender The spender of the tokens - * @param value The amount of token to transfer - * @param bubble Behavior switch if the transfer call reverts: bubble the revert reason or return a false boolean. + * @param value The amount of token to approve + * @param bubble Behavior switch if the approve call reverts: bubble the revert reason or return a false boolean. */ function _safeApprove(IERC20 token, address spender, uint256 value, bool bubble) private returns (bool success) { bytes4 selector = IERC20.approve.selector; diff --git a/dependencies/@openzeppelin-contracts-5.5.0/token/ERC6909/ERC6909.sol b/dependencies/@openzeppelin-contracts-5.7.0/token/ERC6909/ERC6909.sol similarity index 100% rename from dependencies/@openzeppelin-contracts-5.5.0/token/ERC6909/ERC6909.sol rename to dependencies/@openzeppelin-contracts-5.7.0/token/ERC6909/ERC6909.sol diff --git a/dependencies/@openzeppelin-contracts-5.5.0/token/ERC6909/extensions/ERC6909ContentURI.sol b/dependencies/@openzeppelin-contracts-5.7.0/token/ERC6909/extensions/ERC6909ContentURI.sol similarity index 80% rename from dependencies/@openzeppelin-contracts-5.5.0/token/ERC6909/extensions/ERC6909ContentURI.sol rename to dependencies/@openzeppelin-contracts-5.7.0/token/ERC6909/extensions/ERC6909ContentURI.sol index 353de29..09288eb 100644 --- a/dependencies/@openzeppelin-contracts-5.5.0/token/ERC6909/extensions/ERC6909ContentURI.sol +++ b/dependencies/@openzeppelin-contracts-5.7.0/token/ERC6909/extensions/ERC6909ContentURI.sol @@ -1,10 +1,11 @@ // SPDX-License-Identifier: MIT -// OpenZeppelin Contracts (last updated v5.5.0) (token/ERC6909/extensions/ERC6909ContentURI.sol) +// OpenZeppelin Contracts (last updated v5.6.0) (token/ERC6909/extensions/ERC6909ContentURI.sol) pragma solidity ^0.8.20; import {ERC6909} from "../ERC6909.sol"; import {IERC6909ContentURI} from "../../../interfaces/IERC6909.sol"; +import {IERC165} from "../../../utils/introspection/IERC165.sol"; /** * @dev Implementation of the Content URI extension defined in ERC6909. @@ -19,6 +20,11 @@ contract ERC6909ContentURI is ERC6909, IERC6909ContentURI { /// @dev See {IERC1155-URI} event URI(string value, uint256 indexed id); + /// @inheritdoc IERC165 + function supportsInterface(bytes4 interfaceId) public view virtual override(ERC6909, IERC165) returns (bool) { + return interfaceId == type(IERC6909ContentURI).interfaceId || super.supportsInterface(interfaceId); + } + /// @inheritdoc IERC6909ContentURI function contractURI() public view virtual override returns (string memory) { return _contractURI; diff --git a/dependencies/@openzeppelin-contracts-5.5.0/token/ERC6909/extensions/ERC6909Metadata.sol b/dependencies/@openzeppelin-contracts-5.7.0/token/ERC6909/extensions/ERC6909Metadata.sol similarity index 86% rename from dependencies/@openzeppelin-contracts-5.5.0/token/ERC6909/extensions/ERC6909Metadata.sol rename to dependencies/@openzeppelin-contracts-5.7.0/token/ERC6909/extensions/ERC6909Metadata.sol index 6ada69a..e58b61d 100644 --- a/dependencies/@openzeppelin-contracts-5.5.0/token/ERC6909/extensions/ERC6909Metadata.sol +++ b/dependencies/@openzeppelin-contracts-5.7.0/token/ERC6909/extensions/ERC6909Metadata.sol @@ -1,10 +1,11 @@ // SPDX-License-Identifier: MIT -// OpenZeppelin Contracts (last updated v5.5.0) (token/ERC6909/extensions/ERC6909Metadata.sol) +// OpenZeppelin Contracts (last updated v5.6.0) (token/ERC6909/extensions/ERC6909Metadata.sol) pragma solidity ^0.8.20; import {ERC6909} from "../ERC6909.sol"; import {IERC6909Metadata} from "../../../interfaces/IERC6909.sol"; +import {IERC165} from "../../../utils/introspection/IERC165.sol"; /** * @dev Implementation of the Metadata extension defined in ERC6909. Exposes the name, symbol, and decimals of each token id. @@ -42,6 +43,11 @@ contract ERC6909Metadata is ERC6909, IERC6909Metadata { return _tokenMetadata[id].decimals; } + /// @inheritdoc IERC165 + function supportsInterface(bytes4 interfaceId) public view virtual override(ERC6909, IERC165) returns (bool) { + return interfaceId == type(IERC6909Metadata).interfaceId || super.supportsInterface(interfaceId); + } + /** * @dev Sets the `name` for a given token of type `id`. * diff --git a/dependencies/@openzeppelin-contracts-5.5.0/token/ERC6909/extensions/ERC6909TokenSupply.sol b/dependencies/@openzeppelin-contracts-5.7.0/token/ERC6909/extensions/ERC6909TokenSupply.sol similarity index 75% rename from dependencies/@openzeppelin-contracts-5.5.0/token/ERC6909/extensions/ERC6909TokenSupply.sol rename to dependencies/@openzeppelin-contracts-5.7.0/token/ERC6909/extensions/ERC6909TokenSupply.sol index f4a9c60..fa60286 100644 --- a/dependencies/@openzeppelin-contracts-5.5.0/token/ERC6909/extensions/ERC6909TokenSupply.sol +++ b/dependencies/@openzeppelin-contracts-5.7.0/token/ERC6909/extensions/ERC6909TokenSupply.sol @@ -1,10 +1,11 @@ // SPDX-License-Identifier: MIT -// OpenZeppelin Contracts (last updated v5.5.0) (token/ERC6909/extensions/ERC6909TokenSupply.sol) +// OpenZeppelin Contracts (last updated v5.6.0) (token/ERC6909/extensions/ERC6909TokenSupply.sol) pragma solidity ^0.8.20; import {ERC6909} from "../ERC6909.sol"; import {IERC6909TokenSupply} from "../../../interfaces/IERC6909.sol"; +import {IERC165} from "../../../utils/introspection/IERC165.sol"; /** * @dev Implementation of the Token Supply extension defined in ERC6909. @@ -18,6 +19,11 @@ contract ERC6909TokenSupply is ERC6909, IERC6909TokenSupply { return _totalSupplies[id]; } + /// @inheritdoc IERC165 + function supportsInterface(bytes4 interfaceId) public view virtual override(ERC6909, IERC165) returns (bool) { + return interfaceId == type(IERC6909TokenSupply).interfaceId || super.supportsInterface(interfaceId); + } + /// @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); diff --git a/dependencies/@openzeppelin-contracts-5.5.0/token/ERC721/ERC721.sol b/dependencies/@openzeppelin-contracts-5.7.0/token/ERC721/ERC721.sol similarity index 98% rename from dependencies/@openzeppelin-contracts-5.5.0/token/ERC721/ERC721.sol rename to dependencies/@openzeppelin-contracts-5.7.0/token/ERC721/ERC721.sol index f4783f1..f5b7588 100644 --- a/dependencies/@openzeppelin-contracts-5.5.0/token/ERC721/ERC721.sol +++ b/dependencies/@openzeppelin-contracts-5.7.0/token/ERC721/ERC721.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -// OpenZeppelin Contracts (last updated v5.5.0) (token/ERC721/ERC721.sol) +// OpenZeppelin Contracts (last updated v5.6.0) (token/ERC721/ERC721.sol) pragma solidity ^0.8.24; @@ -407,6 +407,9 @@ abstract contract ERC721 is Context, ERC165, IERC721, IERC721Metadata, IERC721Er * Emits an {ApprovalForAll} event. */ function _setApprovalForAll(address owner, address operator, bool approved) internal virtual { + if (owner == address(0)) { + revert ERC721InvalidApprover(address(0)); + } if (operator == address(0)) { revert ERC721InvalidOperator(operator); } diff --git a/dependencies/@openzeppelin-contracts-5.5.0/token/ERC721/IERC721.sol b/dependencies/@openzeppelin-contracts-5.7.0/token/ERC721/IERC721.sol similarity index 100% rename from dependencies/@openzeppelin-contracts-5.5.0/token/ERC721/IERC721.sol rename to dependencies/@openzeppelin-contracts-5.7.0/token/ERC721/IERC721.sol diff --git a/dependencies/@openzeppelin-contracts-5.5.0/token/ERC721/IERC721Receiver.sol b/dependencies/@openzeppelin-contracts-5.7.0/token/ERC721/IERC721Receiver.sol similarity index 100% rename from dependencies/@openzeppelin-contracts-5.5.0/token/ERC721/IERC721Receiver.sol rename to dependencies/@openzeppelin-contracts-5.7.0/token/ERC721/IERC721Receiver.sol diff --git a/dependencies/@openzeppelin-contracts-5.5.0/token/ERC721/extensions/ERC721Burnable.sol b/dependencies/@openzeppelin-contracts-5.7.0/token/ERC721/extensions/ERC721Burnable.sol similarity index 100% rename from dependencies/@openzeppelin-contracts-5.5.0/token/ERC721/extensions/ERC721Burnable.sol rename to dependencies/@openzeppelin-contracts-5.7.0/token/ERC721/extensions/ERC721Burnable.sol diff --git a/dependencies/@openzeppelin-contracts-5.5.0/token/ERC721/extensions/ERC721Consecutive.sol b/dependencies/@openzeppelin-contracts-5.7.0/token/ERC721/extensions/ERC721Consecutive.sol similarity index 97% rename from dependencies/@openzeppelin-contracts-5.5.0/token/ERC721/extensions/ERC721Consecutive.sol rename to dependencies/@openzeppelin-contracts-5.7.0/token/ERC721/extensions/ERC721Consecutive.sol index a391923..1d96b7f 100644 --- a/dependencies/@openzeppelin-contracts-5.5.0/token/ERC721/extensions/ERC721Consecutive.sol +++ b/dependencies/@openzeppelin-contracts-5.7.0/token/ERC721/extensions/ERC721Consecutive.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -// OpenZeppelin Contracts (last updated v5.5.0) (token/ERC721/extensions/ERC721Consecutive.sol) +// OpenZeppelin Contracts (last updated v5.7.0) (token/ERC721/extensions/ERC721Consecutive.sol) pragma solidity ^0.8.24; @@ -87,7 +87,7 @@ abstract contract ERC721Consecutive is IERC2309, ERC721 { /** * @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. + * batch; if `batchSize` is 0, returns the next token id to be minted consecutively. * * Requirements: * diff --git a/dependencies/@openzeppelin-contracts-5.7.0/token/ERC721/extensions/ERC721Crosschain.sol b/dependencies/@openzeppelin-contracts-5.7.0/token/ERC721/extensions/ERC721Crosschain.sol new file mode 100644 index 0000000..4be0d25 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.7.0/token/ERC721/extensions/ERC721Crosschain.sol @@ -0,0 +1,38 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v5.7.0) (token/ERC721/extensions/ERC721Crosschain.sol) + +pragma solidity ^0.8.26; + +import {ERC721} from "../ERC721.sol"; +import {BridgeNonFungible} from "../../../crosschain/bridges/abstract/BridgeNonFungible.sol"; + +/** + * @dev Extension of {ERC721} that makes it natively cross-chain using the ERC-7786 based {BridgeNonFungible}. + * + * This extension makes the token compatible with: + * * {ERC721Crosschain} instances on other chains, + * * {ERC721} instances on other chains that are bridged using {BridgeERC721}, + */ +// slither-disable-next-line locked-ether +abstract contract ERC721Crosschain is BridgeNonFungible, ERC721 { + /// @dev Crosschain variant of {transferFrom}, using the allowance system from the underlying ERC-721 token. + function crosschainTransferFrom(address from, bytes memory to, uint256 tokenId) public virtual returns (bytes32) { + // operator (_msgSender) permission over `from` is checked in `_onSend` + return _crosschainTransfer(from, to, tokenId); + } + + /// @dev "Locking" tokens is achieved through burning + function _onSend(address from, uint256 tokenId) internal virtual override { + address previousOwner = _update(address(0), tokenId, _msgSender()); + if (previousOwner == address(0)) { + revert ERC721NonexistentToken(tokenId); + } else if (previousOwner != from) { + revert ERC721IncorrectOwner(from, tokenId, previousOwner); + } + } + + /// @dev "Unlocking" tokens is achieved through minting + function _onReceive(address to, uint256 tokenId) internal virtual override { + _mint(to, tokenId); + } +} diff --git a/dependencies/@openzeppelin-contracts-5.5.0/token/ERC721/extensions/ERC721Enumerable.sol b/dependencies/@openzeppelin-contracts-5.7.0/token/ERC721/extensions/ERC721Enumerable.sol similarity index 97% rename from dependencies/@openzeppelin-contracts-5.5.0/token/ERC721/extensions/ERC721Enumerable.sol rename to dependencies/@openzeppelin-contracts-5.7.0/token/ERC721/extensions/ERC721Enumerable.sol index 07e2202..109d1e8 100644 --- a/dependencies/@openzeppelin-contracts-5.5.0/token/ERC721/extensions/ERC721Enumerable.sol +++ b/dependencies/@openzeppelin-contracts-5.7.0/token/ERC721/extensions/ERC721Enumerable.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -// OpenZeppelin Contracts (last updated v5.5.0) (token/ERC721/extensions/ERC721Enumerable.sol) +// OpenZeppelin Contracts (last updated v5.6.0) (token/ERC721/extensions/ERC721Enumerable.sol) pragma solidity ^0.8.24; @@ -153,7 +153,8 @@ abstract contract ERC721Enumerable is ERC721, IERC721Enumerable { } /** - * See {ERC721-_increaseBalance}. We need that to account tokens that were minted in batch + * See {ERC721-_increaseBalance}. We need to forbid batch minting because the enumeration + * extension does not support it. */ function _increaseBalance(address account, uint128 amount) internal virtual override { if (amount > 0) { diff --git a/dependencies/@openzeppelin-contracts-5.5.0/token/ERC721/extensions/ERC721Pausable.sol b/dependencies/@openzeppelin-contracts-5.7.0/token/ERC721/extensions/ERC721Pausable.sol similarity index 100% rename from dependencies/@openzeppelin-contracts-5.5.0/token/ERC721/extensions/ERC721Pausable.sol rename to dependencies/@openzeppelin-contracts-5.7.0/token/ERC721/extensions/ERC721Pausable.sol diff --git a/dependencies/@openzeppelin-contracts-5.5.0/token/ERC721/extensions/ERC721Royalty.sol b/dependencies/@openzeppelin-contracts-5.7.0/token/ERC721/extensions/ERC721Royalty.sol similarity index 100% rename from dependencies/@openzeppelin-contracts-5.5.0/token/ERC721/extensions/ERC721Royalty.sol rename to dependencies/@openzeppelin-contracts-5.7.0/token/ERC721/extensions/ERC721Royalty.sol diff --git a/dependencies/@openzeppelin-contracts-5.5.0/token/ERC721/extensions/ERC721URIStorage.sol b/dependencies/@openzeppelin-contracts-5.7.0/token/ERC721/extensions/ERC721URIStorage.sol similarity index 79% rename from dependencies/@openzeppelin-contracts-5.5.0/token/ERC721/extensions/ERC721URIStorage.sol rename to dependencies/@openzeppelin-contracts-5.7.0/token/ERC721/extensions/ERC721URIStorage.sol index 92e9f77..1b4fba5 100644 --- a/dependencies/@openzeppelin-contracts-5.5.0/token/ERC721/extensions/ERC721URIStorage.sol +++ b/dependencies/@openzeppelin-contracts-5.7.0/token/ERC721/extensions/ERC721URIStorage.sol @@ -1,11 +1,10 @@ // SPDX-License-Identifier: MIT -// OpenZeppelin Contracts (last updated v5.5.0) (token/ERC721/extensions/ERC721URIStorage.sol) +// OpenZeppelin Contracts (last updated v5.6.0) (token/ERC721/extensions/ERC721URIStorage.sol) pragma solidity ^0.8.24; 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"; @@ -13,8 +12,6 @@ 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); @@ -31,16 +28,16 @@ abstract contract ERC721URIStorage is IERC4906, ERC721 { function tokenURI(uint256 tokenId) public view virtual override returns (string memory) { _requireOwned(tokenId); - string memory _tokenURI = _tokenURIs[tokenId]; string memory base = _baseURI(); + string memory suffix = _suffixURI(tokenId); // If there is no base URI, return the token URI. if (bytes(base).length == 0) { - return _tokenURI; + return suffix; } // If both are set, concatenate the baseURI and tokenURI (via string.concat). - if (bytes(_tokenURI).length > 0) { - return string.concat(base, _tokenURI); + if (bytes(suffix).length > 0) { + return string.concat(base, suffix); } return super.tokenURI(tokenId); @@ -55,4 +52,11 @@ abstract contract ERC721URIStorage is IERC4906, ERC721 { _tokenURIs[tokenId] = _tokenURI; emit MetadataUpdate(tokenId); } + + /** + * @dev Returns the suffix part of the tokenURI for `tokenId`. + */ + function _suffixURI(uint256 tokenId) internal view virtual returns (string memory) { + return _tokenURIs[tokenId]; + } } diff --git a/dependencies/@openzeppelin-contracts-5.5.0/token/ERC721/extensions/ERC721Votes.sol b/dependencies/@openzeppelin-contracts-5.7.0/token/ERC721/extensions/ERC721Votes.sol similarity index 100% rename from dependencies/@openzeppelin-contracts-5.5.0/token/ERC721/extensions/ERC721Votes.sol rename to dependencies/@openzeppelin-contracts-5.7.0/token/ERC721/extensions/ERC721Votes.sol diff --git a/dependencies/@openzeppelin-contracts-5.5.0/token/ERC721/extensions/ERC721Wrapper.sol b/dependencies/@openzeppelin-contracts-5.7.0/token/ERC721/extensions/ERC721Wrapper.sol similarity index 100% rename from dependencies/@openzeppelin-contracts-5.5.0/token/ERC721/extensions/ERC721Wrapper.sol rename to dependencies/@openzeppelin-contracts-5.7.0/token/ERC721/extensions/ERC721Wrapper.sol diff --git a/dependencies/@openzeppelin-contracts-5.5.0/token/ERC721/extensions/IERC721Enumerable.sol b/dependencies/@openzeppelin-contracts-5.7.0/token/ERC721/extensions/IERC721Enumerable.sol similarity index 100% rename from dependencies/@openzeppelin-contracts-5.5.0/token/ERC721/extensions/IERC721Enumerable.sol rename to dependencies/@openzeppelin-contracts-5.7.0/token/ERC721/extensions/IERC721Enumerable.sol diff --git a/dependencies/@openzeppelin-contracts-5.5.0/token/ERC721/extensions/IERC721Metadata.sol b/dependencies/@openzeppelin-contracts-5.7.0/token/ERC721/extensions/IERC721Metadata.sol similarity index 100% rename from dependencies/@openzeppelin-contracts-5.5.0/token/ERC721/extensions/IERC721Metadata.sol rename to dependencies/@openzeppelin-contracts-5.7.0/token/ERC721/extensions/IERC721Metadata.sol diff --git a/dependencies/@openzeppelin-contracts-5.5.0/token/ERC721/utils/ERC721Holder.sol b/dependencies/@openzeppelin-contracts-5.7.0/token/ERC721/utils/ERC721Holder.sol similarity index 100% rename from dependencies/@openzeppelin-contracts-5.5.0/token/ERC721/utils/ERC721Holder.sol rename to dependencies/@openzeppelin-contracts-5.7.0/token/ERC721/utils/ERC721Holder.sol diff --git a/dependencies/@openzeppelin-contracts-5.5.0/token/ERC721/utils/ERC721Utils.sol b/dependencies/@openzeppelin-contracts-5.7.0/token/ERC721/utils/ERC721Utils.sol similarity index 100% rename from dependencies/@openzeppelin-contracts-5.5.0/token/ERC721/utils/ERC721Utils.sol rename to dependencies/@openzeppelin-contracts-5.7.0/token/ERC721/utils/ERC721Utils.sol diff --git a/dependencies/@openzeppelin-contracts-5.5.0/token/common/ERC2981.sol b/dependencies/@openzeppelin-contracts-5.7.0/token/common/ERC2981.sol similarity index 96% rename from dependencies/@openzeppelin-contracts-5.5.0/token/common/ERC2981.sol rename to dependencies/@openzeppelin-contracts-5.7.0/token/common/ERC2981.sol index 5d75e3a..0374455 100644 --- a/dependencies/@openzeppelin-contracts-5.5.0/token/common/ERC2981.sol +++ b/dependencies/@openzeppelin-contracts-5.7.0/token/common/ERC2981.sol @@ -1,10 +1,11 @@ // SPDX-License-Identifier: MIT -// OpenZeppelin Contracts (last updated v5.4.0) (token/common/ERC2981.sol) +// OpenZeppelin Contracts (last updated v5.7.0) (token/common/ERC2981.sol) pragma solidity ^0.8.20; import {IERC2981} from "../../interfaces/IERC2981.sol"; import {IERC165, ERC165} from "../../utils/introspection/ERC165.sol"; +import {Math} from "../../utils/math/Math.sol"; /** * @dev Implementation of the NFT Royalty Standard, a standardized way to retrieve royalty payment information. @@ -67,7 +68,7 @@ abstract contract ERC2981 is IERC2981, ERC165 { royaltyFraction = _defaultRoyaltyInfo.royaltyFraction; } - uint256 royaltyAmount = (salePrice * royaltyFraction) / _feeDenominator(); + uint256 royaltyAmount = Math.mulDiv(salePrice, royaltyFraction, _feeDenominator()); return (royaltyReceiver, royaltyAmount); } diff --git a/dependencies/@openzeppelin-contracts-5.5.0/utils/Address.sol b/dependencies/@openzeppelin-contracts-5.7.0/utils/Address.sol similarity index 100% rename from dependencies/@openzeppelin-contracts-5.5.0/utils/Address.sol rename to dependencies/@openzeppelin-contracts-5.7.0/utils/Address.sol diff --git a/dependencies/@openzeppelin-contracts-5.5.0/utils/Arrays.sol b/dependencies/@openzeppelin-contracts-5.7.0/utils/Arrays.sol similarity index 76% rename from dependencies/@openzeppelin-contracts-5.5.0/utils/Arrays.sol rename to dependencies/@openzeppelin-contracts-5.7.0/utils/Arrays.sol index e49be48..f19e3ae 100644 --- a/dependencies/@openzeppelin-contracts-5.5.0/utils/Arrays.sol +++ b/dependencies/@openzeppelin-contracts-5.7.0/utils/Arrays.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -// OpenZeppelin Contracts (last updated v5.5.0) (utils/Arrays.sol) +// OpenZeppelin Contracts (last updated v5.7.0) (utils/Arrays.sol) // This file was procedurally generated from scripts/generate/templates/Arrays.js. pragma solidity ^0.8.24; @@ -114,25 +114,33 @@ library Arrays { */ 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); + while (end - begin > 0x20) { + // 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 + _swap(begin, pos); // Swap pivot into place + + // Recurse on the smaller partition, iterate on the larger one. + uint256 middle = pos + 0x20; + if (pos - begin < end - middle) { + _quickSort(begin, pos, comp); + begin = middle; + } else { + _quickSort(middle, end, comp); + end = pos; + } + } } } @@ -466,21 +474,21 @@ library Arrays { } /** - * @dev Moves the content of `array`, from `start` (included) to the end of `array` to the start of that array. + * @dev Moves the content of `array`, from `start` (included) to the end of `array` to the start of that array, + * and shrinks the array length accordingly, effectively overwriting the array with array[start:]. * * NOTE: This function modifies the provided array in place. If you need to preserve the original array, use {slice} instead. - * NOTE: replicates the behavior of https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/splice[Javascript's `Array.splice`] */ function splice(address[] memory array, uint256 start) internal pure returns (address[] memory) { return splice(array, start, array.length); } /** - * @dev Moves the content of `array`, from `start` (included) to `end` (excluded) to the start of that array. The + * @dev Moves the content of `array`, from `start` (included) to `end` (excluded) to the start of that array, + * and shrinks the array length accordingly, effectively overwriting the array with array[start:end]. The * `end` argument is truncated to the length of the `array`. * * NOTE: This function modifies the provided array in place. If you need to preserve the original array, use {slice} instead. - * NOTE: replicates the behavior of https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/splice[Javascript's `Array.splice`] */ function splice(address[] memory array, uint256 start, uint256 end) internal pure returns (address[] memory) { // sanitize @@ -497,21 +505,72 @@ library Arrays { } /** - * @dev Moves the content of `array`, from `start` (included) to the end of `array` to the start of that array. + * @dev Replaces elements in `array` starting at `pos` with all elements from `replacement`. + * + * Parameters are clamped to valid ranges (e.g. `pos` is clamped to `[0, array.length]`). + * If `pos >= array.length`, no replacement occurs and the array is returned unchanged. + * + * NOTE: This function modifies the provided array in place. + */ + function replace( + address[] memory array, + uint256 pos, + address[] memory replacement + ) internal pure returns (address[] memory) { + return replace(array, pos, replacement, 0, replacement.length); + } + + /** + * @dev Replaces elements in `array` starting at `pos` with elements from `replacement` starting at `offset`. + * Copies at most `length` elements from `replacement` to `array`. + * + * Parameters are clamped to valid ranges (i.e. `pos` is clamped to `[0, array.length]`, `offset` is + * clamped to `[0, replacement.length]`, and `length` is clamped to `min(length, replacement.length - offset, + * array.length - pos)`). If `pos >= array.length` or `offset >= replacement.length`, no replacement occurs + * and the array is returned unchanged. + * + * NOTE: This function modifies the provided array in place. + */ + function replace( + address[] memory array, + uint256 pos, + address[] memory replacement, + uint256 offset, + uint256 length + ) internal pure returns (address[] memory) { + // sanitize + pos = Math.min(pos, array.length); + offset = Math.min(offset, replacement.length); + length = Math.min(length, Math.min(replacement.length - offset, array.length - pos)); + + // replace + assembly ("memory-safe") { + mcopy( + add(add(array, 0x20), mul(pos, 0x20)), + add(add(replacement, 0x20), mul(offset, 0x20)), + mul(length, 0x20) + ) + } + + return array; + } + + /** + * @dev Moves the content of `array`, from `start` (included) to the end of `array` to the start of that array, + * and shrinks the array length accordingly, effectively overwriting the array with array[start:]. * * NOTE: This function modifies the provided array in place. If you need to preserve the original array, use {slice} instead. - * NOTE: replicates the behavior of https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/splice[Javascript's `Array.splice`] */ function splice(bytes32[] memory array, uint256 start) internal pure returns (bytes32[] memory) { return splice(array, start, array.length); } /** - * @dev Moves the content of `array`, from `start` (included) to `end` (excluded) to the start of that array. The + * @dev Moves the content of `array`, from `start` (included) to `end` (excluded) to the start of that array, + * and shrinks the array length accordingly, effectively overwriting the array with array[start:end]. The * `end` argument is truncated to the length of the `array`. * * NOTE: This function modifies the provided array in place. If you need to preserve the original array, use {slice} instead. - * NOTE: replicates the behavior of https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/splice[Javascript's `Array.splice`] */ function splice(bytes32[] memory array, uint256 start, uint256 end) internal pure returns (bytes32[] memory) { // sanitize @@ -528,21 +587,72 @@ library Arrays { } /** - * @dev Moves the content of `array`, from `start` (included) to the end of `array` to the start of that array. + * @dev Replaces elements in `array` starting at `pos` with all elements from `replacement`. + * + * Parameters are clamped to valid ranges (e.g. `pos` is clamped to `[0, array.length]`). + * If `pos >= array.length`, no replacement occurs and the array is returned unchanged. + * + * NOTE: This function modifies the provided array in place. + */ + function replace( + bytes32[] memory array, + uint256 pos, + bytes32[] memory replacement + ) internal pure returns (bytes32[] memory) { + return replace(array, pos, replacement, 0, replacement.length); + } + + /** + * @dev Replaces elements in `array` starting at `pos` with elements from `replacement` starting at `offset`. + * Copies at most `length` elements from `replacement` to `array`. + * + * Parameters are clamped to valid ranges (i.e. `pos` is clamped to `[0, array.length]`, `offset` is + * clamped to `[0, replacement.length]`, and `length` is clamped to `min(length, replacement.length - offset, + * array.length - pos)`). If `pos >= array.length` or `offset >= replacement.length`, no replacement occurs + * and the array is returned unchanged. + * + * NOTE: This function modifies the provided array in place. + */ + function replace( + bytes32[] memory array, + uint256 pos, + bytes32[] memory replacement, + uint256 offset, + uint256 length + ) internal pure returns (bytes32[] memory) { + // sanitize + pos = Math.min(pos, array.length); + offset = Math.min(offset, replacement.length); + length = Math.min(length, Math.min(replacement.length - offset, array.length - pos)); + + // replace + assembly ("memory-safe") { + mcopy( + add(add(array, 0x20), mul(pos, 0x20)), + add(add(replacement, 0x20), mul(offset, 0x20)), + mul(length, 0x20) + ) + } + + return array; + } + + /** + * @dev Moves the content of `array`, from `start` (included) to the end of `array` to the start of that array, + * and shrinks the array length accordingly, effectively overwriting the array with array[start:]. * * NOTE: This function modifies the provided array in place. If you need to preserve the original array, use {slice} instead. - * NOTE: replicates the behavior of https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/splice[Javascript's `Array.splice`] */ function splice(uint256[] memory array, uint256 start) internal pure returns (uint256[] memory) { return splice(array, start, array.length); } /** - * @dev Moves the content of `array`, from `start` (included) to `end` (excluded) to the start of that array. The + * @dev Moves the content of `array`, from `start` (included) to `end` (excluded) to the start of that array, + * and shrinks the array length accordingly, effectively overwriting the array with array[start:end]. The * `end` argument is truncated to the length of the `array`. * * NOTE: This function modifies the provided array in place. If you need to preserve the original array, use {slice} instead. - * NOTE: replicates the behavior of https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/splice[Javascript's `Array.splice`] */ function splice(uint256[] memory array, uint256 start, uint256 end) internal pure returns (uint256[] memory) { // sanitize @@ -558,6 +668,57 @@ library Arrays { return array; } + /** + * @dev Replaces elements in `array` starting at `pos` with all elements from `replacement`. + * + * Parameters are clamped to valid ranges (e.g. `pos` is clamped to `[0, array.length]`). + * If `pos >= array.length`, no replacement occurs and the array is returned unchanged. + * + * NOTE: This function modifies the provided array in place. + */ + function replace( + uint256[] memory array, + uint256 pos, + uint256[] memory replacement + ) internal pure returns (uint256[] memory) { + return replace(array, pos, replacement, 0, replacement.length); + } + + /** + * @dev Replaces elements in `array` starting at `pos` with elements from `replacement` starting at `offset`. + * Copies at most `length` elements from `replacement` to `array`. + * + * Parameters are clamped to valid ranges (i.e. `pos` is clamped to `[0, array.length]`, `offset` is + * clamped to `[0, replacement.length]`, and `length` is clamped to `min(length, replacement.length - offset, + * array.length - pos)`). If `pos >= array.length` or `offset >= replacement.length`, no replacement occurs + * and the array is returned unchanged. + * + * NOTE: This function modifies the provided array in place. + */ + function replace( + uint256[] memory array, + uint256 pos, + uint256[] memory replacement, + uint256 offset, + uint256 length + ) internal pure returns (uint256[] memory) { + // sanitize + pos = Math.min(pos, array.length); + offset = Math.min(offset, replacement.length); + length = Math.min(length, Math.min(replacement.length - offset, array.length - pos)); + + // replace + assembly ("memory-safe") { + mcopy( + add(add(array, 0x20), mul(pos, 0x20)), + add(add(replacement, 0x20), mul(offset, 0x20)), + mul(length, 0x20) + ) + } + + return array; + } + /** * @dev Access an array in an "unsafe" way. Skips solidity "index-out-of-range" check. * @@ -681,7 +842,7 @@ library Arrays { /** * @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. + * WARNING: this does not clear elements if length is reduced, or initialize elements if length is increased. */ function unsafeSetLength(address[] storage array, uint256 len) internal { assembly ("memory-safe") { @@ -692,7 +853,7 @@ library Arrays { /** * @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. + * WARNING: this does not clear elements if length is reduced, or initialize elements if length is increased. */ function unsafeSetLength(bytes32[] storage array, uint256 len) internal { assembly ("memory-safe") { @@ -703,7 +864,7 @@ library Arrays { /** * @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. + * WARNING: this does not clear elements if length is reduced, or initialize elements if length is increased. */ function unsafeSetLength(uint256[] storage array, uint256 len) internal { assembly ("memory-safe") { @@ -714,7 +875,7 @@ library Arrays { /** * @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. + * WARNING: this does not clear elements if length is reduced, or initialize elements if length is increased. */ function unsafeSetLength(bytes[] storage array, uint256 len) internal { assembly ("memory-safe") { @@ -725,7 +886,7 @@ library Arrays { /** * @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. + * WARNING: this does not clear elements if length is reduced, or initialize elements if length is increased. */ function unsafeSetLength(string[] storage array, uint256 len) internal { assembly ("memory-safe") { diff --git a/dependencies/@openzeppelin-contracts-5.5.0/utils/Base58.sol b/dependencies/@openzeppelin-contracts-5.7.0/utils/Base58.sol similarity index 100% rename from dependencies/@openzeppelin-contracts-5.5.0/utils/Base58.sol rename to dependencies/@openzeppelin-contracts-5.7.0/utils/Base58.sol diff --git a/dependencies/@openzeppelin-contracts-5.5.0/utils/Base64.sol b/dependencies/@openzeppelin-contracts-5.7.0/utils/Base64.sol similarity index 98% rename from dependencies/@openzeppelin-contracts-5.5.0/utils/Base64.sol rename to dependencies/@openzeppelin-contracts-5.7.0/utils/Base64.sol index 7c665c8..02199c5 100644 --- a/dependencies/@openzeppelin-contracts-5.5.0/utils/Base64.sol +++ b/dependencies/@openzeppelin-contracts-5.7.0/utils/Base64.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -// OpenZeppelin Contracts (last updated v5.5.0) (utils/Base64.sol) +// OpenZeppelin Contracts (last updated v5.6.0) (utils/Base64.sol) pragma solidity ^0.8.20; @@ -33,7 +33,7 @@ library Base64 { * * * Supports padded and unpadded inputs. * * Supports both encoding ({encode} and {encodeURL}) seamlessly. - * * Does NOT revert if the input is not a valid Base64 string. + * * Reverts with {InvalidBase64Char} if the input contains an invalid character. */ function decode(string memory data) internal pure returns (bytes memory) { return _decode(bytes(data)); @@ -208,7 +208,7 @@ library Base64 { // slither-disable-next-line incorrect-shift if iszero(and(shl(d, 1), 0xffffffd0ffffffc47ff5)) { mstore(0, errorSelector) - mstore(4, add(d, 43)) + mstore(4, shl(248, add(d, 43))) revert(0, 0x24) } diff --git a/dependencies/@openzeppelin-contracts-5.7.0/utils/BlockHeader.sol b/dependencies/@openzeppelin-contracts-5.7.0/utils/BlockHeader.sol new file mode 100644 index 0000000..da1dde1 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.7.0/utils/BlockHeader.sol @@ -0,0 +1,312 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v5.7.0) (utils/BlockHeader.sol) + +pragma solidity ^0.8.26; + +import {SafeCast} from "./math/SafeCast.sol"; +import {Blockhash} from "./Blockhash.sol"; +import {Memory} from "./Memory.sol"; +import {RLP} from "./RLP.sol"; + +/// @dev Library for parsing and verifying RLP-encoded block headers. +library BlockHeader { + using RLP for *; + using SafeCast for *; + + /// @dev List of block header fields, in the order they are encoded in the block header RLP. + enum HeaderField { + ParentHash, // Since Frontier + OmmersHash, // Since Frontier + Coinbase, // Since Frontier + StateRoot, // Since Frontier + TransactionsRoot, // Since Frontier + ReceiptsRoot, // Since Frontier + LogsBloom, // Since Frontier + Difficulty, // Since Frontier + Number, // Since Frontier + GasLimit, // Since Frontier + GasUsed, // Since Frontier + Timestamp, // Since Frontier + ExtraData, // Since Frontier + PrevRandao, // Since Frontier (called MixHash before Paris) + Nonce, // Since Frontier + BaseFeePerGas, // Since London + WithdrawalsRoot, // Since Shanghai + BlobGasUsed, // Since Cancun + ExcessBlobGas, // Since Cancun + ParentBeaconBlockRoot, // Since Cancun + RequestsHash, // Since Prague + BlockAccessListHash // Since Amsterdam + } + + /// @dev Thrown when the provided block header RLP does not have the expected number of fields. + /// Happens if it corresponds to an older version of the EVM that doesn't include the field. + error FieldNotPresentInBlockHeader(HeaderField); + + /** + * @dev Verifies that the given block header RLP corresponds to a valid block header for the current chain. + * + * NOTE: Blocks older than 8191 blocks ago are not available through {Blockhash.blockHash} + */ + function verifyBlockHeader(bytes memory headerRLP) internal view returns (bool result) { + return Blockhash.blockHash(getNumber(headerRLP)) == keccak256(headerRLP); + } + + /** + * @dev Variant of {verifyBlockHeader} that takes a pre-parsed list of fields and a pre-computed + * header hash. + * + * NOTE: The caller must supply `headerHash == keccak256(rlp)`, where `rlp` is the RLP + * buffer that `fields` was parsed from; this overload only checks that `headerHash` is the + * canonical hash for the block number in `fields`. Use this when the hash was already computed + * to avoid a second `keccak256`. + */ + function verifyBlockHeader(Memory.Slice[] memory fields, bytes32 headerHash) internal view returns (bool) { + return Blockhash.blockHash(getNumber(fields)) == headerHash; + } + + /** + * @dev Decode the block header RLP into a list of field slices. Use this when reading multiple fields to avoid + * decoding the RLP list more than once. The returned slices reference the input buffer, so it must not be mutated. + */ + function parseHeader(bytes memory headerRLP) internal pure returns (Memory.Slice[] memory) { + return RLP.decodeList(headerRLP); + } + + /// @dev Extract the parent hash from the block header RLP. + function getParentHash(bytes memory headerRLP) internal pure returns (bytes32) { + return _getField(headerRLP, HeaderField.ParentHash).readBytes32(); + } + + /// @dev Extract the parent hash from pre-parsed header fields. + function getParentHash(Memory.Slice[] memory fields) internal pure returns (bytes32) { + return _getField(fields, HeaderField.ParentHash).readBytes32(); + } + + /// @dev Extract the ommers hash from the block header RLP. This is constant to keccak256(rlp([])) since EIP-3675 (Paris) + function getOmmersHash(bytes memory headerRLP) internal pure returns (bytes32) { + return _getField(headerRLP, HeaderField.OmmersHash).readBytes32(); + } + + /// @dev Extract the ommers hash from pre-parsed header fields. + function getOmmersHash(Memory.Slice[] memory fields) internal pure returns (bytes32) { + return _getField(fields, HeaderField.OmmersHash).readBytes32(); + } + + /// @dev Extract the coinbase (a.k.a. beneficiary or miner) address from the block header RLP. + function getCoinbase(bytes memory headerRLP) internal pure returns (address) { + return _getField(headerRLP, HeaderField.Coinbase).readAddress(); + } + + /// @dev Extract the coinbase from pre-parsed header fields. + function getCoinbase(Memory.Slice[] memory fields) internal pure returns (address) { + return _getField(fields, HeaderField.Coinbase).readAddress(); + } + + /// @dev Extract the state root from the block header RLP. + function getStateRoot(bytes memory headerRLP) internal pure returns (bytes32) { + return _getField(headerRLP, HeaderField.StateRoot).readBytes32(); + } + + /// @dev Extract the state root from pre-parsed header fields. + function getStateRoot(Memory.Slice[] memory fields) internal pure returns (bytes32) { + return _getField(fields, HeaderField.StateRoot).readBytes32(); + } + + /// @dev Extract the transactions root from the block header RLP. + function getTransactionsRoot(bytes memory headerRLP) internal pure returns (bytes32) { + return _getField(headerRLP, HeaderField.TransactionsRoot).readBytes32(); + } + + /// @dev Extract the transactions root from pre-parsed header fields. + function getTransactionsRoot(Memory.Slice[] memory fields) internal pure returns (bytes32) { + return _getField(fields, HeaderField.TransactionsRoot).readBytes32(); + } + + /// @dev Extract the receipts root from the block header RLP. + function getReceiptsRoot(bytes memory headerRLP) internal pure returns (bytes32) { + return _getField(headerRLP, HeaderField.ReceiptsRoot).readBytes32(); + } + + /// @dev Extract the receipts root from pre-parsed header fields. + function getReceiptsRoot(Memory.Slice[] memory fields) internal pure returns (bytes32) { + return _getField(fields, HeaderField.ReceiptsRoot).readBytes32(); + } + + /// @dev Extract the logs bloom from the block header RLP. + function getLogsBloom(bytes memory headerRLP) internal pure returns (bytes memory) { + return _getField(headerRLP, HeaderField.LogsBloom).readBytes(); + } + + /// @dev Extract the logs bloom from pre-parsed header fields. + function getLogsBloom(Memory.Slice[] memory fields) internal pure returns (bytes memory) { + return _getField(fields, HeaderField.LogsBloom).readBytes(); + } + + /// @dev Extract the difficulty from the block header RLP. This is constant to 0 since EIP-3675 (Paris) + function getDifficulty(bytes memory headerRLP) internal pure returns (uint256) { + return _getField(headerRLP, HeaderField.Difficulty).readUint256(); + } + + /// @dev Extract the difficulty from pre-parsed header fields. + function getDifficulty(Memory.Slice[] memory fields) internal pure returns (uint256) { + return _getField(fields, HeaderField.Difficulty).readUint256(); + } + + /// @dev Extract the block number from the block header RLP. + function getNumber(bytes memory headerRLP) internal pure returns (uint256) { + return _getField(headerRLP, HeaderField.Number).readUint256(); + } + + /// @dev Extract the block number from pre-parsed header fields. + function getNumber(Memory.Slice[] memory fields) internal pure returns (uint256) { + return _getField(fields, HeaderField.Number).readUint256(); + } + + /// @dev Extract the gas used from the block header RLP. + function getGasUsed(bytes memory headerRLP) internal pure returns (uint256) { + return _getField(headerRLP, HeaderField.GasUsed).readUint256(); + } + + /// @dev Extract the gas used from pre-parsed header fields. + function getGasUsed(Memory.Slice[] memory fields) internal pure returns (uint256) { + return _getField(fields, HeaderField.GasUsed).readUint256(); + } + + /// @dev Extract the gas limit from the block header RLP. + function getGasLimit(bytes memory headerRLP) internal pure returns (uint256) { + return _getField(headerRLP, HeaderField.GasLimit).readUint256(); + } + + /// @dev Extract the gas limit from pre-parsed header fields. + function getGasLimit(Memory.Slice[] memory fields) internal pure returns (uint256) { + return _getField(fields, HeaderField.GasLimit).readUint256(); + } + + /// @dev Extract the timestamp from the block header RLP. + function getTimestamp(bytes memory headerRLP) internal pure returns (uint256) { + return _getField(headerRLP, HeaderField.Timestamp).readUint256(); + } + + /// @dev Extract the timestamp from pre-parsed header fields. + function getTimestamp(Memory.Slice[] memory fields) internal pure returns (uint256) { + return _getField(fields, HeaderField.Timestamp).readUint256(); + } + + /// @dev Extract the extra data from the block header RLP. + function getExtraData(bytes memory headerRLP) internal pure returns (bytes memory) { + return _getField(headerRLP, HeaderField.ExtraData).readBytes(); + } + + /// @dev Extract the extra data from pre-parsed header fields. + function getExtraData(Memory.Slice[] memory fields) internal pure returns (bytes memory) { + return _getField(fields, HeaderField.ExtraData).readBytes(); + } + + /// @dev Extract the prevRandao (a.k.a. mixHash before Paris) from the block header RLP. + function getPrevRandao(bytes memory headerRLP) internal pure returns (bytes32) { + return _getField(headerRLP, HeaderField.PrevRandao).readBytes32(); + } + + /// @dev Extract the prevRandao from pre-parsed header fields. + function getPrevRandao(Memory.Slice[] memory fields) internal pure returns (bytes32) { + return _getField(fields, HeaderField.PrevRandao).readBytes32(); + } + + /// @dev Extract the nonce from the block header RLP. This is constant to 0 since EIP-3675 (Paris) + function getNonce(bytes memory headerRLP) internal pure returns (bytes8) { + return bytes8(_getField(headerRLP, HeaderField.Nonce).readUint256().toUint64()); + } + + /// @dev Extract the nonce from pre-parsed header fields. + function getNonce(Memory.Slice[] memory fields) internal pure returns (bytes8) { + return bytes8(_getField(fields, HeaderField.Nonce).readUint256().toUint64()); + } + + /// @dev Extract the base fee per gas from the block header RLP. This was introduced in London. + function getBaseFeePerGas(bytes memory headerRLP) internal pure returns (uint256) { + return _getField(headerRLP, HeaderField.BaseFeePerGas).readUint256(); + } + + /// @dev Extract the base fee per gas from pre-parsed header fields. + function getBaseFeePerGas(Memory.Slice[] memory fields) internal pure returns (uint256) { + return _getField(fields, HeaderField.BaseFeePerGas).readUint256(); + } + + /// @dev Extract the withdrawals root from the block header RLP. This was introduced in Shanghai. + function getWithdrawalsRoot(bytes memory headerRLP) internal pure returns (bytes32) { + return _getField(headerRLP, HeaderField.WithdrawalsRoot).readBytes32(); + } + + /// @dev Extract the withdrawals root from pre-parsed header fields. + function getWithdrawalsRoot(Memory.Slice[] memory fields) internal pure returns (bytes32) { + return _getField(fields, HeaderField.WithdrawalsRoot).readBytes32(); + } + + /// @dev Extract the blob gas used from the block header RLP. This was introduced in Cancun. + function getBlobGasUsed(bytes memory headerRLP) internal pure returns (uint64) { + return _getField(headerRLP, HeaderField.BlobGasUsed).readUint256().toUint64(); + } + + /// @dev Extract the blob gas used from pre-parsed header fields. + function getBlobGasUsed(Memory.Slice[] memory fields) internal pure returns (uint64) { + return _getField(fields, HeaderField.BlobGasUsed).readUint256().toUint64(); + } + + /// @dev Extract the excess blob gas from the block header RLP. This was introduced in Cancun. + function getExcessBlobGas(bytes memory headerRLP) internal pure returns (uint64) { + return _getField(headerRLP, HeaderField.ExcessBlobGas).readUint256().toUint64(); + } + + /// @dev Extract the excess blob gas from pre-parsed header fields. + function getExcessBlobGas(Memory.Slice[] memory fields) internal pure returns (uint64) { + return _getField(fields, HeaderField.ExcessBlobGas).readUint256().toUint64(); + } + + /// @dev Extract the parent beacon block root from the block header RLP. This was introduced in Cancun. + function getParentBeaconBlockRoot(bytes memory headerRLP) internal pure returns (bytes32) { + return _getField(headerRLP, HeaderField.ParentBeaconBlockRoot).readBytes32(); + } + + /// @dev Extract the parent beacon block root from pre-parsed header fields. + function getParentBeaconBlockRoot(Memory.Slice[] memory fields) internal pure returns (bytes32) { + return _getField(fields, HeaderField.ParentBeaconBlockRoot).readBytes32(); + } + + /// @dev Extract the requests hash from the block header RLP. This was introduced in Prague. + function getRequestsHash(bytes memory headerRLP) internal pure returns (bytes32) { + return _getField(headerRLP, HeaderField.RequestsHash).readBytes32(); + } + + /// @dev Extract the requests hash from pre-parsed header fields. + function getRequestsHash(Memory.Slice[] memory fields) internal pure returns (bytes32) { + return _getField(fields, HeaderField.RequestsHash).readBytes32(); + } + + /// @dev Extract the block access list hash from the block header RLP. This will be introduced in Amsterdam. + function getBlockAccessListHash(bytes memory headerRLP) internal pure returns (bytes32) { + return _getField(headerRLP, HeaderField.BlockAccessListHash).readBytes32(); + } + + /// @dev Extract the block access list hash from pre-parsed header fields. + function getBlockAccessListHash(Memory.Slice[] memory fields) internal pure returns (bytes32) { + return _getField(fields, HeaderField.BlockAccessListHash).readBytes32(); + } + + /** + * @dev Parse the header, extract a single field slice, then release the array memory. The returned slice still + * references the original `headerRLP` buffer, so it remains valid after the FMP reset. Callers that read multiple + * fields should use {parseHeader} once and call the {Memory-Slice} overloads instead. + */ + function _getField(bytes memory headerRLP, HeaderField field) private pure returns (Memory.Slice result) { + Memory.Pointer fmp = Memory.getFreeMemoryPointer(); + result = _getField(parseHeader(headerRLP), field); + Memory.unsafeSetFreeMemoryPointer(fmp); + } + + /// @dev Look up a field slice by its position, reverting if the header is too old to include it. + function _getField(Memory.Slice[] memory fields, HeaderField field) private pure returns (Memory.Slice) { + require(uint8(field) < fields.length, FieldNotPresentInBlockHeader(field)); + return fields[uint8(field)]; + } +} diff --git a/dependencies/@openzeppelin-contracts-5.5.0/utils/Blockhash.sol b/dependencies/@openzeppelin-contracts-5.7.0/utils/Blockhash.sol similarity index 100% rename from dependencies/@openzeppelin-contracts-5.5.0/utils/Blockhash.sol rename to dependencies/@openzeppelin-contracts-5.7.0/utils/Blockhash.sol diff --git a/dependencies/@openzeppelin-contracts-5.5.0/utils/Bytes.sol b/dependencies/@openzeppelin-contracts-5.7.0/utils/Bytes.sol similarity index 71% rename from dependencies/@openzeppelin-contracts-5.5.0/utils/Bytes.sol rename to dependencies/@openzeppelin-contracts-5.7.0/utils/Bytes.sol index e1c3f80..61f85cd 100644 --- a/dependencies/@openzeppelin-contracts-5.5.0/utils/Bytes.sol +++ b/dependencies/@openzeppelin-contracts-5.7.0/utils/Bytes.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -// OpenZeppelin Contracts (last updated v5.5.0) (utils/Bytes.sol) +// OpenZeppelin Contracts (last updated v5.7.0) (utils/Bytes.sol) pragma solidity ^0.8.24; @@ -98,28 +98,28 @@ library Bytes { } /** - * @dev Moves the content of `buffer`, from `start` (included) to the end of `buffer` to the start of that buffer. + * @dev Moves the content of `buffer`, from `start` (included) to the end of `buffer` to the start of that buffer, + * and shrinks the buffer length accordingly, effectively overriding the content of buffer with buffer[start:]. * * NOTE: This function modifies the provided buffer in place. If you need to preserve the original buffer, use {slice} instead - * NOTE: replicates the behavior of https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/splice[Javascript's `Array.splice`] */ function splice(bytes memory buffer, uint256 start) internal pure returns (bytes memory) { return splice(buffer, start, buffer.length); } /** - * @dev Moves the content of `buffer`, from `start` (included) to end (excluded) to the start of that buffer. The - * `end` argument is truncated to the length of the `buffer`. + * @dev Moves the content of `buffer`, from `start` (included) to `end` (excluded) to the start of that buffer, + * and shrinks the buffer length accordingly, effectively overriding the content of buffer with buffer[start:end]. + * The `end` argument is truncated to the length of the `buffer`. * * NOTE: This function modifies the provided buffer in place. If you need to preserve the original buffer, use {slice} instead - * NOTE: replicates the behavior of https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/splice[Javascript's `Array.splice`] */ function splice(bytes memory buffer, uint256 start, uint256 end) internal pure returns (bytes memory) { // sanitize end = Math.min(end, buffer.length); start = Math.min(start, end); - // allocate and copy + // move and resize assembly ("memory-safe") { mcopy(add(buffer, 0x20), add(add(buffer, 0x20), start), sub(end, start)) mstore(buffer, sub(end, start)) @@ -128,6 +128,49 @@ library Bytes { return buffer; } + /** + * @dev Replaces bytes in `buffer` starting at `pos` with all bytes from `replacement`. + * + * Parameters are clamped to valid ranges (i.e. `pos` is clamped to `[0, buffer.length]`). + * If `pos >= buffer.length`, no replacement occurs and the buffer is returned unchanged. + * + * NOTE: This function modifies the provided buffer in place. + */ + function replace(bytes memory buffer, uint256 pos, bytes memory replacement) internal pure returns (bytes memory) { + return replace(buffer, pos, replacement, 0, replacement.length); + } + + /** + * @dev Replaces bytes in `buffer` starting at `pos` with bytes from `replacement` starting at `offset`. + * Copies at most `length` bytes from `replacement` to `buffer`. + * + * Parameters are clamped to valid ranges (i.e. `pos` is clamped to `[0, buffer.length]`, `offset` is + * clamped to `[0, replacement.length]`, and `length` is clamped to `min(length, replacement.length - offset, + * buffer.length - pos))`. If `pos >= buffer.length` or `offset >= replacement.length`, no replacement occurs + * and the buffer is returned unchanged. + * + * NOTE: This function modifies the provided buffer in place. + */ + function replace( + bytes memory buffer, + uint256 pos, + bytes memory replacement, + uint256 offset, + uint256 length + ) internal pure returns (bytes memory) { + // sanitize + pos = Math.min(pos, buffer.length); + offset = Math.min(offset, replacement.length); + length = Math.min(length, Math.min(replacement.length - offset, buffer.length - pos)); + + // replace + assembly ("memory-safe") { + mcopy(add(add(buffer, 0x20), pos), add(add(replacement, 0x20), offset), length) + } + + return buffer; + } + /** * @dev Concatenate an array of bytes into a single bytes object. * @@ -159,6 +202,48 @@ library Bytes { return result; } + /** + * @dev Split each byte in `input` into two nibbles (4 bits each) + * + * Example: hex"01234567" → hex"0001020304050607" + */ + function toNibbles(bytes memory input) internal pure returns (bytes memory output) { + assembly ("memory-safe") { + let length := mload(input) + output := mload(0x40) + mstore(0x40, add(add(output, 0x20), mul(length, 2))) + mstore(output, mul(length, 2)) + for { + let i := 0 + } lt(i, length) { + i := add(i, 0x10) + } { + let chunk := shr(128, mload(add(add(input, 0x20), i))) + chunk := and( + 0x0000000000000000ffffffffffffffff0000000000000000ffffffffffffffff, + or(shl(64, chunk), chunk) + ) + chunk := and( + 0x00000000ffffffff00000000ffffffff00000000ffffffff00000000ffffffff, + or(shl(32, chunk), chunk) + ) + chunk := and( + 0x0000ffff0000ffff0000ffff0000ffff0000ffff0000ffff0000ffff0000ffff, + or(shl(16, chunk), chunk) + ) + chunk := and( + 0x00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff, + or(shl(8, chunk), chunk) + ) + chunk := and( + 0x0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f, + or(shl(4, chunk), chunk) + ) + mstore(add(add(output, 0x20), mul(i, 2)), chunk) + } + } + } + /** * @dev Returns true if the two byte buffers are equal. */ @@ -189,14 +274,11 @@ library Bytes { /// @dev Same as {reverseBytes32} but optimized for 128-bit values. function reverseBytes16(bytes16 value) internal pure returns (bytes16) { value = // swap bytes - ((value & 0xFF00FF00FF00FF00FF00FF00FF00FF00) >> 8) | - ((value & 0x00FF00FF00FF00FF00FF00FF00FF00FF) << 8); + ((value & 0xFF00FF00FF00FF00FF00FF00FF00FF00) >> 8) | ((value & 0x00FF00FF00FF00FF00FF00FF00FF00FF) << 8); value = // swap 2-byte long pairs - ((value & 0xFFFF0000FFFF0000FFFF0000FFFF0000) >> 16) | - ((value & 0x0000FFFF0000FFFF0000FFFF0000FFFF) << 16); + ((value & 0xFFFF0000FFFF0000FFFF0000FFFF0000) >> 16) | ((value & 0x0000FFFF0000FFFF0000FFFF0000FFFF) << 16); value = // swap 4-byte long pairs - ((value & 0xFFFFFFFF00000000FFFFFFFF00000000) >> 32) | - ((value & 0x00000000FFFFFFFF00000000FFFFFFFF) << 32); + ((value & 0xFFFFFFFF00000000FFFFFFFF00000000) >> 32) | ((value & 0x00000000FFFFFFFF00000000FFFFFFFF) << 32); return (value >> 64) | (value << 64); // swap 8-byte long pairs } diff --git a/dependencies/@openzeppelin-contracts-5.5.0/utils/CAIP10.sol b/dependencies/@openzeppelin-contracts-5.7.0/utils/CAIP10.sol similarity index 100% rename from dependencies/@openzeppelin-contracts-5.5.0/utils/CAIP10.sol rename to dependencies/@openzeppelin-contracts-5.7.0/utils/CAIP10.sol diff --git a/dependencies/@openzeppelin-contracts-5.5.0/utils/CAIP2.sol b/dependencies/@openzeppelin-contracts-5.7.0/utils/CAIP2.sol similarity index 100% rename from dependencies/@openzeppelin-contracts-5.5.0/utils/CAIP2.sol rename to dependencies/@openzeppelin-contracts-5.7.0/utils/CAIP2.sol diff --git a/dependencies/@openzeppelin-contracts-5.5.0/utils/Calldata.sol b/dependencies/@openzeppelin-contracts-5.7.0/utils/Calldata.sol similarity index 100% rename from dependencies/@openzeppelin-contracts-5.5.0/utils/Calldata.sol rename to dependencies/@openzeppelin-contracts-5.7.0/utils/Calldata.sol diff --git a/dependencies/@openzeppelin-contracts-5.5.0/utils/Comparators.sol b/dependencies/@openzeppelin-contracts-5.7.0/utils/Comparators.sol similarity index 100% rename from dependencies/@openzeppelin-contracts-5.5.0/utils/Comparators.sol rename to dependencies/@openzeppelin-contracts-5.7.0/utils/Comparators.sol diff --git a/dependencies/@openzeppelin-contracts-5.5.0/utils/Context.sol b/dependencies/@openzeppelin-contracts-5.7.0/utils/Context.sol similarity index 100% rename from dependencies/@openzeppelin-contracts-5.5.0/utils/Context.sol rename to dependencies/@openzeppelin-contracts-5.7.0/utils/Context.sol diff --git a/dependencies/@openzeppelin-contracts-5.5.0/utils/Create2.sol b/dependencies/@openzeppelin-contracts-5.7.0/utils/Create2.sol similarity index 100% rename from dependencies/@openzeppelin-contracts-5.5.0/utils/Create2.sol rename to dependencies/@openzeppelin-contracts-5.7.0/utils/Create2.sol diff --git a/dependencies/@openzeppelin-contracts-5.7.0/utils/Create3.sol b/dependencies/@openzeppelin-contracts-5.7.0/utils/Create3.sol new file mode 100644 index 0000000..a7ef995 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.7.0/utils/Create3.sol @@ -0,0 +1,133 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v5.7.0) (utils/Create3.sol) + +pragma solidity ^0.8.20; + +import {Create2} from "./Create2.sol"; +import {Errors} from "./Errors.sol"; +import {LowLevelCall} from "./LowLevelCall.sol"; + +/** + * @dev Helper to deploy contracts using the `CREATE3` approach. + * `CREATE3` combines both `CREATE2` and `CREATE` opcodes to deploy arbitrary bytecode at an address that only depends + * on the provided salt and the address of the contract using this library. At a high level, it behaves like a `CREATE2` + * operation that would not use the bytecodehash to generate the contract address. + * + * CREATE3 can be used to compute in advance the address where a smart contract will be deployed, even if the bytecode + * is subject to change. + * + * NOTE: To get the same deployment address on multiple chains, the deployer contract must live at the same address on + * each chain. + * + * See {Create2} for counterfactual deployments that include the bytecodehash in the computation of the address. + */ +library Create3 { + /** + * ===================================[ PROXY CODE ]=================================== + * Offset | Opcode | Mnemonic | Stack | Memory + * -------|-------------|------------------|-----------------|------------------------- + * 0x00 | 36 | CALLDATASIZE | cds | + * 0x01 | 5F | PUSH0 | 0 cds | + * 0x02 | 5F | PUSH0 | 0 0 cds | + * 0x03 | 37 | CALLDATACOPY | | [0..cds): calldata + * 0x04 | 36 | CALLDATASIZE | cds | [0..cds): calldata + * 0x05 | 5F | PUSH0 | 0 cds | [0..cds): calldata + * 0x06 | 34 | CALLVALUE | value 0 cds | [0..cds): calldata + * 0x07 | f0 | CREATE | addr | [0..cds): calldata + * 0x08 | 6012 | PUSH1 0x12 | 0x12 addr | + * 0x0A | 57 | JUMPI | | + * 0x0B | 3D | RETURNDATASIZE | rds | + * 0x0C | 5F | PUSH0 | 0 rds | + * 0x0D | 5F | PUSH0 | 0 0 rds | + * 0x0E | 3E | RETURNDATACOPY | | [0..rds): returndata + * 0x0F | 3D | RETURNDATASIZE | rds | [0..rds): returndata + * 0x10 | 5F | PUSH0 | 0 rds | [0..rds): returndata + * 0x11 | FD | REVERT | | + * 0x12 | 5b | JUMPDEST | | + * 0x13 | 00 | STOP | | + * + * ================================[ DEPLOYMENT CODE ]================================= + * Offset | Opcode | Mnemonic | Stack | Memory + * -------|-------------|------------------|-----------------|------------------------- + * 0x00 | 73 bytecode | PUSH20 bytecode | bytecode | + * 0x15 | 5F | PUSH0 | 0 bytecode | + * 0x16 | 52 | MSTORE | | [0x0C..0x20): bytecode + * 0x17 | 6014 | PUSH1 0x14 | 0x14 | [0x0C..0x20): bytecode + * 0x19 | 600C | PUSH1 0x0C | 0x0C 0x14 | [0x0C..0x20): bytecode + * 0x1B | f3 | RETURN | | [0x0C..0x20): bytecode + */ + /// @dev The proxy initialization code. + bytes28 private constant PROXY_INITCODE = 0x73365f5f37365f34f06012573d5f5f3e3d5ffd5b005f526014600cf3; + + /// @dev Hash of the `PROXY_INITCODE`. + /// Equivalent to `keccak256(hex"73365f5f37365f34f06012573d5f5f3e3d5ffd5b005f526014600cf3")`. + bytes32 internal constant PROXY_INITCODE_HASH = 0x57a34f6e879358dd76825d6700df87013ad6a3fb43c0d0c602f70a8772c153bd; + + /** + * @dev There's no code to deploy. + */ + error Create3EmptyBytecode(); + + /** + * @dev Deploys a contract using the `CREATE3` mechanism. The address where the contract + * will be deployed can be known in advance via {computeAddress}, and only depends on the salt. + * The bytecode that is deployed DOES NOT affect the location at which it is deployed. + * + * The bytecode for a contract can be obtained from Solidity with + * `type(contractName).creationCode`. + * + * Requirements: + * + * - `bytecode` must not be empty. + * - `salt` must not have been used 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) { + if (address(this).balance < amount) { + revert Errors.InsufficientBalance(address(this).balance, amount); + } + if (bytecode.length == 0) { + revert Create3EmptyBytecode(); + } + // This fails if the salt was already used. Will never return address(0). + address proxy = Create2.deploy(0, salt, abi.encodePacked(PROXY_INITCODE)); + // Perform the actual deployment (create on the proxy with nonce 1). + bool success = LowLevelCall.callNoReturn(proxy, amount, bytecode); + if (!success) { + if (LowLevelCall.returnDataSize() == 0) { + revert Errors.FailedDeployment(); + } else { + LowLevelCall.bubbleRevert(); + } + } + + return _computeCreateAddress(proxy); + } + + /** + * @dev Returns the address where a contract will be stored if deployed via {deploy}. Any change in the + * `salt` will result in a new destination address. + */ + function computeAddress(bytes32 salt) internal view returns (address) { + return computeAddress(salt, 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, address deployer) internal pure returns (address) { + return _computeCreateAddress(Create2.computeAddress(salt, PROXY_INITCODE_HASH, deployer)); + } + + /// @dev Compute the address of the first contract that `creator` would deploy using CREATE (nonce 1). + function _computeCreateAddress(address creator) private pure returns (address addr) { + assembly ("memory-safe") { + mstore(0x15, 0x01) + mstore(0x14, creator) + mstore(0x00, 0xd694) + addr := and(keccak256(0x1e, 0x17), 0xffffffffffffffffffffffffffffffffffffffff) + } + } +} diff --git a/dependencies/@openzeppelin-contracts-5.7.0/utils/ERC6372Utils.sol b/dependencies/@openzeppelin-contracts-5.7.0/utils/ERC6372Utils.sol new file mode 100644 index 0000000..a02d3d8 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.7.0/utils/ERC6372Utils.sol @@ -0,0 +1,53 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v5.7.0) (utils/ERC6372Utils.sol) + +pragma solidity ^0.8.24; + +import {IERC6372} from "../interfaces/IERC6372.sol"; +import {Time} from "./types/Time.sol"; + +/** + * @dev Utility library for the ERC-6372 clock standard. + */ +library ERC6372Utils { + /// @dev The clock was incorrectly modified. + error ERC6372InconsistentClock(); + + /// @dev Variant of {blockNumberClockMode-uint48-} that checks against an IERC6372 instance + function blockNumberClockMode(IERC6372 instance) internal view returns (string memory) { + return blockNumberClockMode(instance.clock()); + } + + /// @dev Variant of {blockNumberClockMode-uint48-} that checks against the clock function. + function blockNumberClockMode(function() view returns (uint48) clock) internal view returns (string memory) { + return blockNumberClockMode(clock()); + } + + /// @dev Block number clock mode. Checks that the current `clock` was not modified. + function blockNumberClockMode(uint48 clock) internal view returns (string memory) { + // Check that the clock was not modified + if (clock != Time.blockNumber()) { + revert ERC6372InconsistentClock(); + } + return "mode=blocknumber&from=default"; + } + + /// @dev Variant of {timestampClockMode-uint48-} that checks against an IERC6372 instance + function timestampClockMode(IERC6372 instance) internal view returns (string memory) { + return timestampClockMode(instance.clock()); + } + + /// @dev Variant of {timestampClockMode-uint48-} that checks against the clock function. + function timestampClockMode(function() view returns (uint48) clock) internal view returns (string memory) { + return timestampClockMode(clock()); + } + + /// @dev Timestamp clock mode. Checks that the current `clock` was not modified. + function timestampClockMode(uint48 clock) internal view returns (string memory) { + // Check that the clock was not modified + if (clock != Time.timestamp()) { + revert ERC6372InconsistentClock(); + } + return "mode=timestamp"; + } +} diff --git a/dependencies/@openzeppelin-contracts-5.5.0/utils/Errors.sol b/dependencies/@openzeppelin-contracts-5.7.0/utils/Errors.sol similarity index 100% rename from dependencies/@openzeppelin-contracts-5.5.0/utils/Errors.sol rename to dependencies/@openzeppelin-contracts-5.7.0/utils/Errors.sol diff --git a/dependencies/@openzeppelin-contracts-5.5.0/utils/LowLevelCall.sol b/dependencies/@openzeppelin-contracts-5.7.0/utils/LowLevelCall.sol similarity index 92% rename from dependencies/@openzeppelin-contracts-5.5.0/utils/LowLevelCall.sol rename to dependencies/@openzeppelin-contracts-5.7.0/utils/LowLevelCall.sol index 0627693..f6aed90 100644 --- a/dependencies/@openzeppelin-contracts-5.5.0/utils/LowLevelCall.sol +++ b/dependencies/@openzeppelin-contracts-5.7.0/utils/LowLevelCall.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -// OpenZeppelin Contracts (last updated v5.5.0) (utils/LowLevelCall.sol) +// OpenZeppelin Contracts (last updated v5.6.0) (utils/LowLevelCall.sol) pragma solidity ^0.8.20; @@ -15,7 +15,7 @@ library LowLevelCall { return callNoReturn(target, 0, data); } - /// @dev Same as {callNoReturn}, but allows to specify the value to be sent in the call. + /// @dev Same as {callNoReturn-address-bytes}, but allows specifying the value to be sent in the call. function callNoReturn(address target, uint256 value, bytes memory data) internal returns (bool success) { assembly ("memory-safe") { success := call(gas(), target, value, add(data, 0x20), mload(data), 0x00, 0x00) @@ -23,7 +23,7 @@ library LowLevelCall { } /// @dev Performs a Solidity function call using a low level `call` and returns the first 64 bytes of the result - /// in the scratch space of memory. Useful for functions that return a tuple of single-word values. + /// in the scratch space of memory. Useful for functions that return a tuple with two single-word values. /// /// WARNING: Do not assume that the results are zero if `success` is false. Memory can be already allocated /// and this function doesn't zero it out. @@ -34,7 +34,7 @@ library LowLevelCall { return callReturn64Bytes(target, 0, data); } - /// @dev Same as {callReturnBytes32Pair}, but allows to specify the value to be sent in the call. + /// @dev Same as {callReturn64Bytes-address-bytes}, but allows specifying the value to be sent in the call. function callReturn64Bytes( address target, uint256 value, @@ -55,7 +55,7 @@ library LowLevelCall { } /// @dev Performs a Solidity function call using a low level `staticcall` and returns the first 64 bytes of the result - /// in the scratch space of memory. Useful for functions that return a tuple of single-word values. + /// in the scratch space of memory. Useful for functions that return a tuple with two single-word values. /// /// WARNING: Do not assume that the results are zero if `success` is false. Memory can be already allocated /// and this function doesn't zero it out. @@ -78,7 +78,7 @@ library LowLevelCall { } /// @dev Performs a Solidity function call using a low level `delegatecall` and returns the first 64 bytes of the result - /// in the scratch space of memory. Useful for functions that return a tuple of single-word values. + /// in the scratch space of memory. Useful for functions that return a tuple with two single-word values. /// /// WARNING: Do not assume that the results are zero if `success` is false. Memory can be already allocated /// and this function doesn't zero it out. diff --git a/dependencies/@openzeppelin-contracts-5.5.0/utils/Memory.sol b/dependencies/@openzeppelin-contracts-5.7.0/utils/Memory.sol similarity index 72% rename from dependencies/@openzeppelin-contracts-5.5.0/utils/Memory.sol rename to dependencies/@openzeppelin-contracts-5.7.0/utils/Memory.sol index 378d247..251d394 100644 --- a/dependencies/@openzeppelin-contracts-5.5.0/utils/Memory.sol +++ b/dependencies/@openzeppelin-contracts-5.7.0/utils/Memory.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -// OpenZeppelin Contracts (last updated v5.5.0) (utils/Memory.sol) +// OpenZeppelin Contracts (last updated v5.7.0) (utils/Memory.sol) pragma solidity ^0.8.24; @@ -30,24 +30,18 @@ library Memory { /** * @dev Sets the free `Pointer` to a specific value. * + * The solidity memory layout requires that the FMP is never set to a value lower than 0x80. Setting the + * FMP to a value lower than 0x80 may cause unexpected behavior. Deallocating all memory can be achieved by + * setting the FMP to 0x80. + * * WARNING: Everything after the pointer may be overwritten. **/ - function setFreeMemoryPointer(Pointer ptr) internal pure { + function unsafeSetFreeMemoryPointer(Pointer ptr) internal pure { assembly ("memory-safe") { mstore(0x40, ptr) } } - /// @dev `Pointer` to `bytes32`. Expects a pointer to a properly ABI-encoded `bytes` object. - function asBytes32(Pointer ptr) internal pure returns (bytes32) { - return Pointer.unwrap(ptr); - } - - /// @dev `bytes32` to `Pointer`. Expects a pointer to a properly ABI-encoded `bytes` object. - function asPointer(bytes32 value) internal pure returns (Pointer) { - return Pointer.wrap(value); - } - /// @dev Move a pointer forward by a given offset. function forward(Pointer ptr, uint256 offset) internal pure returns (Pointer) { return Pointer.wrap(bytes32(uint256(Pointer.unwrap(ptr)) + offset)); @@ -74,13 +68,13 @@ library Memory { } } - /// @dev Offset a memory slice (equivalent to self[start:] for calldata slices) + /// @dev Offset a memory slice (equivalent to self[offset:] for calldata slices) function slice(Slice self, uint256 offset) internal pure returns (Slice) { if (offset > length(self)) Panic.panic(Panic.ARRAY_OUT_OF_BOUNDS); return _asSlice(length(self) - offset, forward(_pointer(self), offset)); } - /// @dev Offset and cut a Slice (equivalent to self[start:start+length] for calldata slices) + /// @dev Offset and cut a Slice (equivalent to self[offset:offset+len] for calldata slices) function slice(Slice self, uint256 offset, uint256 len) internal pure returns (Slice) { if (offset + len > length(self)) Panic.panic(Panic.ARRAY_OUT_OF_BOUNDS); return _asSlice(len, forward(_pointer(self), offset)); @@ -103,7 +97,7 @@ library Memory { /// @dev Extract the data corresponding to a Slice (allocate new memory) function toBytes(Slice self) internal pure returns (bytes memory result) { uint256 len = length(self); - Memory.Pointer ptr = _pointer(self); + Pointer ptr = _pointer(self); assembly ("memory-safe") { result := mload(0x40) mstore(result, len) @@ -112,6 +106,28 @@ library Memory { } } + /// @dev Returns true if the two slices contain the same data. + function equal(Slice a, Slice b) internal pure returns (bool result) { + uint256 len = length(a); + if (len == length(b)) { + Memory.Pointer ptrA = _pointer(a); + Memory.Pointer ptrB = _pointer(b); + assembly ("memory-safe") { + result := eq(keccak256(ptrA, len), keccak256(ptrB, len)) + } + } + // else returns false (default value) + } + + /// @dev Returns true if the memory occupied by the slice is reserved (i.e. before the free memory pointer) + function isReserved(Slice self) internal pure returns (bool result) { + Memory.Pointer fmp = getFreeMemoryPointer(); + Memory.Pointer end = forward(_pointer(self), length(self)); + assembly ("memory-safe") { + result := iszero(lt(fmp, end)) // end <= fmp + } + } + /** * @dev Private helper: create a slice from raw values (length and pointer) * @@ -120,14 +136,14 @@ library Memory { * (`slice(Slice,uint256)` and `slice(Slice,uint256, uint256)`) should not cause this issue if the parent slice is * correct. */ - function _asSlice(uint256 len, Memory.Pointer ptr) private pure returns (Slice result) { + function _asSlice(uint256 len, Pointer ptr) private pure returns (Slice result) { assembly ("memory-safe") { result := or(shl(128, len), ptr) } } /// @dev Returns the memory location of a given slice (equiv to self.offset for calldata slices) - function _pointer(Slice self) private pure returns (Memory.Pointer result) { + function _pointer(Slice self) private pure returns (Pointer result) { assembly ("memory-safe") { result := and(self, shr(128, not(0))) } diff --git a/dependencies/@openzeppelin-contracts-5.5.0/utils/Multicall.sol b/dependencies/@openzeppelin-contracts-5.7.0/utils/Multicall.sol similarity index 100% rename from dependencies/@openzeppelin-contracts-5.5.0/utils/Multicall.sol rename to dependencies/@openzeppelin-contracts-5.7.0/utils/Multicall.sol diff --git a/dependencies/@openzeppelin-contracts-5.5.0/utils/Nonces.sol b/dependencies/@openzeppelin-contracts-5.7.0/utils/Nonces.sol similarity index 95% rename from dependencies/@openzeppelin-contracts-5.5.0/utils/Nonces.sol rename to dependencies/@openzeppelin-contracts-5.7.0/utils/Nonces.sol index 37451ff..deeacb1 100644 --- a/dependencies/@openzeppelin-contracts-5.5.0/utils/Nonces.sol +++ b/dependencies/@openzeppelin-contracts-5.7.0/utils/Nonces.sol @@ -1,5 +1,6 @@ // SPDX-License-Identifier: MIT -// OpenZeppelin Contracts (last updated v5.0.0) (utils/Nonces.sol) +// OpenZeppelin Contracts (last updated v5.7.0) (utils/Nonces.sol) + pragma solidity ^0.8.20; /** diff --git a/dependencies/@openzeppelin-contracts-5.5.0/utils/NoncesKeyed.sol b/dependencies/@openzeppelin-contracts-5.7.0/utils/NoncesKeyed.sol similarity index 93% rename from dependencies/@openzeppelin-contracts-5.5.0/utils/NoncesKeyed.sol rename to dependencies/@openzeppelin-contracts-5.7.0/utils/NoncesKeyed.sol index df9c570..499fcfe 100644 --- a/dependencies/@openzeppelin-contracts-5.5.0/utils/NoncesKeyed.sol +++ b/dependencies/@openzeppelin-contracts-5.7.0/utils/NoncesKeyed.sol @@ -1,5 +1,6 @@ // SPDX-License-Identifier: MIT -// OpenZeppelin Contracts (last updated v5.2.0) (utils/NoncesKeyed.sol) +// OpenZeppelin Contracts (last updated v5.7.0) (utils/NoncesKeyed.sol) + pragma solidity ^0.8.20; import {Nonces} from "./Nonces.sol"; @@ -24,7 +25,7 @@ abstract contract NoncesKeyed is Nonces { /** * @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 + * Returns the current value with the key prefix (i.e. the packed keyNonce). 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) { diff --git a/dependencies/@openzeppelin-contracts-5.5.0/utils/Packing.sol b/dependencies/@openzeppelin-contracts-5.7.0/utils/Packing.sol similarity index 100% rename from dependencies/@openzeppelin-contracts-5.5.0/utils/Packing.sol rename to dependencies/@openzeppelin-contracts-5.7.0/utils/Packing.sol diff --git a/dependencies/@openzeppelin-contracts-5.5.0/utils/Panic.sol b/dependencies/@openzeppelin-contracts-5.7.0/utils/Panic.sol similarity index 100% rename from dependencies/@openzeppelin-contracts-5.5.0/utils/Panic.sol rename to dependencies/@openzeppelin-contracts-5.7.0/utils/Panic.sol diff --git a/dependencies/@openzeppelin-contracts-5.5.0/utils/Pausable.sol b/dependencies/@openzeppelin-contracts-5.7.0/utils/Pausable.sol similarity index 100% rename from dependencies/@openzeppelin-contracts-5.5.0/utils/Pausable.sol rename to dependencies/@openzeppelin-contracts-5.7.0/utils/Pausable.sol diff --git a/dependencies/@openzeppelin-contracts-5.5.0/utils/RLP.sol b/dependencies/@openzeppelin-contracts-5.7.0/utils/RLP.sol similarity index 67% rename from dependencies/@openzeppelin-contracts-5.5.0/utils/RLP.sol rename to dependencies/@openzeppelin-contracts-5.7.0/utils/RLP.sol index 19572ac..cee10b1 100644 --- a/dependencies/@openzeppelin-contracts-5.5.0/utils/RLP.sol +++ b/dependencies/@openzeppelin-contracts-5.7.0/utils/RLP.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -// OpenZeppelin Contracts (last updated v5.5.0) (utils/RLP.sol) +// OpenZeppelin Contracts (last updated v5.7.0) (utils/RLP.sol) pragma solidity ^0.8.26; @@ -17,13 +17,42 @@ import {Memory} from "./Memory.sol"; * * * https://github.com/succinctlabs/optimism-bedrock-contracts/blob/main/rlp/RLPWriter.sol * * https://github.com/succinctlabs/optimism-bedrock-contracts/blob/main/rlp/RLPReader.sol + * + * == Canonical vs Non-Canonical Encodings + * + * According to the Ethereum Yellow Paper, a "canonical" RLP encoding is the unique, minimal + * representation of a value. For scalar values (integers), this means: + * + * * No leading zero bytes (e.g., `0x0123` should be encoded as 2 bytes, not `0x000123` as 3 bytes) + * * Single bytes less than 0x80 must be encoded directly without a prefix wrapper + * * Zero is represented as an empty byte array (prefix `0x80`) + * + * A "non-canonical" encoding represents the same value but doesn't follow these minimality rules. + * For example, encoding the integer 1234 (0x04d2) with a leading zero as `0x830004d2` instead + * of the canonical `0x8204d2`. + * + * [IMPORTANT] + * ==== + * This implementation takes a permissive approach to decoding, accepting some non-canonical + * encodings (e.g., scalar values with leading zero bytes) that would be rejected by + * strict implementations like go-ethereum. This design choice prioritizes compatibility + * with diverse RLP encoders in the ecosystem over strict adherence to the Yellow Paper + * specification's canonicalization requirements. + * + * Users should be aware that: + * + * * Multiple different RLP encodings may decode to the same value (non-injective) + * * Encoding followed by decoding is guaranteed to work correctly + * * External RLP data from untrusted sources may have non-canonical encodings + * * Improperly wrapped single bytes (< 0x80) are still rejected as invalid + * ==== */ library RLP { using Accumulators for *; using Bytes for *; using Memory for *; - /// @dev The item is not properly formatted and cannot de decoded. + /// @dev The item is not properly formatted and cannot be decoded. error RLPInvalidEncoding(); enum ItemType { @@ -121,7 +150,12 @@ library RLP { } } - /// @dev Encode an address as RLP. + /** + * @dev Encode an address as an RLP item of fixed size (20 bytes). + * + * The address is encoded with its leading zeros (if it has any). If someone wants to encode the address as a scalar, + * they can cast it to a uint256 and then call the corresponding {encode} function. + */ function encode(address input) internal pure returns (bytes memory result) { assembly ("memory-safe") { result := mload(0x40) @@ -131,12 +165,16 @@ library RLP { } } - /// @dev Encode a uint256 as RLP. + /** + * @dev Encode a uint256 as an RLP scalar. + * + * Unlike {encode-bytes32-}, this function uses scalar encoding that removes the prefix zeros. + */ function encode(uint256 input) internal pure returns (bytes memory result) { if (input < SHORT_OFFSET) { assembly ("memory-safe") { result := mload(0x40) - mstore(result, 1) // length of the encoded data: 1 byte + mstore(result, 0x01) // length of the encoded data: 1 byte mstore8(add(result, 0x20), or(input, mul(0x80, iszero(input)))) // input (zero is encoded as 0x80) mstore(0x40, add(result, 0x21)) // reserve memory } @@ -152,14 +190,25 @@ library RLP { } } - /// @dev Encode a bytes32 as RLP. Type alias for {encode-uint256-}. - function encode(bytes32 input) internal pure returns (bytes memory) { - return encode(uint256(input)); + /** + * @dev Encode a bytes32 as an RLP item of fixed size (32 bytes). + * + * Unlike {encode-uint256-}, this function uses array encoding that preserves the prefix zeros. + */ + function encode(bytes32 input) internal pure returns (bytes memory result) { + assembly ("memory-safe") { + result := mload(0x40) + mstore(result, 0x21) // length of the encoded data: 1 (prefix) + 0x20 + mstore8(add(result, 0x20), 0xa0) // prefix: SHORT_OFFSET + 0x20 + mstore(add(result, 0x21), input) + mstore(0x40, add(result, 0x41)) // reserve memory + } } /// @dev Encode a bytes buffer as RLP. function encode(bytes memory input) internal pure returns (bytes memory) { - return (input.length == 1 && uint8(input[0]) < SHORT_OFFSET) ? input : _encode(input, SHORT_OFFSET); + return + (input.length == 1 && uint8(input[0]) < SHORT_OFFSET) ? bytes.concat(input) : _encode(input, SHORT_OFFSET); } /// @dev Encode a string as RLP. Type alias for {encode-bytes-}. @@ -167,13 +216,17 @@ library RLP { return encode(bytes(input)); } - /// @dev Encode an array of bytes as RLP. + /** + * @dev Encode an array of bytes as RLP. + * This function expects an array of already encoded bytes, not raw bytes. + * Users should call {encode} on each element of the array before calling it. + */ function encode(bytes[] memory input) internal pure returns (bytes memory) { return _encode(input.concat(), LONG_OFFSET); } /// @dev Encode an encoder (list of bytes) as RLP - function encode(Encoder memory self) internal pure returns (bytes memory result) { + function encode(Encoder memory self) internal pure returns (bytes memory) { return _encode(self.acc.flatten(), LONG_OFFSET); } @@ -208,19 +261,55 @@ library RLP { * DECODING - READ FROM AN RLP ENCODED MEMORY SLICE * ****************************************************************************************************************/ - /// @dev Decode an RLP encoded bool. See {encode-bool} + /** + * @dev Decode an RLP encoded bool. See {encode-bool} + * + * NOTE: This function treats any non-zero value as `true`, which is more permissive + * than some implementations (e.g., go-ethereum only accepts `0x00` for false and `0x01` + * for true). For example, `0x02`, `0x03`, etc. will all decode as `true`. + */ function readBool(Memory.Slice item) internal pure returns (bool) { return readUint256(item) != 0; } - /// @dev Decode an RLP encoded address. See {encode-address} + /** + * @dev Decode an RLP encoded address. See {encode-address} + * + * [NOTE] + * ==== + * This function accepts both single-byte encodings (for values 0-127, including + * precompile addresses like 0x01) and the standard 21-byte encoding with the `0x94` prefix. + * For example, `0x01` decodes to `0x0000000000000000000000000000000000000001`. + * + * Additionally, like {readUint256}, this function accepts non-canonical encodings with + * leading zeros. For instance, both `0x01` and `0x940000000000000000000000000000000000000001` + * decode to the same address. + * ==== + */ function readAddress(Memory.Slice item) internal pure returns (address) { uint256 length = item.length(); require(length == 1 || length == 21, RLPInvalidEncoding()); return address(uint160(readUint256(item))); } - /// @dev Decode an RLP encoded uint256. See {encode-uint256} + /** + * @dev Decode an RLP encoded uint256. See {encode-uint256} + * + * [NOTE] + * ==== + * This function accepts non-canonical encodings with leading zero bytes for multi-byte values, + * which differs from the Ethereum Yellow Paper specification and some reference + * implementations like go-ethereum. For example, both `0x88ab54a98ceb1f0ad2` and + * `0x8900ab54a98ceb1f0ad2` will decode to the same uint256 value (12345678901234567890). + * + * However, single bytes less than 0x80 must NOT be wrapped with a prefix. For example, + * `0x8100` is invalid (should be `0x00`), but `0x820000` is valid (two zero bytes). + * + * This permissive behavior is intentional for compatibility with various RLP encoders + * in the ecosystem, but users should be aware that multiple RLP encodings may map + * to the same decoded value (non-injective decoding). + * ==== + */ function readUint256(Memory.Slice item) internal pure returns (uint256) { uint256 length = item.length(); require(length <= 33, RLPInvalidEncoding()); @@ -231,7 +320,14 @@ library RLP { return itemLength == 0 ? 0 : uint256(item.load(itemOffset)) >> (256 - 8 * itemLength); } - /// @dev Decode an RLP encoded bytes32. See {encode-bytes32} + /** + * @dev Decode an RLP encoded bytes32. See {encode-bytes32} + * + * NOTE: Since this function delegates to {readUint256}, it inherits the non-canonical + * encoding acceptance behavior for multi-byte values. Multiple RLP encodings with different + * leading zero bytes may decode to the same bytes32 value, but single bytes < 0x80 must + * not be wrapped with a prefix (e.g., `0x820000` is valid, but `0x8100` is not). + */ function readBytes32(Memory.Slice item) internal pure returns (bytes32) { return bytes32(readUint256(item)); } @@ -241,7 +337,7 @@ library RLP { (uint256 offset, uint256 length, ItemType itemType) = _decodeLength(item); require(itemType == ItemType.Data, RLPInvalidEncoding()); - // Length is checked by {toBytes} + // Length is checked by {slice} return item.slice(offset, length).toBytes(); } @@ -250,7 +346,12 @@ library RLP { return string(readBytes(item)); } - /// @dev Decodes an RLP encoded list into an array of RLP Items. + /** + * @dev Decodes an RLP encoded list in a memory slice into an array of RLP Items. + * + * NOTE: The returned array contains slice references into the original payload, not copied bytes. Any further + * modification of the input buffer may cause the output result to become invalid. + */ function readList(Memory.Slice item) internal pure returns (Memory.Slice[] memory list) { uint256 itemLength = item.length(); @@ -317,18 +418,21 @@ library RLP { return readString(item.asSlice()); } - /// @dev Decode an RLP encoded list from bytes. See {readList} + /** + * @dev Decode an RLP encoded list from bytes. See {readList} + * + * NOTE: The returned array contains slice references into the original payload, not copied bytes. Any further + * modification of the input buffer may cause the output result to become invalid. + */ function decodeList(bytes memory value) internal pure returns (Memory.Slice[] memory) { return readList(value.asSlice()); } /** - * @dev Decodes an RLP `item`'s `length and type from its prefix. + * @dev Decodes an RLP `item`'s length and type from its prefix. * Returns the offset, length, and type of the RLP item based on the encoding rules. */ - function _decodeLength( - Memory.Slice item - ) private pure returns (uint256 _offset, uint256 _length, ItemType _itemtype) { + function _decodeLength(Memory.Slice item) private pure returns (uint256, uint256, ItemType) { uint256 itemLength = item.length(); require(itemLength != 0, RLPInvalidEncoding()); @@ -349,12 +453,13 @@ library RLP { return (1, strLength, ItemType.Data); } else { // Case: Long string (>55 bytes) - uint256 lengthLength = prefix - SHORT_OFFSET - SHORT_THRESHOLD; - - require(itemLength > lengthLength && bytes1(item.load(0)) != 0x00, RLPInvalidEncoding()); + uint256 lengthLength = prefix - SHORT_OFFSET - SHORT_THRESHOLD; // >=1 + require(itemLength > lengthLength, RLPInvalidEncoding()); + bytes32 lenChunk = item.load(1); + require(bytes1(lenChunk) != 0x00, RLPInvalidEncoding()); - uint256 len = uint256(item.load(1)) >> (256 - 8 * lengthLength); - require(len > SHORT_THRESHOLD && itemLength > lengthLength + len, RLPInvalidEncoding()); + uint256 len = uint256(lenChunk) >> (256 - 8 * lengthLength); + require(len > SHORT_THRESHOLD && itemLength - lengthLength > len, RLPInvalidEncoding()); return (lengthLength + 1, len, ItemType.Data); } @@ -363,17 +468,17 @@ library RLP { if (prefix <= LONG_OFFSET + SHORT_THRESHOLD) { // Case: Short list uint256 listLength = prefix - LONG_OFFSET; - require(item.length() > listLength, RLPInvalidEncoding()); + require(itemLength > listLength, RLPInvalidEncoding()); return (1, listLength, ItemType.List); } else { // Case: Long list - uint256 lengthLength = prefix - LONG_OFFSET - SHORT_THRESHOLD; - + uint256 lengthLength = prefix - LONG_OFFSET - SHORT_THRESHOLD; // >=1 require(itemLength > lengthLength, RLPInvalidEncoding()); - require(bytes1(item.load(0)) != 0x00); + bytes32 lenChunk = item.load(1); + require(bytes1(lenChunk) != 0x00, RLPInvalidEncoding()); - uint256 len = uint256(item.load(1)) >> (256 - 8 * lengthLength); - require(len > SHORT_THRESHOLD && itemLength > lengthLength + len, RLPInvalidEncoding()); + uint256 len = uint256(lenChunk) >> (256 - 8 * lengthLength); + require(len > SHORT_THRESHOLD && itemLength - lengthLength > len, RLPInvalidEncoding()); return (lengthLength + 1, len, ItemType.List); } diff --git a/dependencies/@openzeppelin-contracts-5.7.0/utils/RateLimiter.sol b/dependencies/@openzeppelin-contracts-5.7.0/utils/RateLimiter.sol new file mode 100644 index 0000000..b7cc73b --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.7.0/utils/RateLimiter.sol @@ -0,0 +1,310 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v5.7.0) (utils/RateLimiter.sol) +pragma solidity ^0.8.27; + +import {Math} from "./math/Math.sol"; +import {SafeCast} from "./math/SafeCast.sol"; +import {Checkpoints} from "./structs/Checkpoints.sol"; +import {Time} from "./types/Time.sol"; + +/** + * @dev This library provides primitives for limiting the rate at which an action can be performed. + * + * Two complementary strategies are available, each represented by a storage struct that the consumer keeps in its + * own storage: + * + * - {RefillingBucket}: a token bucket that refills linearly over time. The bucket starts full; each consumption + * draws from it, and it is refilled over time. Suitable when the protected resource regenerates continuously and bursts + * of size up to the bucket's capacity are allowed. Storage cost is constant regardless of consumption history. + * + * - {SlidingWindow}: a moving-window counter that caps the cumulative consumption over any `window`-second + * interval. Suitable when a strict cap on usage within a rolling window is required. Each successful consumption + * appends a checkpoint, making it a more expensive option with a larger storage footprint. + * + * === Limiter vs. entries === + * + * Each storage struct is a _limiter_: it pairs a single, shared configuration (the `window`, together with the + * `capacity` of a {RefillingBucket} or the `limit` of a {SlidingWindow}) with a mapping of independent _entries_ + * keyed by `bytes32`. Every operation takes a `key` and applies only to that entry. + * + * All entries in a limiter share the same configuration, but each entry tracks its own consumption independently: + * consuming from one `key` never affects the availability of another. This lets a single limiter enforce the same + * rate limit separately across many subjects--for example one entry per caller, per token, or per protected + * function--simply by choosing the `key` accordingly. Using a constant `key` (e.g. `bytes32(0)`) reduces the + * limiter to a single global rate limit. + * + * Configuration is changed for the whole limiter at once with {updateSettings}, whereas {state}, {used}, + * {available}, {tryConsume}, {consume} and {reset} act on the individual entry identified by `key`. + * + * Example usage (one independent rate limit per caller, all sharing the same capacity and window): + * + * ```solidity + * using RateLimiter for RateLimiter.RefillingBucket; + * + * RateLimiter.RefillingBucket private _rateLimiter; + * + * function withdraw(uint256 amount) external { + * _rateLimiter.consume(bytes32(uint256(uint160(msg.sender))), amount); + * // ... + * } + * ``` + */ +library RateLimiter { + using Checkpoints for Checkpoints.Trace208; + + /** + * @dev The requested quantity exceeds the currently available capacity. + */ + error RateLimitExceeded(); + + // ================================================ RefillingBucket ================================================ + /** + * @dev The per-`key` state of a {RefillingBucket} entry. + * + * `lastUsed` and `lastTimepoint` record the used quantity and the time it was recorded at the entry's last + * update. The current state is reconstructed lazily from these two fields on read (see {state}), keeping storage + * cost constant at one packed slot per entry regardless of how many times the entry has been consumed. + * + * WARNING: Manually updating any of the parameters may result in incorrect behavior. Only interact with the + * {RefillingBucket} through the dedicated functions. + */ + struct RefillingBucketItem { + uint208 _lastUsed; + uint48 _lastTimepoint; + } + + /** + * @dev A token-bucket limiter: shared configuration plus a mapping of independent per-`key` buckets. + * + * `capacity` and `window` are shared by every entry: each bucket has a maximum `capacity` and refills at a rate + * of `capacity / window` per second, so that an empty bucket fully refills in `window` seconds. `items` holds the + * individual buckets, each tracking its own consumption under its `key` (see {RefillingBucketItem}). + * + * WARNING: Manually updating any of the parameters may result in incorrect behavior. Only interact with the + * {RefillingBucket} through the dedicated functions. + */ + struct RefillingBucket { + uint208 _capacity; + uint48 _window; + mapping(bytes32 key => RefillingBucketItem) _items; + } + + /** + * @dev Returns the current `used` and `available` quantities for the `key` bucket, accounting for the time-based + * refill that has accrued since that entry's last update. + * + * NOTE: A `window` of 0 is treated as 1 second in the refill computation: the effective refill rate becomes + * `capacity` per second, and an uninitialized limiter (`capacity = window = 0`) reports as an empty bucket. + */ + function state( + RefillingBucket storage self, + bytes32 key + ) internal view returns (uint256 used_, uint256 available_) { + uint208 capacity_ = self._capacity; // cache + RefillingBucketItem storage item_ = self._items[key]; // cache + + used_ = Math.saturatingSub( + item_._lastUsed, + Math.mulDiv(Time.timestamp() - item_._lastTimepoint, capacity_, Math.max(self._window, 1)) + ); + available_ = Math.saturatingSub(capacity_, used_); + } + + /** + * @dev Returns the currently used quantity. See {state-struct-RateLimiter-RefillingBucket-bytes32}. + */ + function used(RefillingBucket storage self, bytes32 key) internal view returns (uint256 used_) { + (used_, ) = state(self, key); + } + + /** + * @dev Returns the currently available quantity. See {state-struct-RateLimiter-RefillingBucket-bytes32}. + */ + function available(RefillingBucket storage self, bytes32 key) internal view returns (uint256 available_) { + (, available_) = state(self, key); + } + + /** + * @dev Attempts to consume `quantity` from the `key` bucket. Returns `true` on success, `false` if that entry's + * available quantity is insufficient. + * + * A `quantity` of 0 is always accepted and does not modify storage. + */ + function tryConsume(RefillingBucket storage self, bytes32 key, uint256 quantity) internal returns (bool) { + if (quantity == 0) { + return true; + } + (uint256 used_, uint256 available_) = state(self, key); + if (quantity <= available_) { + self._items[key] = RefillingBucketItem({ + _lastTimepoint: Time.timestamp(), + _lastUsed: SafeCast.toUint208(used_ + quantity) + }); + return true; + } else { + return false; + } + } + + /** + * @dev Consumes `quantity` from the `key` bucket. Reverts with {RateLimitExceeded} if that entry's available + * quantity is insufficient. See {tryConsume-struct-RateLimiter-RefillingBucket-bytes32-uint256}. + */ + function consume(RefillingBucket storage self, bytes32 key, uint256 quantity) internal { + require(tryConsume(self, key, quantity), RateLimitExceeded()); + } + + /** + * @dev Resets the `key` bucket to a fully-available state. Other entries are unaffected. + */ + function reset(RefillingBucket storage self, bytes32 key) internal { + delete self._items[key]; + } + + /** + * @dev Updates the shared `capacity` and `window` of the limiter, affecting every entry. + * + * NOTE: The new settings will retroactively affect all the keys. The new replenishing rate (capacity / window) is + * applied from the last update timepoint of each key. Therefore, if the new settings correspond to a faster + * replenishing rate, some quantity may become available immediately. Conversely, if the new settings correspond + * to a slower replenishing rate, some quantity that would otherwise be available immediately may become + * unavailable. This side effect can be mitigated by calling {sync} on the relevant keys before updating the + * settings. There is no mechanism to automatically sync all the keys in a single operation. + */ + function updateSettings(RefillingBucket storage self, uint48 newWindow, uint208 newCapacity) internal { + self._capacity = newCapacity; + self._window = newWindow; + } + + /** + * @dev Refreshes the `key` bucket by applying the accrued refill since its last update timepoint to `lastUsed` + * and `lastTimepoint`, effectively moving that entry's timepoint forward to now. This can be used to mitigate the + * side effect of {updateSettings-struct-RateLimiter-RefillingBucket-uint48-uint208} when the replenishing rate is + * modified. It must be called per key; there is no mechanism to sync all entries at once. + */ + function sync(RefillingBucket storage self, bytes32 key) internal { + self._items[key] = RefillingBucketItem({_lastTimepoint: Time.timestamp(), _lastUsed: uint208(used(self, key))}); + } + + // ================================================= SlidingWindow ================================================= + /** + * @dev A moving-window limiter: shared configuration plus a mapping of independent per-`key` counters. + * + * `limit` and `window` are shared by every entry, and cap the cumulative consumption of each entry within any + * `window`-second interval. `items` holds the individual counters: each entry keeps its own checkpoint history + * (a `Checkpoints.Trace208`) under its `key`, recording the running cumulative total. An entry's current `used` + * quantity is the difference between its cumulative total at `block.timestamp` and at `block.timestamp - window`. + * + * NOTE: The cumulative total of each entry is stored as a `uint208`. Once it reaches `2²⁰⁸ - 1`, further + * consumption of that entry will revert in {SafeCast}. This bound is unreachable for any realistic `limit`, but + * consumers should be aware of it. + * + * NOTE: An entry's checkpoint history is not a reliable log of past consumptions--previous entries may be + * overwritten in place. The storage footprint of an entry grows with the number of + * {tryConsume-struct-RateLimiter-SlidingWindow-bytes32-uint256} calls on that `key` that succeed with a non-zero + * `quantity`. + * + * WARNING: Manually updating any of the parameters may result in incorrect behavior. Only interact with the + * {SlidingWindow} through the dedicated functions. + */ + struct SlidingWindow { + uint208 _limit; + uint48 _window; + mapping(bytes32 key => Checkpoints.Trace208) _items; + } + + /** + * @dev Returns the current `used` and `available` quantities for the `key` counter, computed as that entry's + * cumulative consumption over the last `window` seconds. + * + * NOTE: A `window` of 0 is treated as 1 second in the rolling-window lookup, and an uninitialized limiter + * (`limit = window = 0`) reports as a counter with no available quantity. + */ + function state(SlidingWindow storage self, bytes32 key) internal view returns (uint256 used_, uint256 available_) { + Checkpoints.Trace208 storage item_ = self._items[key]; // cache + + used_ = Math.saturatingSub( + item_.latest(), + item_.upperLookupRecent(uint48(Math.saturatingSub(Time.timestamp(), Math.max(self._window, 1)))) + ); + available_ = Math.saturatingSub(self._limit, used_); + } + + /** + * @dev Returns the quantity currently used by the `key` counter within the sliding window. See + * {state-struct-RateLimiter-SlidingWindow-bytes32}. + */ + function used(SlidingWindow storage self, bytes32 key) internal view returns (uint256 used_) { + (used_, ) = state(self, key); + } + + /** + * @dev Returns the quantity currently available to the `key` counter within the rolling window. See + * {state-struct-RateLimiter-SlidingWindow-bytes32}. + */ + function available(SlidingWindow storage self, bytes32 key) internal view returns (uint256 available_) { + (, available_) = state(self, key); + } + + /** + * @dev Attempts to record a consumption of `quantity` against the `key` counter. Returns `true` on success, + * `false` if that entry's available quantity within the current window is insufficient. + * + * A `quantity` of 0 is always accepted and does not modify storage. + */ + function tryConsume(SlidingWindow storage self, bytes32 key, uint256 quantity) internal returns (bool) { + if (quantity == 0) { + return true; + } + (uint256 used_, uint256 available_) = state(self, key); + if (quantity <= available_) { + if (used_ == 0) { + reset(self, key); + } + Checkpoints.Trace208 storage item_ = self._items[key]; // cache + item_.push(Time.timestamp(), SafeCast.toUint208(item_.latest() + quantity)); + return true; + } else { + return false; + } + } + + /** + * @dev Records a consumption of `quantity` against the `key` counter. Reverts with {RateLimitExceeded} if that + * entry's available quantity within the current window is insufficient. See + * {tryConsume-struct-RateLimiter-SlidingWindow-bytes32-uint256}. + */ + function consume(SlidingWindow storage self, bytes32 key, uint256 quantity) internal { + require(tryConsume(self, key, quantity), RateLimitExceeded()); + } + + /** + * @dev Resets the `key` counter to a fully-available state. Other entries are unaffected. + * + * NOTE: This will reset that entry's entire history, meaning it can also be used to recover from the cumulative + * total approaching the `uint208` ceiling. The underlying storage slots holding past checkpoints are not zeroed + * out. As a consequence, there is no gas refunded, but future + * {consume-struct-RateLimiter-SlidingWindow-bytes32-uint256} and + * {tryConsume-struct-RateLimiter-SlidingWindow-bytes32-uint256} operations are cheaper from reusing "dirty" slots. + */ + function reset(SlidingWindow storage self, bytes32 key) internal { + Checkpoints.Checkpoint208[] storage trace = self._items[key]._checkpoints; + assembly ("memory-safe") { + sstore(trace.slot, 0) + } + } + + /** + * @dev Updates the shared `limit` and `window` of the limiter, affecting every entry. + * + * NOTE: Changing the settings does not modify the recorded consumption history; it only changes how that + * history is interpreted. Increasing `window` acts on whatever history each key still has: a key that + * retained older consumptions has them brought back into the larger window, while a key whose history was + * reset before the update (incidentally or deliberately) is unaffected. Decreasing `window` conversely + * causes older consumptions to drop out sooner. + */ + function updateSettings(SlidingWindow storage self, uint48 newWindow, uint208 newLimit) internal { + self._limit = newLimit; + self._window = newWindow; + } +} diff --git a/dependencies/@openzeppelin-contracts-5.5.0/utils/ReentrancyGuard.sol b/dependencies/@openzeppelin-contracts-5.7.0/utils/ReentrancyGuard.sol similarity index 100% rename from dependencies/@openzeppelin-contracts-5.5.0/utils/ReentrancyGuard.sol rename to dependencies/@openzeppelin-contracts-5.7.0/utils/ReentrancyGuard.sol diff --git a/dependencies/@openzeppelin-contracts-5.5.0/utils/ReentrancyGuardTransient.sol b/dependencies/@openzeppelin-contracts-5.7.0/utils/ReentrancyGuardTransient.sol similarity index 100% rename from dependencies/@openzeppelin-contracts-5.5.0/utils/ReentrancyGuardTransient.sol rename to dependencies/@openzeppelin-contracts-5.7.0/utils/ReentrancyGuardTransient.sol diff --git a/dependencies/@openzeppelin-contracts-5.5.0/utils/RelayedCall.sol b/dependencies/@openzeppelin-contracts-5.7.0/utils/RelayedCall.sol similarity index 85% rename from dependencies/@openzeppelin-contracts-5.5.0/utils/RelayedCall.sol rename to dependencies/@openzeppelin-contracts-5.7.0/utils/RelayedCall.sol index e7e5ee0..ed3e32e 100644 --- a/dependencies/@openzeppelin-contracts-5.5.0/utils/RelayedCall.sol +++ b/dependencies/@openzeppelin-contracts-5.7.0/utils/RelayedCall.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -// OpenZeppelin Contracts (last updated v5.5.0) (utils/RelayedCall.sol) +// OpenZeppelin Contracts (last updated v5.7.0) (utils/RelayedCall.sol) pragma solidity ^0.8.20; @@ -15,30 +15,42 @@ pragma solidity ^0.8.20; * * For example, instead of `target.call(data)` where the target sees this contract as `msg.sender`, use * {relayCall} where the target sees a relay address as `msg.sender`. + * + * NOTE: This library uses the PUSH0 opcode that was introduced in the Shanghai hardfork. While this instruction is + * now widely supported, developers using the library on exotic chains should verify that their target chain has + * supports for EIP-3855. */ library RelayedCall { /// @dev Relays a call to the target contract through a dynamically deployed relay contract. - function relayCall(address target, bytes memory data) internal returns (bool, bytes memory) { - return relayCall(target, 0, data); + function relayCall(address target, bytes memory data) internal returns (bool success, bytes memory retData) { + return relayCall(target, 0, data, bytes32(0)); } - /// @dev Same as {relayCall} but with a value. - function relayCall(address target, uint256 value, bytes memory data) internal returns (bool, bytes memory) { + /// @dev Same as {relayCall-address-bytes} but with a value. + function relayCall( + address target, + uint256 value, + bytes memory data + ) internal returns (bool success, bytes memory retData) { return relayCall(target, value, data, bytes32(0)); } - /// @dev Same as {relayCall} but with a salt. - function relayCall(address target, bytes memory data, bytes32 salt) internal returns (bool, bytes memory) { + /// @dev Same as {relayCall-address-bytes} but with a salt. + function relayCall( + address target, + bytes memory data, + bytes32 salt + ) internal returns (bool success, bytes memory retData) { return relayCall(target, 0, data, salt); } - /// @dev Same as {relayCall} but with a salt and a value. + /// @dev Same as {relayCall-address-bytes} but with a salt and a value. function relayCall( address target, uint256 value, bytes memory data, bytes32 salt - ) internal returns (bool, bytes memory) { + ) internal returns (bool success, bytes memory retData) { return getRelayer(salt).call{value: value}(abi.encodePacked(target, data)); } diff --git a/dependencies/@openzeppelin-contracts-5.5.0/utils/ShortStrings.sol b/dependencies/@openzeppelin-contracts-5.7.0/utils/ShortStrings.sol similarity index 97% rename from dependencies/@openzeppelin-contracts-5.5.0/utils/ShortStrings.sol rename to dependencies/@openzeppelin-contracts-5.7.0/utils/ShortStrings.sol index 7933231..2788299 100644 --- a/dependencies/@openzeppelin-contracts-5.5.0/utils/ShortStrings.sol +++ b/dependencies/@openzeppelin-contracts-5.7.0/utils/ShortStrings.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -// OpenZeppelin Contracts (last updated v5.5.0) (utils/ShortStrings.sol) +// OpenZeppelin Contracts (last updated v5.7.0) (utils/ShortStrings.sol) pragma solidity ^0.8.20; @@ -47,7 +47,7 @@ library ShortStrings { /** * @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. + * This will trigger a `StringTooLong` error if the input string is too long. */ function toShortString(string memory str) internal pure returns (ShortString) { bytes memory bstr = bytes(str); diff --git a/dependencies/@openzeppelin-contracts-5.7.0/utils/SimulateCall.sol b/dependencies/@openzeppelin-contracts-5.7.0/utils/SimulateCall.sol new file mode 100644 index 0000000..10bca06 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.7.0/utils/SimulateCall.sol @@ -0,0 +1,114 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v5.7.0) (utils/SimulateCall.sol) + +pragma solidity ^0.8.20; + +/** + * @dev Library for simulating external calls and inspecting the result of the call while reverting any state changes + * of events the call may have produced. + * + * This pattern is useful when you need to simulate the result of a call without actually executing it on-chain. Since + * the address of the sender is preserved, this supports simulating calls that perform token swap that use the caller's + * balance, or any operation that is restricted to the caller. + */ +library SimulateCall { + /// @dev Simulates a call to the target contract through a dynamically deployed simulator. + function simulateCall(address target, bytes memory data) internal returns (bool success, bytes memory retData) { + return simulateCall(target, 0, data); + } + + /// @dev Same as {simulateCall-address-bytes} but with a value. + function simulateCall( + address target, + uint256 value, + bytes memory data + ) internal returns (bool success, bytes memory retData) { + (success, retData) = getSimulator().delegatecall(abi.encodePacked(target, value, data)); + success = !success; // getSimulator() returns the success value inverted + } + + /** + * @dev Returns the simulator address. + * + * The simulator REVERTs on success and RETURNs on failure, preserving the return data in both cases. + * + * * A failed target call returns the return data and succeeds in our context (no state changes). + * * A successful target call causes a revert in our context (undoing all state changes) while still + * capturing the return data. + */ + function getSimulator() internal returns (address instance) { + // [Simulator details] + // deployment prefix: 60315f8160095f39f3 + // deployed bytecode: 60333611600a575f5ffd5b6034360360345f375f5f603436035f6014355f3560601c5af13d5f5f3e5f3d91602f57f35bfd + // + // offset | bytecode | opcode | stack + // -------|-------------|----------------|-------- + // 0x0000 | 6033 | push1 0x33 | 0x33 + // 0x0002 | 36 | calldatasize | cds 0x33 + // 0x0003 | 11 | gt | (cds>0x33) + // 0x0004 | 600a | push1 0x0a | 0x0a (cds>0x33) + // 0x0006 | 57 | jumpi | + // 0x0007 | 5f | push0 | 0 + // 0x0008 | 5f | push0 | 0 0 + // 0x0009 | fd | revert | + // 0x000a | 5b | jumpdest | + // 0x000b | 6034 | push1 0x34 | 0x34 + // 0x000d | 36 | calldatasize | cds 0x34 + // 0x000e | 03 | sub | (cds-0x34) + // 0x000f | 6034 | push1 0x34 | 0x34 (cds-0x34) + // 0x0011 | 5f | push0 | 0 0x34 (cds-0x34) + // 0x0012 | 37 | calldatacopy | + // 0x0013 | 5f | push0 | 0 + // 0x0014 | 5f | push0 | 0 0 + // 0x0015 | 6034 | push1 0x34 | 0x34 0 0 + // 0x0017 | 36 | calldatasize | cds 0x34 0 0 + // 0x0018 | 03 | sub | (cds-0x34) 0 0 + // 0x0019 | 5f | push0 | 0 (cds-0x34) 0 0 + // 0x001a | 6014 | push1 0x14 | 0x14 0 (cds-0x34) 0 0 + // 0x001c | 35 | calldataload | cd[0x14] 0 (cds-0x34) 0 0 + // 0x001d | 5f | push0 | 0 cd[0x14] 0 (cds-0x34) 0 0 + // 0x001e | 35 | calldataload | cd[0] cd[0x14] 0 (cds-0x34) 0 0 + // 0x001f | 6060 | push1 0x60 | 0x60 cd[0] cd[0x14] 0 (cds-0x34) 0 0 + // 0x0021 | 1c | shr | target cd[0x14] 0 (cds-0x34) 0 0 + // 0x0022 | 5a | gas | gas target cd[0x14] 0 (cds-0x34) 0 0 + // 0x0023 | f1 | call | suc + // 0x0024 | 3d | returndatasize | rds suc + // 0x0025 | 5f | push0 | 0 rds suc + // 0x0026 | 5f | push0 | 0 0 rds suc + // 0x0027 | 3e | returndatacopy | suc + // 0x0028 | 5f | push0 | 0 suc + // 0x0029 | 3d | returndatasize | rds 0 suc + // 0x002a | 91 | swap2 | suc 0 rds + // 0x002b | 602f | push1 0x2f | 0x2f suc 0 rds + // 0x002d | 57 | jumpi | 0 rds + // 0x002e | f3 | return | + // 0x002f | 5b | jumpdest | 0 rds + // 0x0030 | fd | revert | + assembly ("memory-safe") { + let fmp := mload(0x40) + + // build initcode at FMP + mstore(add(fmp, 0x20), 0x5f375f5f603436035f6014355f3560601c5af13d5f5f3e5f3d91602f57f35bfd) + mstore(fmp, 0x60315f8160095f39f360333611600a575f5ffd5b603436036034) + let initcodehash := keccak256(add(fmp, 0x06), 0x3a) + + // compute create2 address + mstore(0x40, initcodehash) + mstore(0x20, 0) + mstore(0x00, address()) + mstore8(0x0b, 0xff) + instance := and(keccak256(0x0b, 0x55), shr(96, not(0))) + + // if simulator not yet deployed, deploy it + if iszero(extcodesize(instance)) { + if iszero(create2(0, add(fmp, 0x06), 0x3a, 0)) { + returndatacopy(fmp, 0x00, returndatasize()) + revert(fmp, returndatasize()) + } + } + + // cleanup fmp space used as scratch + mstore(0x40, fmp) + } + } +} diff --git a/dependencies/@openzeppelin-contracts-5.5.0/utils/SlotDerivation.sol b/dependencies/@openzeppelin-contracts-5.7.0/utils/SlotDerivation.sol similarity index 100% rename from dependencies/@openzeppelin-contracts-5.5.0/utils/SlotDerivation.sol rename to dependencies/@openzeppelin-contracts-5.7.0/utils/SlotDerivation.sol diff --git a/dependencies/@openzeppelin-contracts-5.5.0/utils/StorageSlot.sol b/dependencies/@openzeppelin-contracts-5.7.0/utils/StorageSlot.sol similarity index 100% rename from dependencies/@openzeppelin-contracts-5.5.0/utils/StorageSlot.sol rename to dependencies/@openzeppelin-contracts-5.7.0/utils/StorageSlot.sol diff --git a/dependencies/@openzeppelin-contracts-5.5.0/utils/Strings.sol b/dependencies/@openzeppelin-contracts-5.7.0/utils/Strings.sol similarity index 85% rename from dependencies/@openzeppelin-contracts-5.5.0/utils/Strings.sol rename to dependencies/@openzeppelin-contracts-5.7.0/utils/Strings.sol index 2fcd286..6612f7e 100644 --- a/dependencies/@openzeppelin-contracts-5.5.0/utils/Strings.sol +++ b/dependencies/@openzeppelin-contracts-5.7.0/utils/Strings.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -// OpenZeppelin Contracts (last updated v5.5.0) (utils/Strings.sol) +// OpenZeppelin Contracts (last updated v5.6.0) (utils/Strings.sol) pragma solidity ^0.8.24; @@ -17,11 +17,7 @@ library Strings { 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 + 0xffffffff | // first 32 bits corresponding to the control characters (U+0000 to U+001F) (1 << 0x22) | // double quote (1 << 0x5c); // backslash @@ -457,37 +453,52 @@ library Strings { * * 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. + * NOTE: This function escapes backslashes (including those in \uXXXX sequences) and the characters in ranges + * defined in section 2.5 of RFC-4627 (U+0000 to U+001F, U+0022 and U+005C). All control characters in U+0000 + * to U+001F are escaped (\b, \t, \n, \f, \r use short form; others use \u00XX). 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 + + // Put output at the FMP. Memory will be reserved later when we figure out the actual length of the escaped + // string. All write are done using _unsafeWriteBytesOffset, which avoid the (expensive) length checks for + // each character written. + bytes memory output; + assembly ("memory-safe") { + output := mload(0x40) + } uint256 outputLength = 0; for (uint256 i = 0; 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++] = "\\"; + uint8 char = uint8(bytes1(_unsafeReadBytesOffset(buffer, i))); + if (((SPECIAL_CHARS_LOOKUP & (1 << char)) != 0)) { + _unsafeWriteBytesOffset(output, outputLength++, "\\"); + if (char == 0x08) _unsafeWriteBytesOffset(output, outputLength++, "b"); + else if (char == 0x09) _unsafeWriteBytesOffset(output, outputLength++, "t"); + else if (char == 0x0a) _unsafeWriteBytesOffset(output, outputLength++, "n"); + else if (char == 0x0c) _unsafeWriteBytesOffset(output, outputLength++, "f"); + else if (char == 0x0d) _unsafeWriteBytesOffset(output, outputLength++, "r"); + else if (char == 0x5c) _unsafeWriteBytesOffset(output, outputLength++, "\\"); else if (char == 0x22) { // solhint-disable-next-line quotes - output[outputLength++] = '"'; + _unsafeWriteBytesOffset(output, outputLength++, '"'); + } else { + // U+0000 to U+001F without short form: output \u00XX + _unsafeWriteBytesOffset(output, outputLength++, "u"); + _unsafeWriteBytesOffset(output, outputLength++, "0"); + _unsafeWriteBytesOffset(output, outputLength++, "0"); + _unsafeWriteBytesOffset(output, outputLength++, HEX_DIGITS[char >> 4]); + _unsafeWriteBytesOffset(output, outputLength++, HEX_DIGITS[char & 0x0f]); } } else { - output[outputLength++] = char; + _unsafeWriteBytesOffset(output, outputLength++, bytes1(char)); } } - // write the actual length and deallocate unused memory + // write the actual length and reserve memory assembly ("memory-safe") { mstore(output, outputLength) - mstore(0x40, add(output, shl(5, shr(5, add(outputLength, 63))))) + mstore(0x40, add(output, add(outputLength, 0x20))) } return string(output); @@ -505,4 +516,17 @@ library Strings { value := mload(add(add(buffer, 0x20), offset)) } } + + /** + * @dev Write a bytes1 to 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 _unsafeWriteBytesOffset(bytes memory buffer, uint256 offset, bytes1 value) private pure { + // This is not memory safe in the general case, but all calls to this private function are within bounds. + assembly ("memory-safe") { + mstore8(add(add(buffer, 0x20), offset), shr(248, value)) + } + } } diff --git a/dependencies/@openzeppelin-contracts-5.5.0/utils/TransientSlot.sol b/dependencies/@openzeppelin-contracts-5.7.0/utils/TransientSlot.sol similarity index 100% rename from dependencies/@openzeppelin-contracts-5.5.0/utils/TransientSlot.sol rename to dependencies/@openzeppelin-contracts-5.7.0/utils/TransientSlot.sol diff --git a/dependencies/@openzeppelin-contracts-5.5.0/utils/cryptography/ECDSA.sol b/dependencies/@openzeppelin-contracts-5.7.0/utils/cryptography/ECDSA.sol similarity index 91% rename from dependencies/@openzeppelin-contracts-5.5.0/utils/cryptography/ECDSA.sol rename to dependencies/@openzeppelin-contracts-5.7.0/utils/cryptography/ECDSA.sol index 838fe26..f0e8c61 100644 --- a/dependencies/@openzeppelin-contracts-5.5.0/utils/cryptography/ECDSA.sol +++ b/dependencies/@openzeppelin-contracts-5.7.0/utils/cryptography/ECDSA.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -// OpenZeppelin Contracts (last updated v5.5.0) (utils/cryptography/ECDSA.sol) +// OpenZeppelin Contracts (last updated v5.7.0) (utils/cryptography/ECDSA.sol) pragma solidity ^0.8.20; @@ -18,7 +18,7 @@ library ECDSA { } /** - * @dev The signature derives the `address(0)`. + * @dev The signature is invalid. */ error ECDSAInvalidSignature(); @@ -122,8 +122,8 @@ library ECDSA { * 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); + (address recovered, RecoverError err, bytes32 errorArg) = tryRecover(hash, signature); + _throwError(err, errorArg); return recovered; } @@ -131,8 +131,8 @@ library ECDSA { * @dev Variant of {recover} that takes a signature in calldata */ function recoverCalldata(bytes32 hash, bytes calldata signature) internal pure returns (address) { - (address recovered, RecoverError error, bytes32 errorArg) = tryRecoverCalldata(hash, signature); - _throwError(error, errorArg); + (address recovered, RecoverError err, bytes32 errorArg) = tryRecoverCalldata(hash, signature); + _throwError(err, errorArg); return recovered; } @@ -155,11 +155,11 @@ library ECDSA { } /** - * @dev Overload of {ECDSA-recover} that receives the `r and `vs` short-signature fields separately. + * @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); + (address recovered, RecoverError err, bytes32 errorArg) = tryRecover(hash, r, vs); + _throwError(err, errorArg); return recovered; } @@ -200,8 +200,8 @@ library ECDSA { * `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); + (address recovered, RecoverError err, bytes32 errorArg) = tryRecover(hash, v, r, s); + _throwError(err, errorArg); return recovered; } @@ -270,14 +270,14 @@ library ECDSA { /** * @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) { + function _throwError(RecoverError err, bytes32 errorArg) private pure { + if (err == RecoverError.NoError) { return; // no error: do nothing - } else if (error == RecoverError.InvalidSignature) { + } else if (err == RecoverError.InvalidSignature) { revert ECDSAInvalidSignature(); - } else if (error == RecoverError.InvalidSignatureLength) { + } else if (err == RecoverError.InvalidSignatureLength) { revert ECDSAInvalidSignatureLength(uint256(errorArg)); - } else if (error == RecoverError.InvalidSignatureS) { + } else if (err == RecoverError.InvalidSignatureS) { revert ECDSAInvalidSignatureS(errorArg); } } diff --git a/dependencies/@openzeppelin-contracts-5.5.0/utils/cryptography/EIP712.sol b/dependencies/@openzeppelin-contracts-5.7.0/utils/cryptography/EIP712.sol similarity index 85% rename from dependencies/@openzeppelin-contracts-5.5.0/utils/cryptography/EIP712.sol rename to dependencies/@openzeppelin-contracts-5.7.0/utils/cryptography/EIP712.sol index 2bc45a4..a2e7bf4 100644 --- a/dependencies/@openzeppelin-contracts-5.5.0/utils/cryptography/EIP712.sol +++ b/dependencies/@openzeppelin-contracts-5.7.0/utils/cryptography/EIP712.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -// OpenZeppelin Contracts (last updated v5.5.0) (utils/cryptography/EIP712.sol) +// OpenZeppelin Contracts (last updated v5.7.0) (utils/cryptography/EIP712.sol) pragma solidity ^0.8.24; @@ -29,6 +29,10 @@ import {IERC5267} from "../../interfaces/IERC5267.sol"; * 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. * + * IMPORTANT: The `name` and `version` must each fit in a `ShortString` (at most 31 bytes). Longer values cause the + * constructor to revert with a `ShortStrings.StringTooLong` error. Because the values are stored exclusively in + * immutables, the domain is preserved when the contract is used behind a proxy or clone without an initializer. + * * @custom:oz-upgrades-unsafe-allow state-variable-immutable */ abstract contract EIP712 is IERC5267 { @@ -48,8 +52,14 @@ abstract contract EIP712 is IERC5267 { ShortString private immutable _name; ShortString private immutable _version; + + // IMPORTANT: Deprecated. Kept to preserve the storage layout of inheriting contracts used as an + // implementation behind a proxy. // slither-disable-next-line constable-states string private _nameFallback; + + // IMPORTANT: Deprecated. Kept to preserve the storage layout of inheriting contracts used as an + // implementation behind a proxy. // slither-disable-next-line constable-states string private _versionFallback; @@ -66,8 +76,8 @@ abstract contract EIP712 is IERC5267 { * contract upgrade]. */ constructor(string memory name, string memory version) { - _name = name.toShortStringWithFallback(_nameFallback); - _version = version.toShortStringWithFallback(_versionFallback); + _name = name.toShortString(); + _version = version.toShortString(); _hashedName = keccak256(bytes(name)); _hashedVersion = keccak256(bytes(version)); @@ -139,22 +149,20 @@ abstract contract EIP712 is IERC5267 { /** * @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). + * NOTE: This function reads `_name`, which is an immutable value. */ // solhint-disable-next-line func-name-mixedcase function _EIP712Name() internal view returns (string memory) { - return _name.toStringWithFallback(_nameFallback); + return _name.toString(); } /** * @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). + * NOTE: This function reads `_version`, which is an immutable value. */ // solhint-disable-next-line func-name-mixedcase function _EIP712Version() internal view returns (string memory) { - return _version.toStringWithFallback(_versionFallback); + return _version.toString(); } } diff --git a/dependencies/@openzeppelin-contracts-5.5.0/utils/cryptography/Hashes.sol b/dependencies/@openzeppelin-contracts-5.7.0/utils/cryptography/Hashes.sol similarity index 100% rename from dependencies/@openzeppelin-contracts-5.5.0/utils/cryptography/Hashes.sol rename to dependencies/@openzeppelin-contracts-5.7.0/utils/cryptography/Hashes.sol diff --git a/dependencies/@openzeppelin-contracts-5.5.0/utils/cryptography/MerkleProof.sol b/dependencies/@openzeppelin-contracts-5.7.0/utils/cryptography/MerkleProof.sol similarity index 80% rename from dependencies/@openzeppelin-contracts-5.5.0/utils/cryptography/MerkleProof.sol rename to dependencies/@openzeppelin-contracts-5.7.0/utils/cryptography/MerkleProof.sol index 19b09e2..869f624 100644 --- a/dependencies/@openzeppelin-contracts-5.5.0/utils/cryptography/MerkleProof.sol +++ b/dependencies/@openzeppelin-contracts-5.7.0/utils/cryptography/MerkleProof.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -// OpenZeppelin Contracts (last updated v5.1.0) (utils/cryptography/MerkleProof.sol) +// OpenZeppelin Contracts (last updated v5.6.0) (utils/cryptography/MerkleProof.sol) // This file was procedurally generated from scripts/generate/templates/MerkleProof.js. pragma solidity ^0.8.20; @@ -30,7 +30,7 @@ import {Hashes} from "./Hashes.sol"; */ library MerkleProof { /** - *@dev The multiproof provided is not valid. + * @dev The multiproof provided is not valid. */ error MerkleProofInvalidMultiproof(); @@ -217,26 +217,25 @@ library MerkleProof { 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) { + // 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 (proofPos != proof.length) { revert MerkleProofInvalidMultiproof(); } @@ -305,26 +304,25 @@ library MerkleProof { 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) { + // 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 (proofPos != proof.length) { revert MerkleProofInvalidMultiproof(); } @@ -391,26 +389,25 @@ library MerkleProof { 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) { + // 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 (proofPos != proof.length) { revert MerkleProofInvalidMultiproof(); } @@ -479,26 +476,25 @@ library MerkleProof { 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) { + // 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 (proofPos != proof.length) { revert MerkleProofInvalidMultiproof(); } diff --git a/dependencies/@openzeppelin-contracts-5.7.0/utils/cryptography/MessageHashUtils.sol b/dependencies/@openzeppelin-contracts-5.7.0/utils/cryptography/MessageHashUtils.sol new file mode 100644 index 0000000..f42308a --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.7.0/utils/cryptography/MessageHashUtils.sol @@ -0,0 +1,228 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v5.6.0) (utils/cryptography/MessageHashUtils.sol) + +pragma solidity ^0.8.24; + +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 { + error ERC5267ExtensionsNotSupported(); + + /** + * @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) + } + } + + /** + * @dev Returns the EIP-712 domain separator constructed from an `eip712Domain`. See {IERC5267-eip712Domain} + * + * This function dynamically constructs the domain separator based on which fields are present in the + * `fields` parameter. It contains flags that indicate which domain fields are present: + * + * * Bit 0 (0x01): name + * * Bit 1 (0x02): version + * * Bit 2 (0x04): chainId + * * Bit 3 (0x08): verifyingContract + * * Bit 4 (0x10): salt + * + * Arguments that correspond to fields which are not present in `fields` are ignored. For example, if `fields` is + * `0x0f` (`0b01111`), then the `salt` parameter is ignored. + */ + function toDomainSeparator( + bytes1 fields, + string memory name, + string memory version, + uint256 chainId, + address verifyingContract, + bytes32 salt + ) internal pure returns (bytes32 hash) { + return + toDomainSeparator( + fields, + keccak256(bytes(name)), + keccak256(bytes(version)), + chainId, + verifyingContract, + salt + ); + } + + /// @dev Variant of {toDomainSeparator-bytes1-string-string-uint256-address-bytes32} that uses hashed name and version. + function toDomainSeparator( + bytes1 fields, + bytes32 nameHash, + bytes32 versionHash, + uint256 chainId, + address verifyingContract, + bytes32 salt + ) internal pure returns (bytes32 hash) { + bytes32 domainTypeHash = toDomainTypeHash(fields); + + assembly ("memory-safe") { + // align fields to the right for easy processing + fields := shr(248, fields) + + // FMP used as scratch space + let fmp := mload(0x40) + mstore(fmp, domainTypeHash) + + let ptr := add(fmp, 0x20) + if and(fields, 0x01) { + mstore(ptr, nameHash) + ptr := add(ptr, 0x20) + } + if and(fields, 0x02) { + mstore(ptr, versionHash) + ptr := add(ptr, 0x20) + } + if and(fields, 0x04) { + mstore(ptr, chainId) + ptr := add(ptr, 0x20) + } + if and(fields, 0x08) { + mstore(ptr, verifyingContract) + ptr := add(ptr, 0x20) + } + if and(fields, 0x10) { + mstore(ptr, salt) + ptr := add(ptr, 0x20) + } + + hash := keccak256(fmp, sub(ptr, fmp)) + } + } + + /// @dev Builds an EIP-712 domain type hash depending on the `fields` provided, following https://eips.ethereum.org/EIPS/eip-5267[ERC-5267] + function toDomainTypeHash(bytes1 fields) internal pure returns (bytes32 hash) { + if (fields & 0x20 == 0x20) revert ERC5267ExtensionsNotSupported(); + + assembly ("memory-safe") { + // align fields to the right for easy processing + fields := shr(248, fields) + + // FMP used as scratch space + let fmp := mload(0x40) + mstore(fmp, "EIP712Domain(") + + let ptr := add(fmp, 0x0d) + // name field + if and(fields, 0x01) { + mstore(ptr, "string name,") + ptr := add(ptr, 0x0c) + } + // version field + if and(fields, 0x02) { + mstore(ptr, "string version,") + ptr := add(ptr, 0x0f) + } + // chainId field + if and(fields, 0x04) { + mstore(ptr, "uint256 chainId,") + ptr := add(ptr, 0x10) + } + // verifyingContract field + if and(fields, 0x08) { + mstore(ptr, "address verifyingContract,") + ptr := add(ptr, 0x1a) + } + // salt field + if and(fields, 0x10) { + mstore(ptr, "bytes32 salt,") + ptr := add(ptr, 0x0d) + } + // if any field is enabled, remove the trailing comma + ptr := sub(ptr, iszero(iszero(and(fields, 0x1f)))) + // add the closing brace + mstore8(ptr, 0x29) // add closing brace + ptr := add(ptr, 1) + + hash := keccak256(fmp, sub(ptr, fmp)) + } + } +} diff --git a/dependencies/@openzeppelin-contracts-5.5.0/utils/cryptography/P256.sol b/dependencies/@openzeppelin-contracts-5.7.0/utils/cryptography/P256.sol similarity index 99% rename from dependencies/@openzeppelin-contracts-5.5.0/utils/cryptography/P256.sol rename to dependencies/@openzeppelin-contracts-5.7.0/utils/cryptography/P256.sol index 81d79ad..33a9c49 100644 --- a/dependencies/@openzeppelin-contracts-5.5.0/utils/cryptography/P256.sol +++ b/dependencies/@openzeppelin-contracts-5.7.0/utils/cryptography/P256.sol @@ -1,5 +1,6 @@ // SPDX-License-Identifier: MIT -// OpenZeppelin Contracts (last updated v5.3.0) (utils/cryptography/P256.sol) +// OpenZeppelin Contracts (last updated v5.7.0) (utils/cryptography/P256.sol) + pragma solidity ^0.8.20; import {Math} from "../math/Math.sol"; @@ -89,7 +90,7 @@ library P256 { 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 + return (false, true); // signature is invalid, and it's 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 ( diff --git a/dependencies/@openzeppelin-contracts-5.5.0/utils/cryptography/RSA.sol b/dependencies/@openzeppelin-contracts-5.7.0/utils/cryptography/RSA.sol similarity index 95% rename from dependencies/@openzeppelin-contracts-5.5.0/utils/cryptography/RSA.sol rename to dependencies/@openzeppelin-contracts-5.7.0/utils/cryptography/RSA.sol index 4e04ce5..0c3f926 100644 --- a/dependencies/@openzeppelin-contracts-5.5.0/utils/cryptography/RSA.sol +++ b/dependencies/@openzeppelin-contracts-5.7.0/utils/cryptography/RSA.sol @@ -1,5 +1,6 @@ // SPDX-License-Identifier: MIT -// OpenZeppelin Contracts (last updated v5.1.0) (utils/cryptography/RSA.sol) +// OpenZeppelin Contracts (last updated v5.7.0) (utils/cryptography/RSA.sol) + pragma solidity ^0.8.20; import {Math} from "../math/Math.sol"; @@ -77,8 +78,12 @@ library RSA { } // 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); + // The previous check guarantees that n > 0. Therefore tryModExp can only fail if the precompile runs + // out of gas (e.g. oversized inputs); fail closed in that case. + (bool success, bytes memory buffer) = Math.tryModExp(s, e, n); + if (!success) { + return false; + } // Check that buffer is well encoded: // buffer ::= 0x00 | 0x01 | PS | 0x00 | DigestInfo diff --git a/dependencies/@openzeppelin-contracts-5.5.0/utils/cryptography/SignatureChecker.sol b/dependencies/@openzeppelin-contracts-5.7.0/utils/cryptography/SignatureChecker.sol similarity index 77% rename from dependencies/@openzeppelin-contracts-5.5.0/utils/cryptography/SignatureChecker.sol rename to dependencies/@openzeppelin-contracts-5.7.0/utils/cryptography/SignatureChecker.sol index de61956..24d1f64 100644 --- a/dependencies/@openzeppelin-contracts-5.5.0/utils/cryptography/SignatureChecker.sol +++ b/dependencies/@openzeppelin-contracts-5.7.0/utils/cryptography/SignatureChecker.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -// OpenZeppelin Contracts (last updated v5.5.0) (utils/cryptography/SignatureChecker.sol) +// OpenZeppelin Contracts (last updated v5.7.0) (utils/cryptography/SignatureChecker.sol) pragma solidity ^0.8.24; @@ -50,7 +50,7 @@ library SignatureChecker { (address recovered, ECDSA.RecoverError err, ) = ECDSA.tryRecoverCalldata(hash, signature); return err == ECDSA.RecoverError.NoError && recovered == signer; } else { - return isValidERC1271SignatureNow(signer, hash, signature); + return isValidERC1271SignatureNowCalldata(signer, hash, signature); } } @@ -70,17 +70,52 @@ library SignatureChecker { uint256 length = signature.length; assembly ("memory-safe") { - // Encoded calldata is : + // Encoded calldata following https://docs.soliditylang.org/en/v0.8.35/abi-spec.html: // [ 0x00 - 0x03 ] // [ 0x04 - 0x23 ] - // [ 0x24 - 0x44 ] (0x40) - // [ 0x44 - 0x64 ] - // [ 0x64 - ... ] + // [ 0x24 - 0x43 ] (0x40) + // [ 0x44 - 0x63 ] + // [ 0x64 - ... ] | let ptr := mload(0x40) mstore(ptr, selector) mstore(add(ptr, 0x04), hash) mstore(add(ptr, 0x24), 0x40) mcopy(add(ptr, 0x44), signature, add(length, 0x20)) + mstore(add(add(ptr, 0x64), length), 0) + + // round up the length to the next multiple of 32 bytes to ensure that the calldata is properly padded + length := shl(5, shr(5, add(length, 0x1F))) + + let success := staticcall(gas(), signer, ptr, add(length, 0x64), 0x00, 0x20) + result := and(success, and(gt(returndatasize(), 0x1f), eq(mload(0x00), selector))) + } + } + + function isValidERC1271SignatureNowCalldata( + address signer, + bytes32 hash, + bytes calldata signature + ) internal view returns (bool result) { + bytes4 selector = IERC1271.isValidSignature.selector; + uint256 length = signature.length; + + assembly ("memory-safe") { + // Encoded calldata following https://docs.soliditylang.org/en/v0.8.35/abi-spec.html: + // [ 0x00 - 0x03 ] + // [ 0x04 - 0x23 ] + // [ 0x24 - 0x43 ] (0x40) + // [ 0x44 - 0x63 ] + // [ 0x64 - ... ] | + let ptr := mload(0x40) + mstore(ptr, selector) + mstore(add(ptr, 0x04), hash) + mstore(add(ptr, 0x24), 0x40) + mstore(add(ptr, 0x44), length) + calldatacopy(add(ptr, 0x64), signature.offset, length) + mstore(add(add(ptr, 0x64), length), 0) + + // round up the length to the next multiple of 32 bytes to ensure that the calldata is properly padded + length := shl(5, shr(5, add(length, 0x1F))) let success := staticcall(gas(), signer, ptr, add(length, 0x64), 0x00, 0x20) result := and(success, and(gt(returndatasize(), 0x1f), eq(mload(0x00), selector))) diff --git a/dependencies/@openzeppelin-contracts-5.7.0/utils/cryptography/TrieProof.sol b/dependencies/@openzeppelin-contracts-5.7.0/utils/cryptography/TrieProof.sol new file mode 100644 index 0000000..7390024 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.7.0/utils/cryptography/TrieProof.sol @@ -0,0 +1,256 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v5.7.0) (utils/cryptography/TrieProof.sol) + +pragma solidity ^0.8.26; + +import {Bytes} from "../Bytes.sol"; +import {Memory} from "../Memory.sol"; +import {RLP} from "../RLP.sol"; + +/** + * @dev Library for verifying Ethereum Merkle-Patricia trie inclusion proofs. + * + * The {traverse} and {verify} functions can be used to prove the following value: + * + * * Transaction against the transactionsRoot of a block. + * * Event against receiptsRoot of a block. + * * Account details (RLP encoding of [nonce, balance, storageRoot, codeHash]) against the stateRoot of a block. + * * Storage slot (RLP encoding of the value) against the storageRoot of an account. + * + * Proving a storage slot is usually done in 3 steps: + * + * * From the stateRoot of a block, process the account proof (see `eth_getProof`) to get the account details. + * * RLP decode the account details to extract the storageRoot. + * * Use storageRoot of that account to process the storageProof (again, see `eth_getProof`). + * + * See https://ethereum.org/en/developers/docs/data-structures-and-encoding/patricia-merkle-trie[Merkle-Patricia trie] + * + * Based on https://github.com/ethereum-optimism/optimism/blob/ef970556e668b271a152124023a8d6bb5159bacf/packages/contracts-bedrock/src/libraries/trie/MerkleTrie.sol[this implementation from optimism]. + */ +library TrieProof { + using Bytes for *; + using RLP for *; + using Memory for *; + + enum Prefix { + EXTENSION_EVEN, // 0 - Extension node with even length path + EXTENSION_ODD, // 1 - Extension node with odd length path + LEAF_EVEN, // 2 - Leaf node with even length path + LEAF_ODD // 3 - Leaf node with odd length path + } + + enum ProofError { + NO_ERROR, // No error occurred during proof traversal + EMPTY_KEY, // The provided key is empty + INVALID_ROOT, // The validation of the root node failed + INVALID_LARGE_NODE, // The validation of a large node failed + INVALID_SHORT_NODE, // The validation of a short node failed + EMPTY_PATH, // The path in a leaf or extension node is empty + INVALID_PATH_REMAINDER, // The path remainder in a leaf or extension node is invalid + EMPTY_EXTENSION_PATH_REMAINDER, // The path remainder in an extension node is empty + INVALID_EXTRA_PROOF_ELEMENT, // A leaf value should be the last proof element + EMPTY_VALUE, // The leaf value is empty + MISMATCH_LEAF_PATH_KEY_REMAINDER, // The path remainder in a leaf node doesn't match the key remainder + UNKNOWN_NODE_PREFIX, // The node prefix is unknown + UNPARSEABLE_NODE, // The node cannot be parsed from RLP encoding + INVALID_PROOF // General failure during proof traversal + } + + error TrieProofTraversalError(ProofError err); + + /// @dev The radix of the Ethereum trie + uint256 internal constant EVM_TREE_RADIX = 16; + + /// @dev Number of items in a branch node (16 children + 1 value) + uint256 internal constant BRANCH_NODE_LENGTH = EVM_TREE_RADIX + 1; + + /// @dev Number of items in leaf or extension nodes (always 2) + uint256 internal constant LEAF_OR_EXTENSION_NODE_LENGTH = 2; + + /// @dev Verifies a `proof` against a given `key`, `value`, and `root` hash. + function verify( + bytes memory value, + bytes32 root, + bytes memory key, + bytes[] memory proof + ) internal pure returns (bool) { + (bytes memory processedValue, ProofError err) = tryTraverse(root, key, proof); + return processedValue.equal(value) && err == ProofError.NO_ERROR; + } + + /** + * @dev Traverses a proof with a given key and returns the value. + * + * Reverts with {TrieProofTraversalError} if proof is invalid. + */ + function traverse(bytes32 root, bytes memory key, bytes[] memory proof) internal pure returns (bytes memory) { + (bytes memory value, ProofError err) = tryTraverse(root, key, proof); + require(err == ProofError.NO_ERROR, TrieProofTraversalError(err)); + return value; + } + + /** + * @dev Traverses a proof with a given key and returns the value and an error flag + * instead of reverting if the proof is invalid. This function may still revert if + * malformed input leads to RLP decoding errors. + */ + function tryTraverse( + bytes32 root, + bytes memory key, + bytes[] memory proof + ) internal pure returns (bytes memory value, ProofError err) { + if (key.length == 0) return (_emptyBytesMemory(), ProofError.EMPTY_KEY); + + // Expand the key + bytes memory keyExpanded = key.toNibbles(); + + bytes32 currentNodeId; + uint256 currentNodeIdLength; + + // Free memory pointer cache + Memory.Pointer fmp = Memory.getFreeMemoryPointer(); + + // Traverse proof + uint256 keyIndex = 0; + for (uint256 i = 0; i < proof.length; ++i) { + // validates the encoded node matches the expected node id + bytes memory encoded = proof[i]; + if (keyIndex == 0) { + // Root node must match root hash + if (keccak256(encoded) != root) return (_emptyBytesMemory(), ProofError.INVALID_ROOT); + } else if (encoded.length >= 32) { + // Large nodes are stored as hashes + if (currentNodeIdLength != 32 || keccak256(encoded) != currentNodeId) + return (_emptyBytesMemory(), ProofError.INVALID_LARGE_NODE); + } else { + // Short nodes must match directly + if (currentNodeIdLength != encoded.length || bytes32(encoded) != currentNodeId) + return (_emptyBytesMemory(), ProofError.INVALID_SHORT_NODE); + } + + // decode the current node as an RLP list, and process it + for (Memory.Slice[] memory decoded = encoded.decodeList(); ; ) { + if (decoded.length == BRANCH_NODE_LENGTH) { + // If we've consumed the entire key, the value must be in the last slot + // Otherwise, continue down the branch specified by the next nibble in the key + if (keyIndex == keyExpanded.length) { + return _validateLastItem(decoded[EVM_TREE_RADIX], proof.length, i); + } else { + bytes1 branchKey = keyExpanded[keyIndex]; + Memory.Slice childNode = decoded[uint8(branchKey)]; + (currentNodeId, currentNodeIdLength) = _getNodeId(childNode); + keyIndex += 1; + + if (currentNodeIdLength == 32 || _match(childNode, proof, i + 1)) { + break; + } + decoded = childNode.readList(); + } + } else if (decoded.length == LEAF_OR_EXTENSION_NODE_LENGTH) { + bytes[] memory proof_ = proof; + + bytes memory path = decoded[0].readBytes().toNibbles(); // expanded path + // The following is equivalent to path.length < 2 because toNibbles can't return odd-length buffers + if (path.length == 0) { + return (_emptyBytesMemory(), ProofError.EMPTY_PATH); + } + uint8 prefix = uint8(path[0]); // path encoding nibble (node type + parity), see {Prefix} + Memory.Slice keyRemainder = keyExpanded.asSlice().slice(keyIndex); // Remaining key to match + Memory.Slice pathRemainder = path.asSlice().slice(2 - (prefix % 2)); // Path after the prefix + uint256 pathRemainderLength = pathRemainder.length(); + + // pathRemainder must not be longer than keyRemainder and must match the start of keyRemainder + if ( + pathRemainderLength > keyRemainder.length() || + !pathRemainder.equal(keyRemainder.slice(0, pathRemainderLength)) + ) { + return (_emptyBytesMemory(), ProofError.INVALID_PATH_REMAINDER); + } + + if (prefix <= uint8(Prefix.EXTENSION_ODD)) { + // Eq to: prefix == EXTENSION_EVEN || prefix == EXTENSION_ODD + if (pathRemainderLength == 0) { + return (_emptyBytesMemory(), ProofError.EMPTY_EXTENSION_PATH_REMAINDER); + } + // Increment keyIndex by the number of nibbles consumed and continue traversal + Memory.Slice childNode = decoded[1]; + (currentNodeId, currentNodeIdLength) = _getNodeId(childNode); + keyIndex += pathRemainderLength; + + if (currentNodeIdLength == 32 || _match(childNode, proof_, i + 1)) { + break; + } + decoded = childNode.readList(); + } else if (prefix <= uint8(Prefix.LEAF_ODD)) { + // Eq to: prefix == LEAF_EVEN || prefix == LEAF_ODD + // + // Leaf node (terminal) - return its value if key matches completely + // we already know that pathRemainder is a prefix of keyRemainder, so checking the length sufficient + return + pathRemainderLength == keyRemainder.length() + ? _validateLastItem(decoded[1], proof_.length, i) + : (_emptyBytesMemory(), ProofError.MISMATCH_LEAF_PATH_KEY_REMAINDER); + } else { + return (_emptyBytesMemory(), ProofError.UNKNOWN_NODE_PREFIX); + } + } else { + return (_emptyBytesMemory(), ProofError.UNPARSEABLE_NODE); + } + } + // Reset memory before next iteration. Deallocates `decoded` and `path`. + Memory.unsafeSetFreeMemoryPointer(fmp); + } + + // If we've gone through all proof elements without finding a value, the proof is invalid + return (_emptyBytesMemory(), ProofError.INVALID_PROOF); + } + + /** + * @dev Validates that we've reached a valid leaf value and this is the last proof element. + * Ensures the value is not empty and no extra proof elements exist. + */ + function _validateLastItem( + Memory.Slice item, + uint256 trieProofLength, + uint256 i + ) private pure returns (bytes memory, ProofError) { + if (i != trieProofLength - 1) { + return (_emptyBytesMemory(), ProofError.INVALID_EXTRA_PROOF_ELEMENT); + } + bytes memory value = item.readBytes(); + return (value, value.length == 0 ? ProofError.EMPTY_VALUE : ProofError.NO_ERROR); + } + + /** + * @dev Extracts the node ID (hash or raw data based on size) + * + * For short nodes (encoded length < 32 bytes) the node ID is the node content itself, + * For larger nodes, the node ID is the hash of the encoded node data. + * + * [NOTE] + * ==== + * If a 32-byte input is provided (can occur with inline child references), it is used directly (like short nodes). + * When `nodeIdLength == 32`, inline processing is skipped. The next traversal step then checks whether the next + * node is large and its hash matches those raw bytes. If that is not the case, it returns {INVALID_LARGE_NODE}. + * + * If the input is empty (e.g. when traversing a branch node whose target child slot is empty, meaning the key + * does not exist in the trie), calling this function will panic with {ARRAY_OUT_OF_BOUNDS}. In practice, this + * never occurs because {readList} always returns slices with at least 1 byte (every RLP element includes its + * prefix byte, e.g., empty string is `0x80`). + * ==== + */ + function _getNodeId(Memory.Slice node) private pure returns (bytes32 nodeId, uint256 nodeIdLength) { + uint256 nodeLength = node.length(); + return nodeLength < 33 ? (node.load(0), nodeLength) : (node.readBytes32(), 32); + } + + function _emptyBytesMemory() private pure returns (bytes memory result) { + assembly ("memory-safe") { + result := 0x60 // mload(0x60) is always 0 + } + } + + function _match(Memory.Slice slice, bytes[] memory array, uint256 index) private pure returns (bool) { + return index < array.length && slice.equal(array[index].asSlice()); + } +} diff --git a/dependencies/@openzeppelin-contracts-5.5.0/utils/cryptography/WebAuthn.sol b/dependencies/@openzeppelin-contracts-5.7.0/utils/cryptography/WebAuthn.sol similarity index 91% rename from dependencies/@openzeppelin-contracts-5.5.0/utils/cryptography/WebAuthn.sol rename to dependencies/@openzeppelin-contracts-5.7.0/utils/cryptography/WebAuthn.sol index aa0c474..085a783 100644 --- a/dependencies/@openzeppelin-contracts-5.5.0/utils/cryptography/WebAuthn.sol +++ b/dependencies/@openzeppelin-contracts-5.7.0/utils/cryptography/WebAuthn.sol @@ -1,9 +1,10 @@ // SPDX-License-Identifier: MIT -// OpenZeppelin Contracts (last updated v5.5.0) (utils/cryptography/WebAuthn.sol) +// OpenZeppelin Contracts (last updated v5.6.0) (utils/cryptography/WebAuthn.sol) pragma solidity ^0.8.24; import {P256} from "./P256.sol"; +import {Math} from "../math/Math.sol"; import {Base64} from "../Base64.sol"; import {Bytes} from "../Bytes.sol"; import {Strings} from "../Strings.sol"; @@ -19,15 +20,18 @@ import {Strings} from "../Strings.sol"; * * For blockchain use cases, the following WebAuthn validations are intentionally omitted: * - * * Origin validation: Origin verification in `clientDataJSON` is omitted as blockchain - * contexts rely on authenticator and dapp frontend enforcement. Standard authenticators - * implement proper origin validation. + * * Origin validation: Origin verification in `clientDataJSON` is omitted. This check is the + * responsibility of the authenticator and does not have a meaningful on-chain use case; standard + * authenticators implement proper origin validation before signing. * * RP ID hash validation: Verification of `rpIdHash` in authenticatorData against expected - * RP ID hash is omitted. This is typically handled by platform-level security measures. - * Including an expiry timestamp in signed data is recommended for enhanced security. - * * Signature counter: Verification of signature counter increments is omitted. While - * useful for detecting credential cloning, on-chain operations typically include nonce - * protection, making this check redundant. + * RP ID hash is omitted. This check is the responsibility of the authenticator and does not have + * a meaningful on-chain use case; it is typically enforced at the platform level. + * * Signature counter: Verification of signature counter increments is omitted. The + * signature counter is maintained by authenticators per the WebAuthn spec to detect + * credential cloning, but validating it requires storing per-credential mutable state + * (the last seen counter value) which is impractical for most smart contract applications. + * Additionally, counter enforcement is primarily an authenticator responsibility, not a + * contract-level concern. * * Extension outputs: Extension output value verification is omitted as these are not * essential for core authentication security in blockchain applications. * * Attestation: Attestation object verification is omitted as this implementation @@ -156,7 +160,11 @@ library WebAuthn { // solhint-disable-next-line quotes string memory expectedChallenge = string.concat('"challenge":"', Base64.encodeURL(challenge), '"'); string memory actualChallenge = string( - Bytes.slice(bytes(clientDataJSON), challengeIndex, challengeIndex + bytes(expectedChallenge).length) + Bytes.slice( + bytes(clientDataJSON), + challengeIndex, + Math.saturatingAdd(challengeIndex, bytes(expectedChallenge).length) + ) ); return Strings.equal(actualChallenge, expectedChallenge); diff --git a/dependencies/@openzeppelin-contracts-5.5.0/utils/cryptography/draft-ERC7739Utils.sol b/dependencies/@openzeppelin-contracts-5.7.0/utils/cryptography/draft-ERC7739Utils.sol similarity index 90% rename from dependencies/@openzeppelin-contracts-5.5.0/utils/cryptography/draft-ERC7739Utils.sol rename to dependencies/@openzeppelin-contracts-5.7.0/utils/cryptography/draft-ERC7739Utils.sol index 94fd1b6..ce2018f 100644 --- a/dependencies/@openzeppelin-contracts-5.5.0/utils/cryptography/draft-ERC7739Utils.sol +++ b/dependencies/@openzeppelin-contracts-5.7.0/utils/cryptography/draft-ERC7739Utils.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -// OpenZeppelin Contracts (last updated v5.5.0) (utils/cryptography/draft-ERC7739Utils.sol) +// OpenZeppelin Contracts (last updated v5.7.0) (utils/cryptography/draft-ERC7739Utils.sol) pragma solidity ^0.8.20; @@ -62,7 +62,6 @@ library ERC7739Utils { * - `contentsDescr` is a descriptor of the "contents" part of 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 @@ -99,7 +98,7 @@ library ERC7739Utils { * 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. + * This is used to simulate the `personal_sign` RPC method in the context of smart contracts. */ function personalSignStructHash(bytes32 contents) internal pure returns (bytes32) { return Hashes.efficientKeccak256(PERSONAL_SIGN_TYPEHASH, contents); @@ -109,6 +108,11 @@ library ERC7739Utils { * @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. + * + * NOTE: Returns `bytes32(0)` when `contentsName` is empty. Since {decodeContentsDescr} yields an empty + * `contentsName` for both empty and malformed descriptors, callers must either sanitize the input so an empty + * `contentsName` is never passed, or reject the `bytes32(0)` return before signing/verifying. Combining it + * with any domain separator produces a struct hash that no longer binds `contentsHash` nor `domainBytes`. */ function typedDataSignStructHash( string calldata contentsName, @@ -127,6 +131,9 @@ library ERC7739Utils { /** * @dev Variant of {typedDataSignStructHash-string-string-bytes32-bytes} that takes a content descriptor * and decodes the `contentsName` and `contentsType` out of it. + * + * NOTE: Returns `bytes32(0)` when `contentsDescr` is empty or malformed (i.e. {decodeContentsDescr} yields + * an empty `contentsName`). See {typedDataSignStructHash-string-string-bytes32-bytes} for the caller's obligation. */ function typedDataSignStructHash( string calldata contentsDescr, @@ -163,7 +170,7 @@ library ERC7739Utils { * 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 + * If the `contentsDescr` is invalid, this returns empty strings. Otherwise, the return strings have non-zero * length. */ function decodeContentsDescr( diff --git a/dependencies/@openzeppelin-contracts-5.5.0/utils/cryptography/signers/AbstractSigner.sol b/dependencies/@openzeppelin-contracts-5.7.0/utils/cryptography/signers/AbstractSigner.sol similarity index 100% rename from dependencies/@openzeppelin-contracts-5.5.0/utils/cryptography/signers/AbstractSigner.sol rename to dependencies/@openzeppelin-contracts-5.7.0/utils/cryptography/signers/AbstractSigner.sol diff --git a/dependencies/@openzeppelin-contracts-5.5.0/utils/cryptography/signers/MultiSignerERC7913.sol b/dependencies/@openzeppelin-contracts-5.7.0/utils/cryptography/signers/MultiSignerERC7913.sol similarity index 67% rename from dependencies/@openzeppelin-contracts-5.5.0/utils/cryptography/signers/MultiSignerERC7913.sol rename to dependencies/@openzeppelin-contracts-5.7.0/utils/cryptography/signers/MultiSignerERC7913.sol index f485409..b93fdd9 100644 --- a/dependencies/@openzeppelin-contracts-5.5.0/utils/cryptography/signers/MultiSignerERC7913.sol +++ b/dependencies/@openzeppelin-contracts-5.7.0/utils/cryptography/signers/MultiSignerERC7913.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -// OpenZeppelin Contracts (last updated v5.4.0) (utils/cryptography/signers/MultiSignerERC7913.sol) +// OpenZeppelin Contracts (last updated v5.7.0) (utils/cryptography/signers/MultiSignerERC7913.sol) pragma solidity ^0.8.26; @@ -114,6 +114,13 @@ abstract contract MultiSignerERC7913 is AbstractSigner { * * * 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. + * + * NOTE: This function does not validate that signers are controlled or represent appropriate entities. Integrators + * must ensure signers are properly validated before adding them. Problematic signers can compromise + * the multisig's security or functionality. Examples include uncontrolled addresses (e.g., `address(0)`), + * the account's own address (which may cause recursive validation loops), or contracts that may unintentionally + * allow arbitrary validation (e.g. using the identity precompile at `address(0x04)`, which would return the + * ERC-1271 magic value for any `isValidSignature` call). */ function _addSigners(bytes[] memory newSigners) internal virtual { for (uint256 i = 0; i < newSigners.length; ++i) { @@ -214,8 +221,10 @@ abstract contract MultiSignerERC7913 is AbstractSigner { 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); + (bool success, bytes[] calldata signers, bytes[] calldata signatures) = _tryDecodeMultisignatureCalldata( + signature + ); + return success && _validateThreshold(signers) && _validateSignatures(hash, signers, signatures); } /** @@ -231,8 +240,8 @@ abstract contract MultiSignerERC7913 is AbstractSigner { */ function _validateSignatures( bytes32 hash, - bytes[] memory signers, - bytes[] memory signatures + bytes[] calldata signers, + bytes[] calldata signatures ) internal view virtual returns (bool valid) { for (uint256 i = 0; i < signers.length; ++i) { if (!isSigner(signers[i])) { @@ -246,7 +255,77 @@ abstract contract MultiSignerERC7913 is AbstractSigner { * @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) { + function _validateThreshold(bytes[] calldata validatingSigners) internal view virtual returns (bool) { return validatingSigners.length >= threshold(); } + + /** + * @dev Decodes an `abi.encode(bytes[], bytes[])` multisignature payload from calldata without memory + * allocation. Returns `success = false` on malformed encoding so callers can report an invalid + * signature instead of reverting during validation (see ERC-4337 `SIG_VALIDATION_FAILED` semantics). + */ + function _tryDecodeMultisignatureCalldata( + bytes calldata signature + ) private pure returns (bool success, bytes[] calldata signers, bytes[] calldata signatures) { + unchecked { + uint256 bufferLength = signature.length; + + // Check #1: Theoretical minimum length of a valid multisignature encoding is 0x40 bytes. + // 64 bytes of zero is a valid encoding for two empty arrays. + if (bufferLength < 0x40) return (false, _emptyBytesArray(), _emptyBytesArray()); + + // Read the offset pointers to the signers and signatures arrays + // Read is done in assembly to avoid the cost of creating calldata slices. + uint256 signersOffset; + uint256 signaturesOffset; + assembly ("memory-safe") { + signersOffset := calldataload(signature.offset) + signaturesOffset := calldataload(add(signature.offset, 0x20)) + } + + // Check #2: The length fields that the offset pointers point to must be within the bounds of the buffer. + if (signersOffset > bufferLength - 0x20 || signaturesOffset > bufferLength - 0x20) + return (false, _emptyBytesArray(), _emptyBytesArray()); + + // Read the length fields + // Read is done in assembly to avoid the cost of creating calldata slices. + uint256 signersLength; + uint256 signaturesLength; + assembly ("memory-safe") { + signersLength := calldataload(add(signature.offset, signersOffset)) + signaturesLength := calldataload(add(signature.offset, signaturesOffset)) + } + + // Data is just after the length fields + uint256 signersDataOffset = signersOffset + 0x20; + uint256 signaturesDataOffset = signaturesOffset + 0x20; + + // Check #3 & #4: + // - Cap lengths at 2**64-1 (Solidity's own dynamic-array limit) so `length * 0x20` cannot overflow. + // - The data for each array must fit within the bounds of the buffer. + if ( + signersLength > type(uint64).max || + signaturesLength > type(uint64).max || + 0x20 * signersLength > bufferLength - signersDataOffset || + 0x20 * signaturesLength > bufferLength - signaturesDataOffset + ) return (false, _emptyBytesArray(), _emptyBytesArray()); + + // Assembly cast + assembly ("memory-safe") { + success := 1 // true + signers.offset := add(signature.offset, signersDataOffset) + signers.length := signersLength + signatures.offset := add(signature.offset, signaturesDataOffset) + signatures.length := signaturesLength + } + } + } + + /// @dev Returns an empty `bytes[]` calldata slice, used as a placeholder on decode failure. + function _emptyBytesArray() private pure returns (bytes[] calldata result) { + assembly ("memory-safe") { + result.offset := 0 + result.length := 0 + } + } } diff --git a/dependencies/@openzeppelin-contracts-5.5.0/utils/cryptography/signers/MultiSignerERC7913Weighted.sol b/dependencies/@openzeppelin-contracts-5.7.0/utils/cryptography/signers/MultiSignerERC7913Weighted.sol similarity index 98% rename from dependencies/@openzeppelin-contracts-5.5.0/utils/cryptography/signers/MultiSignerERC7913Weighted.sol rename to dependencies/@openzeppelin-contracts-5.7.0/utils/cryptography/signers/MultiSignerERC7913Weighted.sol index 653272f..55ee696 100644 --- a/dependencies/@openzeppelin-contracts-5.5.0/utils/cryptography/signers/MultiSignerERC7913Weighted.sol +++ b/dependencies/@openzeppelin-contracts-5.7.0/utils/cryptography/signers/MultiSignerERC7913Weighted.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -// OpenZeppelin Contracts (last updated v5.4.0) (utils/cryptography/signers/MultiSignerERC7913Weighted.sol) +// OpenZeppelin Contracts (last updated v5.7.0) (utils/cryptography/signers/MultiSignerERC7913Weighted.sol) pragma solidity ^0.8.26; @@ -195,7 +195,7 @@ abstract contract MultiSignerERC7913Weighted is MultiSignerERC7913 { * 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) { + function _validateThreshold(bytes[] calldata signers) internal view virtual override returns (bool) { unchecked { uint64 weight = 0; for (uint256 i = 0; i < signers.length; ++i) { diff --git a/dependencies/@openzeppelin-contracts-5.5.0/utils/cryptography/signers/SignerECDSA.sol b/dependencies/@openzeppelin-contracts-5.7.0/utils/cryptography/signers/SignerECDSA.sol similarity index 90% rename from dependencies/@openzeppelin-contracts-5.5.0/utils/cryptography/signers/SignerECDSA.sol rename to dependencies/@openzeppelin-contracts-5.7.0/utils/cryptography/signers/SignerECDSA.sol index 517cd7e..3857bd7 100644 --- a/dependencies/@openzeppelin-contracts-5.5.0/utils/cryptography/signers/SignerECDSA.sol +++ b/dependencies/@openzeppelin-contracts-5.7.0/utils/cryptography/signers/SignerECDSA.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -// OpenZeppelin Contracts (last updated v5.4.0) (utils/cryptography/signers/SignerECDSA.sol) +// OpenZeppelin Contracts (last updated v5.7.0) (utils/cryptography/signers/SignerECDSA.sol) pragma solidity ^0.8.20; @@ -50,7 +50,7 @@ abstract contract SignerECDSA is AbstractSigner { 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; + (address recovered, ECDSA.RecoverError err, ) = ECDSA.tryRecoverCalldata(hash, signature); + return err == ECDSA.RecoverError.NoError && signer() == recovered; } } diff --git a/dependencies/@openzeppelin-contracts-5.5.0/utils/cryptography/signers/SignerEIP7702.sol b/dependencies/@openzeppelin-contracts-5.7.0/utils/cryptography/signers/SignerEIP7702.sol similarity index 83% rename from dependencies/@openzeppelin-contracts-5.5.0/utils/cryptography/signers/SignerEIP7702.sol rename to dependencies/@openzeppelin-contracts-5.7.0/utils/cryptography/signers/SignerEIP7702.sol index a129445..10d199f 100644 --- a/dependencies/@openzeppelin-contracts-5.5.0/utils/cryptography/signers/SignerEIP7702.sol +++ b/dependencies/@openzeppelin-contracts-5.7.0/utils/cryptography/signers/SignerEIP7702.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -// OpenZeppelin Contracts (last updated v5.5.0) (utils/cryptography/signers/SignerEIP7702.sol) +// OpenZeppelin Contracts (last updated v5.6.0) (utils/cryptography/signers/SignerEIP7702.sol) pragma solidity ^0.8.20; @@ -7,7 +7,7 @@ import {AbstractSigner} from "./AbstractSigner.sol"; import {ECDSA} from "../ECDSA.sol"; /** - * @dev Implementation of {AbstractSigner} for implementation for an EOA. Useful for ERC-7702 accounts. + * @dev Implementation of {AbstractSigner} for implementation for an EOA. Useful for EIP-7702 accounts. * * @custom:stateless */ @@ -19,7 +19,7 @@ abstract contract SignerEIP7702 is AbstractSigner { bytes32 hash, bytes calldata signature ) internal view virtual override returns (bool) { - (address recovered, ECDSA.RecoverError err, ) = ECDSA.tryRecover(hash, signature); + (address recovered, ECDSA.RecoverError err, ) = ECDSA.tryRecoverCalldata(hash, signature); return address(this) == recovered && err == ECDSA.RecoverError.NoError; } } diff --git a/dependencies/@openzeppelin-contracts-5.5.0/utils/cryptography/signers/SignerERC7913.sol b/dependencies/@openzeppelin-contracts-5.7.0/utils/cryptography/signers/SignerERC7913.sol similarity index 100% rename from dependencies/@openzeppelin-contracts-5.5.0/utils/cryptography/signers/SignerERC7913.sol rename to dependencies/@openzeppelin-contracts-5.7.0/utils/cryptography/signers/SignerERC7913.sol diff --git a/dependencies/@openzeppelin-contracts-5.5.0/utils/cryptography/signers/SignerP256.sol b/dependencies/@openzeppelin-contracts-5.7.0/utils/cryptography/signers/SignerP256.sol similarity index 100% rename from dependencies/@openzeppelin-contracts-5.5.0/utils/cryptography/signers/SignerP256.sol rename to dependencies/@openzeppelin-contracts-5.7.0/utils/cryptography/signers/SignerP256.sol diff --git a/dependencies/@openzeppelin-contracts-5.5.0/utils/cryptography/signers/SignerRSA.sol b/dependencies/@openzeppelin-contracts-5.7.0/utils/cryptography/signers/SignerRSA.sol similarity index 100% rename from dependencies/@openzeppelin-contracts-5.5.0/utils/cryptography/signers/SignerRSA.sol rename to dependencies/@openzeppelin-contracts-5.7.0/utils/cryptography/signers/SignerRSA.sol diff --git a/dependencies/@openzeppelin-contracts-5.5.0/utils/cryptography/signers/SignerWebAuthn.sol b/dependencies/@openzeppelin-contracts-5.7.0/utils/cryptography/signers/SignerWebAuthn.sol similarity index 67% rename from dependencies/@openzeppelin-contracts-5.5.0/utils/cryptography/signers/SignerWebAuthn.sol rename to dependencies/@openzeppelin-contracts-5.7.0/utils/cryptography/signers/SignerWebAuthn.sol index 7352950..53d3137 100644 --- a/dependencies/@openzeppelin-contracts-5.5.0/utils/cryptography/signers/SignerWebAuthn.sol +++ b/dependencies/@openzeppelin-contracts-5.7.0/utils/cryptography/signers/SignerWebAuthn.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -// OpenZeppelin Contracts (last updated v5.5.0) (utils/cryptography/signers/SignerWebAuthn.sol) +// OpenZeppelin Contracts (last updated v5.7.0) (utils/cryptography/signers/SignerWebAuthn.sol) pragma solidity ^0.8.24; @@ -10,8 +10,7 @@ import {WebAuthn} from "../WebAuthn.sol"; * @dev Implementation of {SignerP256} that supports WebAuthn authentication assertions. * * This contract enables signature validation using WebAuthn authentication assertions, - * leveraging the P256 public key stored in the contract. It allows for both WebAuthn - * and raw P256 signature validation, providing compatibility with both signature types. + * leveraging the P256 public key stored in the contract. * * The signature is expected to be an abi-encoded {WebAuthn-WebAuthnAuth} struct. * @@ -32,20 +31,15 @@ abstract contract SignerWebAuthn is SignerP256 { /** * @dev Validates a raw signature using the WebAuthn authentication assertion. * - * In case the signature can't be validated, it falls back to the - * {SignerP256-_rawSignatureValidation} method for raw P256 signature validation by passing - * the raw `r` and `s` values from the signature. + * Returns `false` if the signature is not a valid WebAuthn authentication assertion. */ function _rawSignatureValidation( bytes32 hash, bytes calldata signature ) internal view virtual override returns (bool) { - (bytes32 qx, bytes32 qy) = signer(); (bool decodeSuccess, WebAuthn.WebAuthnAuth calldata auth) = WebAuthn.tryDecodeAuth(signature); - - return - decodeSuccess - ? WebAuthn.verify(abi.encodePacked(hash), auth, qx, qy) - : super._rawSignatureValidation(hash, signature); + if (!decodeSuccess) return false; + (bytes32 qx, bytes32 qy) = signer(); + return WebAuthn.verify(abi.encodePacked(hash), auth, qx, qy); } } diff --git a/dependencies/@openzeppelin-contracts-5.5.0/utils/cryptography/signers/draft-ERC7739.sol b/dependencies/@openzeppelin-contracts-5.7.0/utils/cryptography/signers/draft-ERC7739.sol similarity index 88% rename from dependencies/@openzeppelin-contracts-5.5.0/utils/cryptography/signers/draft-ERC7739.sol rename to dependencies/@openzeppelin-contracts-5.7.0/utils/cryptography/signers/draft-ERC7739.sol index 4552464..09cef8c 100644 --- a/dependencies/@openzeppelin-contracts-5.5.0/utils/cryptography/signers/draft-ERC7739.sol +++ b/dependencies/@openzeppelin-contracts-5.7.0/utils/cryptography/signers/draft-ERC7739.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -// OpenZeppelin Contracts (last updated v5.5.0) (utils/cryptography/signers/draft-ERC7739.sol) +// OpenZeppelin Contracts (last updated v5.7.0) (utils/cryptography/signers/draft-ERC7739.sol) pragma solidity ^0.8.24; @@ -69,30 +69,31 @@ abstract contract ERC7739 is AbstractSigner, EIP712, IERC1271 { string calldata contentsDescr ) = encodedSignature.decodeTypedDataSig(); - ( - , - string memory name, - string memory version, - uint256 chainId, - address verifyingContract, - bytes32 salt, - - ) = eip712Domain(); + (string calldata contentsName, string calldata contentsType) = contentsDescr.decodeContentsDescr(); // Check that contentHash and separator are correct // Rebuild nested hash return hash == appSeparator.toTypedDataHash(contentsHash) && - bytes(contentsDescr).length != 0 && + bytes(contentsName).length != 0 && _rawSignatureValidation( appSeparator.toTypedDataHash( - ERC7739Utils.typedDataSignStructHash( - contentsDescr, - contentsHash, - abi.encode(keccak256(bytes(name)), keccak256(bytes(version)), chainId, verifyingContract, salt) - ) + ERC7739Utils.typedDataSignStructHash(contentsName, contentsType, contentsHash, _buildDomainBytes()) ), signature ); } + + function _buildDomainBytes() private view returns (bytes memory) { + ( + , + string memory name, + string memory version, + uint256 chainId, + address verifyingContract, + bytes32 salt, + + ) = eip712Domain(); + return abi.encode(keccak256(bytes(name)), keccak256(bytes(version)), chainId, verifyingContract, salt); + } } diff --git a/dependencies/@openzeppelin-contracts-5.5.0/utils/cryptography/verifiers/ERC7913P256Verifier.sol b/dependencies/@openzeppelin-contracts-5.7.0/utils/cryptography/verifiers/ERC7913P256Verifier.sol similarity index 100% rename from dependencies/@openzeppelin-contracts-5.5.0/utils/cryptography/verifiers/ERC7913P256Verifier.sol rename to dependencies/@openzeppelin-contracts-5.7.0/utils/cryptography/verifiers/ERC7913P256Verifier.sol diff --git a/dependencies/@openzeppelin-contracts-5.5.0/utils/cryptography/verifiers/ERC7913RSAVerifier.sol b/dependencies/@openzeppelin-contracts-5.7.0/utils/cryptography/verifiers/ERC7913RSAVerifier.sol similarity index 100% rename from dependencies/@openzeppelin-contracts-5.5.0/utils/cryptography/verifiers/ERC7913RSAVerifier.sol rename to dependencies/@openzeppelin-contracts-5.7.0/utils/cryptography/verifiers/ERC7913RSAVerifier.sol diff --git a/dependencies/@openzeppelin-contracts-5.5.0/utils/cryptography/verifiers/ERC7913WebAuthnVerifier.sol b/dependencies/@openzeppelin-contracts-5.7.0/utils/cryptography/verifiers/ERC7913WebAuthnVerifier.sol similarity index 73% rename from dependencies/@openzeppelin-contracts-5.5.0/utils/cryptography/verifiers/ERC7913WebAuthnVerifier.sol rename to dependencies/@openzeppelin-contracts-5.7.0/utils/cryptography/verifiers/ERC7913WebAuthnVerifier.sol index 3542860..8fe3700 100644 --- a/dependencies/@openzeppelin-contracts-5.5.0/utils/cryptography/verifiers/ERC7913WebAuthnVerifier.sol +++ b/dependencies/@openzeppelin-contracts-5.7.0/utils/cryptography/verifiers/ERC7913WebAuthnVerifier.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -// OpenZeppelin Contracts (last updated v5.5.0) (utils/cryptography/verifiers/ERC7913WebAuthnVerifier.sol) +// OpenZeppelin Contracts (last updated v5.7.0) (utils/cryptography/verifiers/ERC7913WebAuthnVerifier.sol) pragma solidity ^0.8.24; @@ -13,7 +13,7 @@ import {IERC7913SignatureVerifier} from "../../../interfaces/IERC7913.sol"; * The key is expected to be a 64-byte concatenation of the P256 public key coordinates (qx || qy). * The signature is expected to be an abi-encoded {WebAuthn-WebAuthnAuth} struct. * - * Uses {WebAuthn-verifyMinimal} for signature verification, which performs the essential + * Uses {WebAuthn-verify} for signature verification, which performs the essential * WebAuthn checks: type validation, challenge matching, and cryptographic signature verification. * * NOTE: Wallets that may require default P256 validation may install a P256 verifier separately. @@ -28,8 +28,18 @@ contract ERC7913WebAuthnVerifier is IERC7913SignatureVerifier { return decodeSuccess && key.length == 0x40 && - WebAuthn.verify(abi.encodePacked(hash), auth, bytes32(key[0x00:0x20]), bytes32(key[0x20:0x40])) + WebAuthn.verify( + abi.encodePacked(hash), + auth, + bytes32(key[0x00:0x20]), + bytes32(key[0x20:0x40]), + _requireUV() + ) ? IERC7913SignatureVerifier.verify.selector : bytes4(0xFFFFFFFF); } + + function _requireUV() internal pure virtual returns (bool) { + return true; + } } diff --git a/dependencies/@openzeppelin-contracts-5.5.0/utils/draft-InteroperableAddress.sol b/dependencies/@openzeppelin-contracts-5.7.0/utils/draft-InteroperableAddress.sol similarity index 86% rename from dependencies/@openzeppelin-contracts-5.5.0/utils/draft-InteroperableAddress.sol rename to dependencies/@openzeppelin-contracts-5.7.0/utils/draft-InteroperableAddress.sol index d00cc6d..6aceff0 100644 --- a/dependencies/@openzeppelin-contracts-5.5.0/utils/draft-InteroperableAddress.sol +++ b/dependencies/@openzeppelin-contracts-5.7.0/utils/draft-InteroperableAddress.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -// OpenZeppelin Contracts (last updated v5.5.0) (utils/draft-InteroperableAddress.sol) +// OpenZeppelin Contracts (last updated v5.7.0) (utils/draft-InteroperableAddress.sol) pragma solidity ^0.8.26; @@ -66,8 +66,11 @@ library InteroperableAddress { } /** - * @dev Parse a ERC-7930 interoperable address (version 1) into its different components. Reverts if the input is - * not following a version 1 of ERC-7930 + * @dev Parse an ERC-7930 interoperable address (version 1) into its different components. Reverts if the input is + * not following a version 1 of ERC-7930. + * + * NOTE: Trailing bytes after a valid v1 encoding are ignored. The same decoded address may therefore correspond + * to multiple distinct input byte strings. */ function parseV1( bytes memory self @@ -96,22 +99,24 @@ library InteroperableAddress { bytes memory self ) internal pure returns (bool success, bytes2 chainType, bytes memory chainReference, bytes memory addr) { unchecked { - success = true; if (self.length < 0x06) return (false, 0x0000, _emptyBytesMemory(), _emptyBytesMemory()); bytes2 version = _readBytes2(self, 0x00); if (version != bytes2(0x0001)) return (false, 0x0000, _emptyBytesMemory(), _emptyBytesMemory()); - chainType = _readBytes2(self, 0x02); - uint8 chainReferenceLength = uint8(self[0x04]); + uint256 chainReferenceLength = uint8(self[0x04]); if (self.length < 0x06 + chainReferenceLength) return (false, 0x0000, _emptyBytesMemory(), _emptyBytesMemory()); chainReference = self.slice(0x05, 0x05 + chainReferenceLength); - uint8 addrLength = uint8(self[0x05 + chainReferenceLength]); + uint256 addrLength = uint8(self[0x05 + chainReferenceLength]); if (self.length < 0x06 + chainReferenceLength + addrLength) return (false, 0x0000, _emptyBytesMemory(), _emptyBytesMemory()); addr = self.slice(0x06 + chainReferenceLength, 0x06 + chainReferenceLength + addrLength); + + // At least one of chainReference or addr must be non-empty + success = (chainReferenceLength > 0) || (addrLength > 0); + chainType = success ? _readBytes2(self, 0x02) : bytes2(0); } } @@ -122,29 +127,34 @@ library InteroperableAddress { bytes calldata self ) internal pure returns (bool success, bytes2 chainType, bytes calldata chainReference, bytes calldata addr) { unchecked { - success = true; if (self.length < 0x06) return (false, 0x0000, Calldata.emptyBytes(), Calldata.emptyBytes()); bytes2 version = _readBytes2Calldata(self, 0x00); if (version != bytes2(0x0001)) return (false, 0x0000, Calldata.emptyBytes(), Calldata.emptyBytes()); - chainType = _readBytes2Calldata(self, 0x02); - uint8 chainReferenceLength = uint8(self[0x04]); + uint256 chainReferenceLength = uint8(self[0x04]); if (self.length < 0x06 + chainReferenceLength) return (false, 0x0000, Calldata.emptyBytes(), Calldata.emptyBytes()); chainReference = self[0x05:0x05 + chainReferenceLength]; - uint8 addrLength = uint8(self[0x05 + chainReferenceLength]); + uint256 addrLength = uint8(self[0x05 + chainReferenceLength]); if (self.length < 0x06 + chainReferenceLength + addrLength) return (false, 0x0000, Calldata.emptyBytes(), Calldata.emptyBytes()); addr = self[0x06 + chainReferenceLength:0x06 + chainReferenceLength + addrLength]; + + // At least one of chainReference or addr must be non-empty + success = (chainReferenceLength > 0) || (addrLength > 0); + chainType = success ? _readBytes2Calldata(self, 0x02) : bytes2(0); } } /** - * @dev Parse a ERC-7930 interoperable address (version 1) corresponding to an EIP-155 chain. The `chainId` and + * @dev Parse an ERC-7930 interoperable address (version 1) corresponding to an EIP-155 chain. The `chainId` and * `addr` return values will be zero if the input doesn't include a chainReference or an address, respectively. * + * NOTE: Trailing bytes after a valid v1 encoding are ignored. The same decoded (chainId, addr) may therefore + * correspond to multiple distinct input byte strings. + * * Requirements: * * * The input must be a valid ERC-7930 interoperable address (version 1) diff --git a/dependencies/@openzeppelin-contracts-5.5.0/utils/introspection/ERC165.sol b/dependencies/@openzeppelin-contracts-5.7.0/utils/introspection/ERC165.sol similarity index 100% rename from dependencies/@openzeppelin-contracts-5.5.0/utils/introspection/ERC165.sol rename to dependencies/@openzeppelin-contracts-5.7.0/utils/introspection/ERC165.sol diff --git a/dependencies/@openzeppelin-contracts-5.5.0/utils/introspection/ERC165Checker.sol b/dependencies/@openzeppelin-contracts-5.7.0/utils/introspection/ERC165Checker.sol similarity index 97% rename from dependencies/@openzeppelin-contracts-5.5.0/utils/introspection/ERC165Checker.sol rename to dependencies/@openzeppelin-contracts-5.7.0/utils/introspection/ERC165Checker.sol index bfbfbad..f2c5ab2 100644 --- a/dependencies/@openzeppelin-contracts-5.5.0/utils/introspection/ERC165Checker.sol +++ b/dependencies/@openzeppelin-contracts-5.7.0/utils/introspection/ERC165Checker.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -// OpenZeppelin Contracts (last updated v5.5.0) (utils/introspection/ERC165Checker.sol) +// OpenZeppelin Contracts (last updated v5.6.0) (utils/introspection/ERC165Checker.sol) pragma solidity ^0.8.20; @@ -121,7 +121,7 @@ library ERC165Checker { * function. It returns: * * * `success`: true if the call didn't revert, false if it did - * * `supported`: true if the call succeeded AND returned data indicating the interface is supported + * * `supported`: true if the returned data indicating the interface is supported */ function _trySupportsInterface( address account, diff --git a/dependencies/@openzeppelin-contracts-5.5.0/utils/introspection/IERC165.sol b/dependencies/@openzeppelin-contracts-5.7.0/utils/introspection/IERC165.sol similarity index 100% rename from dependencies/@openzeppelin-contracts-5.5.0/utils/introspection/IERC165.sol rename to dependencies/@openzeppelin-contracts-5.7.0/utils/introspection/IERC165.sol diff --git a/dependencies/@openzeppelin-contracts-5.5.0/utils/math/Math.sol b/dependencies/@openzeppelin-contracts-5.7.0/utils/math/Math.sol similarity index 97% rename from dependencies/@openzeppelin-contracts-5.5.0/utils/math/Math.sol rename to dependencies/@openzeppelin-contracts-5.7.0/utils/math/Math.sol index 3c20905..e728859 100644 --- a/dependencies/@openzeppelin-contracts-5.5.0/utils/math/Math.sol +++ b/dependencies/@openzeppelin-contracts-5.7.0/utils/math/Math.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -// OpenZeppelin Contracts (last updated v5.5.0) (utils/math/Math.sol) +// OpenZeppelin Contracts (last updated v5.6.0) (utils/math/Math.sol) pragma solidity ^0.8.20; @@ -168,8 +168,10 @@ library Math { * zero. */ function average(uint256 a, uint256 b) internal pure returns (uint256) { - // (a + b) / 2 can overflow. - return (a & b) + (a ^ b) / 2; + unchecked { + // (a + b) / 2 can overflow. + return (a & b) + (a ^ b) / 2; + } } /** @@ -473,9 +475,14 @@ library Math { /** * @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) { + function _zeroBytes(bytes memory buffer) private pure returns (bool) { + uint256 chunk; + for (uint256 i = 0; i < buffer.length; i += 0x20) { + // See _unsafeReadBytesOffset from utils/Bytes.sol + assembly ("memory-safe") { + chunk := mload(add(add(buffer, 0x20), i)) + } + if (chunk >> (8 * saturatingSub(i + 0x20, buffer.length)) != 0) { return false; } } @@ -644,7 +651,7 @@ library Math { // | 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. + // The lookup table is represented as a 32-byte value with the MSB positions for 0-15 in the first 16 bytes (most significant half). assembly ("memory-safe") { r := or(r, byte(shr(r, x), 0x0000010102020202030303030303030300000000000000000000000000000000)) } diff --git a/dependencies/@openzeppelin-contracts-5.5.0/utils/math/SafeCast.sol b/dependencies/@openzeppelin-contracts-5.7.0/utils/math/SafeCast.sol similarity index 99% rename from dependencies/@openzeppelin-contracts-5.5.0/utils/math/SafeCast.sol rename to dependencies/@openzeppelin-contracts-5.7.0/utils/math/SafeCast.sol index b345ede..ccb979f 100644 --- a/dependencies/@openzeppelin-contracts-5.5.0/utils/math/SafeCast.sol +++ b/dependencies/@openzeppelin-contracts-5.7.0/utils/math/SafeCast.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -// OpenZeppelin Contracts (last updated v5.1.0) (utils/math/SafeCast.sol) +// OpenZeppelin Contracts (last updated v5.6.0) (utils/math/SafeCast.sol) // This file was procedurally generated from scripts/generate/templates/SafeCast.js. pragma solidity ^0.8.20; @@ -18,12 +18,12 @@ pragma solidity ^0.8.20; */ library SafeCast { /** - * @dev Value doesn't fit in an uint of `bits` size. + * @dev Value doesn't fit in a uint of `bits` size. */ error SafeCastOverflowedUintDowncast(uint8 bits, uint256 value); /** - * @dev An int value doesn't fit in an uint of `bits` size. + * @dev An int value doesn't fit in a uint of `bits` size. */ error SafeCastOverflowedIntToUint(int256 value); @@ -33,7 +33,7 @@ library SafeCast { error SafeCastOverflowedIntDowncast(uint8 bits, int256 value); /** - * @dev An uint value doesn't fit in an int of `bits` size. + * @dev A uint value doesn't fit in an int of `bits` size. */ error SafeCastOverflowedUintToInt(uint256 value); diff --git a/dependencies/@openzeppelin-contracts-5.5.0/utils/math/SignedMath.sol b/dependencies/@openzeppelin-contracts-5.7.0/utils/math/SignedMath.sol similarity index 100% rename from dependencies/@openzeppelin-contracts-5.5.0/utils/math/SignedMath.sol rename to dependencies/@openzeppelin-contracts-5.7.0/utils/math/SignedMath.sol diff --git a/dependencies/@openzeppelin-contracts-5.5.0/utils/structs/Accumulators.sol b/dependencies/@openzeppelin-contracts-5.7.0/utils/structs/Accumulators.sol similarity index 92% rename from dependencies/@openzeppelin-contracts-5.5.0/utils/structs/Accumulators.sol rename to dependencies/@openzeppelin-contracts-5.7.0/utils/structs/Accumulators.sol index 696d930..c53b2dd 100644 --- a/dependencies/@openzeppelin-contracts-5.5.0/utils/structs/Accumulators.sol +++ b/dependencies/@openzeppelin-contracts-5.7.0/utils/structs/Accumulators.sol @@ -1,9 +1,10 @@ // SPDX-License-Identifier: MIT -// OpenZeppelin Contracts (last updated v5.5.0) (utils/structs/Accumulators.sol) +// OpenZeppelin Contracts (last updated v5.6.0) (utils/structs/Accumulators.sol) pragma solidity ^0.8.24; import {Memory} from "../Memory.sol"; +import {Panic} from "../Panic.sol"; /** * @dev Structure concatenating an arbitrary number of bytes buffers with limited memory allocation. @@ -33,7 +34,7 @@ library Accumulators { /** * @dev Bytes accumulator: a linked list of `bytes`. * - * NOTE: This is a memory structure that SHOULD not be put in storage. + * NOTE: This is a memory structure that SHOULD NOT be put in storage. */ struct Accumulator { Memory.Pointer head; @@ -59,6 +60,8 @@ library Accumulators { /// @dev Add a memory slice to (the end of) an Accumulator function push(Accumulator memory self, Memory.Slice data) internal pure returns (Accumulator memory) { + if (!data.isReserved()) Panic.panic(Panic.RESOURCE_ERROR); + Memory.Pointer ptr = _asPtr(AccumulatorEntry({next: _nullPtr(), data: data})); if (_nullPtr().equal(self.head)) { @@ -79,6 +82,8 @@ library Accumulators { /// @dev Add a memory slice to (the beginning of) an Accumulator function shift(Accumulator memory self, Memory.Slice data) internal pure returns (Accumulator memory) { + if (!data.isReserved()) Panic.panic(Panic.RESOURCE_ERROR); + Memory.Pointer ptr = _asPtr(AccumulatorEntry({next: self.head, data: data})); if (_nullPtr().equal(self.head)) { @@ -125,6 +130,6 @@ library Accumulators { } function _nullPtr() private pure returns (Memory.Pointer) { - return Memory.asPointer(0x00); + return Memory.Pointer.wrap(0); } } diff --git a/dependencies/@openzeppelin-contracts-5.5.0/utils/structs/BitMaps.sol b/dependencies/@openzeppelin-contracts-5.7.0/utils/structs/BitMaps.sol similarity index 96% rename from dependencies/@openzeppelin-contracts-5.5.0/utils/structs/BitMaps.sol rename to dependencies/@openzeppelin-contracts-5.7.0/utils/structs/BitMaps.sol index 40cceb9..6958062 100644 --- a/dependencies/@openzeppelin-contracts-5.5.0/utils/structs/BitMaps.sol +++ b/dependencies/@openzeppelin-contracts-5.7.0/utils/structs/BitMaps.sol @@ -1,5 +1,6 @@ // SPDX-License-Identifier: MIT -// OpenZeppelin Contracts (last updated v5.0.0) (utils/structs/BitMaps.sol) +// OpenZeppelin Contracts (last updated v5.7.0) (utils/structs/BitMaps.sol) + pragma solidity ^0.8.20; /** diff --git a/dependencies/@openzeppelin-contracts-5.5.0/utils/structs/Checkpoints.sol b/dependencies/@openzeppelin-contracts-5.7.0/utils/structs/Checkpoints.sol similarity index 80% rename from dependencies/@openzeppelin-contracts-5.5.0/utils/structs/Checkpoints.sol rename to dependencies/@openzeppelin-contracts-5.7.0/utils/structs/Checkpoints.sol index 6f67317..b046a6a 100644 --- a/dependencies/@openzeppelin-contracts-5.5.0/utils/structs/Checkpoints.sol +++ b/dependencies/@openzeppelin-contracts-5.7.0/utils/structs/Checkpoints.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -// OpenZeppelin Contracts (last updated v5.5.0) (utils/structs/Checkpoints.sol) +// OpenZeppelin Contracts (last updated v5.7.0) (utils/structs/Checkpoints.sol) // This file was procedurally generated from scripts/generate/templates/Checkpoints.js. pragma solidity ^0.8.20; @@ -50,8 +50,8 @@ library Checkpoints { */ function lowerLookup(Trace256 storage self, uint256 key) internal view returns (uint256) { uint256 len = self._checkpoints.length; - uint256 pos = _lowerBinaryLookup(self._checkpoints, key, 0, len); - return pos == len ? 0 : _unsafeAccess(self._checkpoints, pos)._value; + uint256 index = _lowerBinaryLookup(self._checkpoints, key, 0, len); + return index == len ? 0 : _unsafeAccess(self._checkpoints, index)._value; } /** @@ -60,8 +60,8 @@ library Checkpoints { */ function upperLookup(Trace256 storage self, uint256 key) internal view returns (uint256) { uint256 len = self._checkpoints.length; - uint256 pos = _upperBinaryLookup(self._checkpoints, key, 0, len); - return pos == 0 ? 0 : _unsafeAccess(self._checkpoints, pos - 1)._value; + uint256 index = _upperBinaryLookup(self._checkpoints, key, 0, len); + return index == 0 ? 0 : _unsafeAccess(self._checkpoints, index - 1)._value; } /** @@ -86,17 +86,17 @@ library Checkpoints { } } - uint256 pos = _upperBinaryLookup(self._checkpoints, key, low, high); + uint256 index = _upperBinaryLookup(self._checkpoints, key, low, high); - return pos == 0 ? 0 : _unsafeAccess(self._checkpoints, pos - 1)._value; + return index == 0 ? 0 : _unsafeAccess(self._checkpoints, index - 1)._value; } /** * @dev Returns the value in the most recent checkpoint, or zero if there are no checkpoints. */ function latest(Trace256 storage self) internal view returns (uint256) { - uint256 pos = self._checkpoints.length; - return pos == 0 ? 0 : _unsafeAccess(self._checkpoints, pos - 1)._value; + uint256 len = self._checkpoints.length; + return len == 0 ? 0 : _unsafeAccess(self._checkpoints, len - 1)._value; } /** @@ -104,11 +104,11 @@ library Checkpoints { * in the most recent checkpoint. */ function latestCheckpoint(Trace256 storage self) internal view returns (bool exists, uint256 _key, uint256 _value) { - uint256 pos = self._checkpoints.length; - if (pos == 0) { + uint256 len = self._checkpoints.length; + if (len == 0) { return (false, 0, 0); } else { - Checkpoint256 storage ckpt = _unsafeAccess(self._checkpoints, pos - 1); + Checkpoint256 storage ckpt = _unsafeAccess(self._checkpoints, len - 1); return (true, ckpt._key, ckpt._value); } } @@ -122,9 +122,21 @@ library Checkpoints { /** * @dev Returns checkpoint at given position. + * + * IMPORTANT: Deprecated. This function's name clashes with a keyword scheduled for inclusion in Solidity. Developers + * should use {pos} instead. + */ + function at(Trace256 storage self, uint32 index) internal view returns (Checkpoint256 memory) { + return pos(self, index); + } + + /** + * @dev Returns checkpoint at given position. + * + * Replacement of the deprecated {at} function. */ - function at(Trace256 storage self, uint32 pos) internal view returns (Checkpoint256 memory) { - return self._checkpoints[pos]; + function pos(Trace256 storage self, uint32 index) internal view returns (Checkpoint256 memory) { + return self._checkpoints[index]; } /** @@ -136,10 +148,10 @@ library Checkpoints { uint256 key, uint256 value ) private returns (uint256 oldValue, uint256 newValue) { - uint256 pos = self.length; + uint256 len = self.length; - if (pos > 0) { - Checkpoint256 storage last = _unsafeAccess(self, pos - 1); + if (len > 0) { + Checkpoint256 storage last = _unsafeAccess(self, len - 1); uint256 lastKey = last._key; uint256 lastValue = last._value; @@ -214,11 +226,11 @@ library Checkpoints { */ function _unsafeAccess( Checkpoint256[] storage self, - uint256 pos + uint256 index ) private pure returns (Checkpoint256 storage result) { assembly { mstore(0x00, self.slot) - result.slot := add(keccak256(0x00, 0x20), mul(pos, 2)) + result.slot := add(keccak256(0x00, 0x20), mul(index, 2)) } } @@ -253,8 +265,8 @@ library Checkpoints { */ 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; + uint256 index = _lowerBinaryLookup(self._checkpoints, key, 0, len); + return index == len ? 0 : _unsafeAccess(self._checkpoints, index)._value; } /** @@ -263,8 +275,8 @@ library Checkpoints { */ 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; + uint256 index = _upperBinaryLookup(self._checkpoints, key, 0, len); + return index == 0 ? 0 : _unsafeAccess(self._checkpoints, index - 1)._value; } /** @@ -289,17 +301,17 @@ library Checkpoints { } } - uint256 pos = _upperBinaryLookup(self._checkpoints, key, low, high); + uint256 index = _upperBinaryLookup(self._checkpoints, key, low, high); - return pos == 0 ? 0 : _unsafeAccess(self._checkpoints, pos - 1)._value; + return index == 0 ? 0 : _unsafeAccess(self._checkpoints, index - 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; + uint256 len = self._checkpoints.length; + return len == 0 ? 0 : _unsafeAccess(self._checkpoints, len - 1)._value; } /** @@ -307,11 +319,11 @@ library Checkpoints { * 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) { + uint256 len = self._checkpoints.length; + if (len == 0) { return (false, 0, 0); } else { - Checkpoint224 storage ckpt = _unsafeAccess(self._checkpoints, pos - 1); + Checkpoint224 storage ckpt = _unsafeAccess(self._checkpoints, len - 1); return (true, ckpt._key, ckpt._value); } } @@ -325,9 +337,21 @@ library Checkpoints { /** * @dev Returns checkpoint at given position. + * + * IMPORTANT: Deprecated. This function's name clashes with a keyword scheduled for inclusion in Solidity. Developers + * should use {pos} instead. + */ + function at(Trace224 storage self, uint32 index) internal view returns (Checkpoint224 memory) { + return pos(self, index); + } + + /** + * @dev Returns checkpoint at given position. + * + * Replacement of the deprecated {at} function. */ - function at(Trace224 storage self, uint32 pos) internal view returns (Checkpoint224 memory) { - return self._checkpoints[pos]; + function pos(Trace224 storage self, uint32 index) internal view returns (Checkpoint224 memory) { + return self._checkpoints[index]; } /** @@ -339,10 +363,10 @@ library Checkpoints { uint32 key, uint224 value ) private returns (uint224 oldValue, uint224 newValue) { - uint256 pos = self.length; + uint256 len = self.length; - if (pos > 0) { - Checkpoint224 storage last = _unsafeAccess(self, pos - 1); + if (len > 0) { + Checkpoint224 storage last = _unsafeAccess(self, len - 1); uint32 lastKey = last._key; uint224 lastValue = last._value; @@ -417,11 +441,11 @@ library Checkpoints { */ function _unsafeAccess( Checkpoint224[] storage self, - uint256 pos + uint256 index ) private pure returns (Checkpoint224 storage result) { assembly { mstore(0x00, self.slot) - result.slot := add(keccak256(0x00, 0x20), pos) + result.slot := add(keccak256(0x00, 0x20), index) } } @@ -456,8 +480,8 @@ library Checkpoints { */ 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; + uint256 index = _lowerBinaryLookup(self._checkpoints, key, 0, len); + return index == len ? 0 : _unsafeAccess(self._checkpoints, index)._value; } /** @@ -466,8 +490,8 @@ library Checkpoints { */ 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; + uint256 index = _upperBinaryLookup(self._checkpoints, key, 0, len); + return index == 0 ? 0 : _unsafeAccess(self._checkpoints, index - 1)._value; } /** @@ -492,17 +516,17 @@ library Checkpoints { } } - uint256 pos = _upperBinaryLookup(self._checkpoints, key, low, high); + uint256 index = _upperBinaryLookup(self._checkpoints, key, low, high); - return pos == 0 ? 0 : _unsafeAccess(self._checkpoints, pos - 1)._value; + return index == 0 ? 0 : _unsafeAccess(self._checkpoints, index - 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; + uint256 len = self._checkpoints.length; + return len == 0 ? 0 : _unsafeAccess(self._checkpoints, len - 1)._value; } /** @@ -510,11 +534,11 @@ library Checkpoints { * 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) { + uint256 len = self._checkpoints.length; + if (len == 0) { return (false, 0, 0); } else { - Checkpoint208 storage ckpt = _unsafeAccess(self._checkpoints, pos - 1); + Checkpoint208 storage ckpt = _unsafeAccess(self._checkpoints, len - 1); return (true, ckpt._key, ckpt._value); } } @@ -528,9 +552,21 @@ library Checkpoints { /** * @dev Returns checkpoint at given position. + * + * IMPORTANT: Deprecated. This function's name clashes with a keyword scheduled for inclusion in Solidity. Developers + * should use {pos} instead. + */ + function at(Trace208 storage self, uint32 index) internal view returns (Checkpoint208 memory) { + return pos(self, index); + } + + /** + * @dev Returns checkpoint at given position. + * + * Replacement of the deprecated {at} function. */ - function at(Trace208 storage self, uint32 pos) internal view returns (Checkpoint208 memory) { - return self._checkpoints[pos]; + function pos(Trace208 storage self, uint32 index) internal view returns (Checkpoint208 memory) { + return self._checkpoints[index]; } /** @@ -542,10 +578,10 @@ library Checkpoints { uint48 key, uint208 value ) private returns (uint208 oldValue, uint208 newValue) { - uint256 pos = self.length; + uint256 len = self.length; - if (pos > 0) { - Checkpoint208 storage last = _unsafeAccess(self, pos - 1); + if (len > 0) { + Checkpoint208 storage last = _unsafeAccess(self, len - 1); uint48 lastKey = last._key; uint208 lastValue = last._value; @@ -620,11 +656,11 @@ library Checkpoints { */ function _unsafeAccess( Checkpoint208[] storage self, - uint256 pos + uint256 index ) private pure returns (Checkpoint208 storage result) { assembly { mstore(0x00, self.slot) - result.slot := add(keccak256(0x00, 0x20), pos) + result.slot := add(keccak256(0x00, 0x20), index) } } @@ -659,8 +695,8 @@ library Checkpoints { */ 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; + uint256 index = _lowerBinaryLookup(self._checkpoints, key, 0, len); + return index == len ? 0 : _unsafeAccess(self._checkpoints, index)._value; } /** @@ -669,8 +705,8 @@ library Checkpoints { */ 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; + uint256 index = _upperBinaryLookup(self._checkpoints, key, 0, len); + return index == 0 ? 0 : _unsafeAccess(self._checkpoints, index - 1)._value; } /** @@ -695,17 +731,17 @@ library Checkpoints { } } - uint256 pos = _upperBinaryLookup(self._checkpoints, key, low, high); + uint256 index = _upperBinaryLookup(self._checkpoints, key, low, high); - return pos == 0 ? 0 : _unsafeAccess(self._checkpoints, pos - 1)._value; + return index == 0 ? 0 : _unsafeAccess(self._checkpoints, index - 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; + uint256 len = self._checkpoints.length; + return len == 0 ? 0 : _unsafeAccess(self._checkpoints, len - 1)._value; } /** @@ -713,11 +749,11 @@ library Checkpoints { * 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) { + uint256 len = self._checkpoints.length; + if (len == 0) { return (false, 0, 0); } else { - Checkpoint160 storage ckpt = _unsafeAccess(self._checkpoints, pos - 1); + Checkpoint160 storage ckpt = _unsafeAccess(self._checkpoints, len - 1); return (true, ckpt._key, ckpt._value); } } @@ -731,9 +767,21 @@ library Checkpoints { /** * @dev Returns checkpoint at given position. + * + * IMPORTANT: Deprecated. This function's name clashes with a keyword scheduled for inclusion in Solidity. Developers + * should use {pos} instead. + */ + function at(Trace160 storage self, uint32 index) internal view returns (Checkpoint160 memory) { + return pos(self, index); + } + + /** + * @dev Returns checkpoint at given position. + * + * Replacement of the deprecated {at} function. */ - function at(Trace160 storage self, uint32 pos) internal view returns (Checkpoint160 memory) { - return self._checkpoints[pos]; + function pos(Trace160 storage self, uint32 index) internal view returns (Checkpoint160 memory) { + return self._checkpoints[index]; } /** @@ -745,10 +793,10 @@ library Checkpoints { uint96 key, uint160 value ) private returns (uint160 oldValue, uint160 newValue) { - uint256 pos = self.length; + uint256 len = self.length; - if (pos > 0) { - Checkpoint160 storage last = _unsafeAccess(self, pos - 1); + if (len > 0) { + Checkpoint160 storage last = _unsafeAccess(self, len - 1); uint96 lastKey = last._key; uint160 lastValue = last._value; @@ -823,11 +871,11 @@ library Checkpoints { */ function _unsafeAccess( Checkpoint160[] storage self, - uint256 pos + uint256 index ) private pure returns (Checkpoint160 storage result) { assembly { mstore(0x00, self.slot) - result.slot := add(keccak256(0x00, 0x20), pos) + result.slot := add(keccak256(0x00, 0x20), index) } } } diff --git a/dependencies/@openzeppelin-contracts-5.5.0/utils/structs/CircularBuffer.sol b/dependencies/@openzeppelin-contracts-5.7.0/utils/structs/CircularBuffer.sol similarity index 91% rename from dependencies/@openzeppelin-contracts-5.5.0/utils/structs/CircularBuffer.sol rename to dependencies/@openzeppelin-contracts-5.7.0/utils/structs/CircularBuffer.sol index 8d7801d..13c716d 100644 --- a/dependencies/@openzeppelin-contracts-5.5.0/utils/structs/CircularBuffer.sol +++ b/dependencies/@openzeppelin-contracts-5.7.0/utils/structs/CircularBuffer.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -// OpenZeppelin Contracts (last updated v5.5.0) (utils/structs/CircularBuffer.sol) +// OpenZeppelin Contracts (last updated v5.6.0) (utils/structs/CircularBuffer.sol) pragma solidity ^0.8.24; @@ -17,6 +17,7 @@ import {Panic} from "../Panic.sol"; * 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) @@ -34,9 +35,19 @@ import {Panic} from "../Panic.sol"; * * // Declare a buffer storage variable * CircularBuffer.Bytes32CircularBuffer private myBuffer; + * + * constructor() { + * myBuffer.setup(16); // Initialize the buffer with a non-zero fixed size (e.g., 16) + * } + * + * function pushValue(bytes32 value) external { + * myBuffer.push(value); // Safe to push because the buffer was initialized in the constructor + * } * } * ``` * + * NOTE: Make sure to call {setup} on your buffer during construction/initialization + * * _Available since v5.1._ */ library CircularBuffer { diff --git a/dependencies/@openzeppelin-contracts-5.7.0/utils/structs/DoubleEndedQueue.sol b/dependencies/@openzeppelin-contracts-5.7.0/utils/structs/DoubleEndedQueue.sol new file mode 100644 index 0000000..24907f5 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.7.0/utils/structs/DoubleEndedQueue.sol @@ -0,0 +1,280 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v5.7.0) (utils/structs/DoubleEndedQueue.sol) + +pragma solidity ^0.8.20; + +import {Math} from "../math/Math.sol"; +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 { + bool success = tryPushBack(deque, value); + if (!success) Panic.panic(Panic.RESOURCE_ERROR); + } + + /** + * @dev Attempts to insert an item at the end of the queue. + * + * Returns `false` if the queue is full. Never reverts. + */ + function tryPushBack(Bytes32Deque storage deque, bytes32 value) internal returns (bool success) { + unchecked { + uint128 backIndex = deque._end; + if (backIndex + 1 == deque._begin) return false; + deque._data[backIndex] = value; + deque._end = backIndex + 1; + return true; + } + } + + /** + * @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) { + (bool success, bytes32 value) = tryPopBack(deque); + if (!success) Panic.panic(Panic.EMPTY_ARRAY_POP); + return value; + } + + /** + * @dev Attempts to remove the item at the end of the queue and return it. + * + * Returns `(false, 0x00)` if the queue is empty. Never reverts. + */ + function tryPopBack(Bytes32Deque storage deque) internal returns (bool success, bytes32 value) { + unchecked { + uint128 backIndex = deque._end; + if (backIndex == deque._begin) return (false, bytes32(0)); + --backIndex; + success = true; + 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 { + bool success = tryPushFront(deque, value); + if (!success) Panic.panic(Panic.RESOURCE_ERROR); + } + + /** + * @dev Attempts to insert an item at the beginning of the queue. + * + * Returns `false` if the queue is full. Never reverts. + */ + function tryPushFront(Bytes32Deque storage deque, bytes32 value) internal returns (bool success) { + unchecked { + uint128 frontIndex = deque._begin - 1; + if (frontIndex == deque._end) return false; + deque._data[frontIndex] = value; + deque._begin = frontIndex; + return true; + } + } + + /** + * @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) { + (bool success, bytes32 value) = tryPopFront(deque); + if (!success) Panic.panic(Panic.EMPTY_ARRAY_POP); + return value; + } + + /** + * @dev Attempts to remove the item at the beginning of the queue and + * return it. + * + * Returns `(false, 0x00)` if the queue is empty. Never reverts. + */ + function tryPopFront(Bytes32Deque storage deque) internal returns (bool success, bytes32 value) { + unchecked { + uint128 frontIndex = deque._begin; + if (frontIndex == deque._end) return (false, bytes32(0)); + success = true; + 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) { + (bool success, bytes32 value) = tryFront(deque); + if (!success) Panic.panic(Panic.ARRAY_OUT_OF_BOUNDS); + return value; + } + + /** + * @dev Attempts to return the item at the beginning of the queue. + * + * Returns `(false, 0x00)` if the queue is empty. Never reverts. + */ + function tryFront(Bytes32Deque storage deque) internal view returns (bool success, bytes32 value) { + if (empty(deque)) return (false, bytes32(0)); + return (true, 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) { + (bool success, bytes32 value) = tryBack(deque); + if (!success) Panic.panic(Panic.ARRAY_OUT_OF_BOUNDS); + return value; + } + + /** + * @dev Attempts to return the item at the end of the queue. + * + * Returns `(false, 0x00)` if the queue is empty. Never reverts. + */ + function tryBack(Bytes32Deque storage deque) internal view returns (bool success, bytes32 value) { + if (empty(deque)) return (false, bytes32(0)); + unchecked { + return (true, 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. + * + * IMPORTANT: Deprecated. This function's name clashes with a keyword scheduled for inclusion in Solidity. Developers + * should use {pos} instead. + */ + function at(Bytes32Deque storage deque, uint256 index) internal view returns (bytes32) { + return pos(deque, index); + } + + /** + * @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. + * + * Replacement of the deprecated {at} function. + */ + function pos(Bytes32Deque storage deque, uint256 index) internal view returns (bytes32) { + (bool success, bytes32 value) = tryAt(deque, index); + if (!success) Panic.panic(Panic.ARRAY_OUT_OF_BOUNDS); + return value; + } + + /** + * @dev Attempts to return the item at a position in the queue given by `index`, with the first item at + * 0 and the last item at `length(deque) - 1`. + * + * Returns `(false, 0x00)` if the index is out of bounds. Never reverts. + */ + function tryAt(Bytes32Deque storage deque, uint256 index) internal view returns (bool success, bytes32 value) { + if (index >= length(deque)) return (false, bytes32(0)); + // By construction, length is a uint128, so the check above ensures that index can be safely downcast to uint128 + unchecked { + return (true, deque._data[deque._begin + uint128(index)]); + } + } + + /** + * @dev Return a slice of the queue in an array, with the first item at `start` (inclusive) and the last item at + * `end` (exclusive). Out-of-bound values for `start` and `end` are clamped to the queue length. + * + * WARNING: This operation will copy a portion of the 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 queue grows to a point where copying to memory consumes too much gas to fit in a + * block. + */ + function values(Bytes32Deque storage deque, uint256 start, uint256 end) internal view returns (bytes32[] memory) { + unchecked { + end = Math.min(end, length(deque)); + start = Math.min(start, end); + + uint256 len = end - start; + bytes32[] memory result = new bytes32[](len); + + uint128 offset = deque._begin + uint128(start); + for (uint128 i = 0; i < len; ++i) { + result[i] = deque._data[offset + i]; + } + return result; + } + } + + /** + * @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.5.0/utils/structs/EnumerableMap.sol b/dependencies/@openzeppelin-contracts-5.7.0/utils/structs/EnumerableMap.sol similarity index 78% rename from dependencies/@openzeppelin-contracts-5.5.0/utils/structs/EnumerableMap.sol rename to dependencies/@openzeppelin-contracts-5.7.0/utils/structs/EnumerableMap.sol index 3173623..8a56578 100644 --- a/dependencies/@openzeppelin-contracts-5.5.0/utils/structs/EnumerableMap.sol +++ b/dependencies/@openzeppelin-contracts-5.7.0/utils/structs/EnumerableMap.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -// OpenZeppelin Contracts (last updated v5.5.0) (utils/structs/EnumerableMap.sol) +// OpenZeppelin Contracts (last updated v5.7.0) (utils/structs/EnumerableMap.sol) // This file was procedurally generated from scripts/generate/templates/EnumerableMap.js. pragma solidity ^0.8.24; @@ -40,6 +40,7 @@ import {EnumerableSet} from "./EnumerableSet.sol"; * - `address -> bytes32` (`AddressToBytes32Map`) since v5.1.0 * - `bytes32 -> address` (`Bytes32ToAddressMap`) since v5.1.0 * - `bytes -> bytes` (`BytesToBytesMap`) since v5.4.0 + * - `bytes4 -> address` (`Bytes4ToAddressMap`) since v5.6.0 * * [WARNING] * ==== @@ -101,7 +102,7 @@ library EnumerableMap { function clear(Bytes32ToBytes32Map storage map) internal { uint256 len = length(map); for (uint256 i = 0; i < len; ++i) { - delete map._values[map._keys.at(i)]; + delete map._values[map._keys.pos(i)]; } map._keys.clear(); } @@ -129,9 +130,28 @@ library EnumerableMap { * Requirements: * * - `index` must be strictly less than {length}. + * + * IMPORTANT: Deprecated. This function's name clashes with a keyword scheduled for inclusion in Solidity. Developers + * should use {pos} instead. */ function at(Bytes32ToBytes32Map storage map, uint256 index) internal view returns (bytes32 key, bytes32 value) { - bytes32 atKey = map._keys.at(index); + return pos(map, index); + } + + /** + * @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}. + * + * Replacement of the deprecated {at} function. + */ + function pos(Bytes32ToBytes32Map storage map, uint256 index) internal view returns (bytes32 key, bytes32 value) { + bytes32 atKey = map._keys.pos(index); return (atKey, map._values[atKey]); } @@ -250,9 +270,27 @@ library EnumerableMap { * Requirements: * * - `index` must be strictly less than {length}. + * + * IMPORTANT: Deprecated. This function's name clashes with a keyword scheduled for inclusion in Solidity. Developers + * should use {pos} instead. */ function at(UintToUintMap storage map, uint256 index) internal view returns (uint256 key, uint256 value) { - (bytes32 atKey, bytes32 val) = at(map._inner, index); + return pos(map, index); + } + + /** + * @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}. + * + * Replacement of the deprecated {at} function. + */ + function pos(UintToUintMap storage map, uint256 index) internal view returns (uint256 key, uint256 value) { + (bytes32 atKey, bytes32 val) = pos(map._inner, index); return (uint256(atKey), uint256(val)); } @@ -373,9 +411,27 @@ library EnumerableMap { * Requirements: * * - `index` must be strictly less than {length}. + * + * IMPORTANT: Deprecated. This function's name clashes with a keyword scheduled for inclusion in Solidity. Developers + * should use {pos} instead. */ function at(UintToAddressMap storage map, uint256 index) internal view returns (uint256 key, address value) { - (bytes32 atKey, bytes32 val) = at(map._inner, index); + return pos(map, index); + } + + /** + * @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}. + * + * Replacement of the deprecated {at} function. + */ + function pos(UintToAddressMap storage map, uint256 index) internal view returns (uint256 key, address value) { + (bytes32 atKey, bytes32 val) = pos(map._inner, index); return (uint256(atKey), address(uint160(uint256(val)))); } @@ -496,9 +552,27 @@ library EnumerableMap { * Requirements: * * - `index` must be strictly less than {length}. + * + * IMPORTANT: Deprecated. This function's name clashes with a keyword scheduled for inclusion in Solidity. Developers + * should use {pos} instead. */ function at(UintToBytes32Map storage map, uint256 index) internal view returns (uint256 key, bytes32 value) { - (bytes32 atKey, bytes32 val) = at(map._inner, index); + return pos(map, index); + } + + /** + * @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}. + * + * Replacement of the deprecated {at} function. + */ + function pos(UintToBytes32Map storage map, uint256 index) internal view returns (uint256 key, bytes32 value) { + (bytes32 atKey, bytes32 val) = pos(map._inner, index); return (uint256(atKey), val); } @@ -619,9 +693,27 @@ library EnumerableMap { * Requirements: * * - `index` must be strictly less than {length}. + * + * IMPORTANT: Deprecated. This function's name clashes with a keyword scheduled for inclusion in Solidity. Developers + * should use {pos} instead. */ function at(AddressToUintMap storage map, uint256 index) internal view returns (address key, uint256 value) { - (bytes32 atKey, bytes32 val) = at(map._inner, index); + return pos(map, index); + } + + /** + * @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}. + * + * Replacement of the deprecated {at} function. + */ + function pos(AddressToUintMap storage map, uint256 index) internal view returns (address key, uint256 value) { + (bytes32 atKey, bytes32 val) = pos(map._inner, index); return (address(uint160(uint256(atKey))), uint256(val)); } @@ -742,9 +834,27 @@ library EnumerableMap { * Requirements: * * - `index` must be strictly less than {length}. + * + * IMPORTANT: Deprecated. This function's name clashes with a keyword scheduled for inclusion in Solidity. Developers + * should use {pos} instead. */ function at(AddressToAddressMap storage map, uint256 index) internal view returns (address key, address value) { - (bytes32 atKey, bytes32 val) = at(map._inner, index); + return pos(map, index); + } + + /** + * @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}. + * + * Replacement of the deprecated {at} function. + */ + function pos(AddressToAddressMap storage map, uint256 index) internal view returns (address key, address value) { + (bytes32 atKey, bytes32 val) = pos(map._inner, index); return (address(uint160(uint256(atKey))), address(uint160(uint256(val)))); } @@ -869,9 +979,27 @@ library EnumerableMap { * Requirements: * * - `index` must be strictly less than {length}. + * + * IMPORTANT: Deprecated. This function's name clashes with a keyword scheduled for inclusion in Solidity. Developers + * should use {pos} instead. */ function at(AddressToBytes32Map storage map, uint256 index) internal view returns (address key, bytes32 value) { - (bytes32 atKey, bytes32 val) = at(map._inner, index); + return pos(map, index); + } + + /** + * @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}. + * + * Replacement of the deprecated {at} function. + */ + function pos(AddressToBytes32Map storage map, uint256 index) internal view returns (address key, bytes32 value) { + (bytes32 atKey, bytes32 val) = pos(map._inner, index); return (address(uint160(uint256(atKey))), val); } @@ -996,9 +1124,27 @@ library EnumerableMap { * Requirements: * * - `index` must be strictly less than {length}. + * + * IMPORTANT: Deprecated. This function's name clashes with a keyword scheduled for inclusion in Solidity. Developers + * should use {pos} instead. */ function at(Bytes32ToUintMap storage map, uint256 index) internal view returns (bytes32 key, uint256 value) { - (bytes32 atKey, bytes32 val) = at(map._inner, index); + return pos(map, index); + } + + /** + * @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}. + * + * Replacement of the deprecated {at} function. + */ + function pos(Bytes32ToUintMap storage map, uint256 index) internal view returns (bytes32 key, uint256 value) { + (bytes32 atKey, bytes32 val) = pos(map._inner, index); return (atKey, uint256(val)); } @@ -1119,9 +1265,27 @@ library EnumerableMap { * Requirements: * * - `index` must be strictly less than {length}. + * + * IMPORTANT: Deprecated. This function's name clashes with a keyword scheduled for inclusion in Solidity. Developers + * should use {pos} instead. */ function at(Bytes32ToAddressMap storage map, uint256 index) internal view returns (bytes32 key, address value) { - (bytes32 atKey, bytes32 val) = at(map._inner, index); + return pos(map, index); + } + + /** + * @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}. + * + * Replacement of the deprecated {at} function. + */ + function pos(Bytes32ToAddressMap storage map, uint256 index) internal view returns (bytes32 key, address value) { + (bytes32 atKey, bytes32 val) = pos(map._inner, index); return (atKey, address(uint160(uint256(val)))); } @@ -1187,6 +1351,147 @@ library EnumerableMap { return result; } + // Bytes4ToAddressMap + + struct Bytes4ToAddressMap { + 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(Bytes4ToAddressMap storage map, bytes4 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(Bytes4ToAddressMap storage map, bytes4 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(Bytes4ToAddressMap storage map) internal { + clear(map._inner); + } + + /** + * @dev Returns true if the key is in the map. O(1). + */ + function contains(Bytes4ToAddressMap storage map, bytes4 key) internal view returns (bool) { + return contains(map._inner, bytes32(key)); + } + + /** + * @dev Returns the number of elements in the map. O(1). + */ + function length(Bytes4ToAddressMap 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}. + * + * IMPORTANT: Deprecated. This function's name clashes with a keyword scheduled for inclusion in Solidity. Developers + * should use {pos} instead. + */ + function at(Bytes4ToAddressMap storage map, uint256 index) internal view returns (bytes4 key, address value) { + return pos(map, index); + } + + /** + * @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}. + * + * Replacement of the deprecated {at} function. + */ + function pos(Bytes4ToAddressMap storage map, uint256 index) internal view returns (bytes4 key, address value) { + (bytes32 atKey, bytes32 val) = pos(map._inner, index); + return (bytes4(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(Bytes4ToAddressMap storage map, bytes4 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(Bytes4ToAddressMap storage map, bytes4 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(Bytes4ToAddressMap storage map) internal view returns (bytes4[] memory) { + bytes32[] memory store = keys(map._inner); + bytes4[] 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(Bytes4ToAddressMap storage map, uint256 start, uint256 end) internal view returns (bytes4[] memory) { + bytes32[] memory store = keys(map._inner, start, end); + bytes4[] memory result; + + assembly ("memory-safe") { + result := store + } + + return result; + } + /** * @dev Query for a nonexistent map key. */ @@ -1229,7 +1534,7 @@ library EnumerableMap { function clear(BytesToBytesMap storage map) internal { uint256 len = length(map); for (uint256 i = 0; i < len; ++i) { - delete map._values[map._keys.at(i)]; + delete map._values[map._keys.pos(i)]; } map._keys.clear(); } @@ -1257,12 +1562,33 @@ library EnumerableMap { * Requirements: * * - `index` must be strictly less than {length}. + * + * IMPORTANT: Deprecated. This function's name clashes with a keyword scheduled for inclusion in Solidity. Developers + * should use {pos} instead. */ function at( BytesToBytesMap storage map, uint256 index ) internal view returns (bytes memory key, bytes memory value) { - key = map._keys.at(index); + return pos(map, index); + } + + /** + * @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}. + * + * Replacement of the deprecated {at} function. + */ + function pos( + BytesToBytesMap storage map, + uint256 index + ) internal view returns (bytes memory key, bytes memory value) { + key = map._keys.pos(index); value = map._values[key]; } diff --git a/dependencies/@openzeppelin-contracts-5.5.0/utils/structs/EnumerableSet.sol b/dependencies/@openzeppelin-contracts-5.7.0/utils/structs/EnumerableSet.sol similarity index 78% rename from dependencies/@openzeppelin-contracts-5.5.0/utils/structs/EnumerableSet.sol rename to dependencies/@openzeppelin-contracts-5.7.0/utils/structs/EnumerableSet.sol index 12479ca..37bebc5 100644 --- a/dependencies/@openzeppelin-contracts-5.5.0/utils/structs/EnumerableSet.sol +++ b/dependencies/@openzeppelin-contracts-5.7.0/utils/structs/EnumerableSet.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -// OpenZeppelin Contracts (last updated v5.5.0) (utils/structs/EnumerableSet.sol) +// OpenZeppelin Contracts (last updated v5.7.0) (utils/structs/EnumerableSet.sol) // This file was procedurally generated from scripts/generate/templates/EnumerableSet.js. pragma solidity ^0.8.24; @@ -36,6 +36,7 @@ import {Math} from "../math/Math.sol"; * - `uint256` (`UintSet`) since v3.3.0 * - `string` (`StringSet`) since v5.4.0 * - `bytes` (`BytesSet`) since v5.4.0 + * - `bytes4` (`Bytes4Set`) since v5.6.0 * * [WARNING] * ==== @@ -162,7 +163,7 @@ library EnumerableSet { * * - `index` must be strictly less than {length}. */ - function _at(Set storage set, uint256 index) private view returns (bytes32) { + function _pos(Set storage set, uint256 index) private view returns (bytes32) { return set._values[index]; } @@ -259,9 +260,28 @@ library EnumerableSet { * Requirements: * * - `index` must be strictly less than {length}. + * + * IMPORTANT: Deprecated. This function's name clashes with a keyword scheduled for inclusion in Solidity. Developers + * should use {pos} instead. */ function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) { - return _at(set._inner, index); + return pos(set, index); + } + + /** + * @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}. + * + * Replacement of the deprecated {at} function. + */ + function pos(Bytes32Set storage set, uint256 index) internal view returns (bytes32) { + return _pos(set._inner, index); } /** @@ -302,6 +322,127 @@ library EnumerableSet { return result; } + // Bytes4Set + + struct Bytes4Set { + 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(Bytes4Set storage set, bytes4 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(Bytes4Set storage set, bytes4 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(Bytes4Set storage set) internal { + _clear(set._inner); + } + + /** + * @dev Returns true if the value is in the set. O(1). + */ + function contains(Bytes4Set storage set, bytes4 value) internal view returns (bool) { + return _contains(set._inner, bytes32(value)); + } + + /** + * @dev Returns the number of values in the set. O(1). + */ + function length(Bytes4Set 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}. + * + * IMPORTANT: Deprecated. This function's name clashes with a keyword scheduled for inclusion in Solidity. Developers + * should use {pos} instead. + */ + function at(Bytes4Set storage set, uint256 index) internal view returns (bytes4) { + return pos(set, index); + } + + /** + * @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}. + * + * Replacement of the deprecated {at} function. + */ + function pos(Bytes4Set storage set, uint256 index) internal view returns (bytes4) { + return bytes4(_pos(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(Bytes4Set storage set) internal view returns (bytes4[] memory) { + bytes32[] memory store = _values(set._inner); + bytes4[] 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(Bytes4Set storage set, uint256 start, uint256 end) internal view returns (bytes4[] memory) { + bytes32[] memory store = _values(set._inner, start, end); + bytes4[] memory result; + + assembly ("memory-safe") { + result := store + } + + return result; + } + // AddressSet struct AddressSet { @@ -361,9 +502,28 @@ library EnumerableSet { * Requirements: * * - `index` must be strictly less than {length}. + * + * IMPORTANT: Deprecated. This function's name clashes with a keyword scheduled for inclusion in Solidity. Developers + * should use {pos} instead. */ function at(AddressSet storage set, uint256 index) internal view returns (address) { - return address(uint160(uint256(_at(set._inner, index)))); + return pos(set, index); + } + + /** + * @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}. + * + * Replacement of the deprecated {at} function. + */ + function pos(AddressSet storage set, uint256 index) internal view returns (address) { + return address(uint160(uint256(_pos(set._inner, index)))); } /** @@ -463,9 +623,28 @@ library EnumerableSet { * Requirements: * * - `index` must be strictly less than {length}. + * + * IMPORTANT: Deprecated. This function's name clashes with a keyword scheduled for inclusion in Solidity. Developers + * should use {pos} instead. */ function at(UintSet storage set, uint256 index) internal view returns (uint256) { - return uint256(_at(set._inner, index)); + return pos(set, index); + } + + /** + * @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}. + * + * Replacement of the deprecated {at} function. + */ + function pos(UintSet storage set, uint256 index) internal view returns (uint256) { + return uint256(_pos(set._inner, index)); } /** @@ -609,8 +788,27 @@ library EnumerableSet { * Requirements: * * - `index` must be strictly less than {length}. + * + * IMPORTANT: Deprecated. This function's name clashes with a keyword scheduled for inclusion in Solidity. Developers + * should use {pos} instead. */ function at(StringSet storage set, uint256 index) internal view returns (string memory) { + return pos(set, index); + } + + /** + * @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}. + * + * Replacement of the deprecated {at} function. + */ + function pos(StringSet storage set, uint256 index) internal view returns (string memory) { return set._values[index]; } @@ -751,8 +949,27 @@ library EnumerableSet { * Requirements: * * - `index` must be strictly less than {length}. + * + * IMPORTANT: Deprecated. This function's name clashes with a keyword scheduled for inclusion in Solidity. Developers + * should use {pos} instead. */ function at(BytesSet storage set, uint256 index) internal view returns (bytes memory) { + return pos(set, index); + } + + /** + * @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}. + * + * Replacement of the deprecated {at} function. + */ + function pos(BytesSet storage set, uint256 index) internal view returns (bytes memory) { return set._values[index]; } diff --git a/dependencies/@openzeppelin-contracts-5.5.0/utils/structs/Heap.sol b/dependencies/@openzeppelin-contracts-5.7.0/utils/structs/Heap.sol similarity index 91% rename from dependencies/@openzeppelin-contracts-5.5.0/utils/structs/Heap.sol rename to dependencies/@openzeppelin-contracts-5.7.0/utils/structs/Heap.sol index b5f0730..5e6ea66 100644 --- a/dependencies/@openzeppelin-contracts-5.5.0/utils/structs/Heap.sol +++ b/dependencies/@openzeppelin-contracts-5.7.0/utils/structs/Heap.sol @@ -1,10 +1,9 @@ // SPDX-License-Identifier: MIT -// OpenZeppelin Contracts (last updated v5.5.0) (utils/structs/Heap.sol) +// OpenZeppelin Contracts (last updated v5.7.0) (utils/structs/Heap.sol) pragma solidity ^0.8.24; 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"; @@ -18,9 +17,10 @@ import {StorageSlot} from "../StorageSlot.sol"; * 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 ordered so that, per the comparator, each node has lower priority than its parent; as a + * consequence, the highest-priority value is at the root. This value can be looked up in constant time (O(1)) at + * `heap.tree[0]`. By default, the comparator is `Comparators.lt`, which treats smaller values as higher priority + * (min-heap). Using `Comparators.gt` yields a max-heap. * * The structure is designed to perform the following operations with the corresponding complexities: * @@ -40,7 +40,6 @@ import {StorageSlot} from "../StorageSlot.sol"; library Heap { using Arrays for *; using Math for *; - using SafeCast for *; /** * @dev Binary heap that supports values of type uint256. @@ -85,13 +84,17 @@ library Heap { // 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); - + if (size == 1) { + self.tree.pop(); + } else { + // swap last leaf with root ... + uint256 lastValue = self.tree.unsafeAccess(size - 1).value; + self.tree.unsafeAccess(0).value = lastValue; + // ... shrink tree ... + self.tree.pop(); + // ... re-heapify + _siftDown(self, size - 1, 0, lastValue, comp); + } return rootValue; } } @@ -208,7 +211,7 @@ library Heap { uint256 rIndex = 2 * index + 2; // Three cases: - // 1. Both children exist: sifting may continue on one of the branch (selection required) + // 1. Both children exist: sifting may continue on one of the branches (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) { diff --git a/dependencies/@openzeppelin-contracts-5.5.0/utils/structs/MerkleTree.sol b/dependencies/@openzeppelin-contracts-5.7.0/utils/structs/MerkleTree.sol similarity index 100% rename from dependencies/@openzeppelin-contracts-5.5.0/utils/structs/MerkleTree.sol rename to dependencies/@openzeppelin-contracts-5.7.0/utils/structs/MerkleTree.sol diff --git a/dependencies/@openzeppelin-contracts-5.5.0/utils/types/Time.sol b/dependencies/@openzeppelin-contracts-5.7.0/utils/types/Time.sol similarity index 100% rename from dependencies/@openzeppelin-contracts-5.5.0/utils/types/Time.sol rename to dependencies/@openzeppelin-contracts-5.7.0/utils/types/Time.sol diff --git a/dependencies/@openzeppelin-contracts-5.5.0/vendor/compound/ICompoundTimelock.sol b/dependencies/@openzeppelin-contracts-5.7.0/vendor/compound/ICompoundTimelock.sol similarity index 100% rename from dependencies/@openzeppelin-contracts-5.5.0/vendor/compound/ICompoundTimelock.sol rename to dependencies/@openzeppelin-contracts-5.7.0/vendor/compound/ICompoundTimelock.sol diff --git a/dependencies/eth-infinitism-account-abstraction-0.8.0/.solhint.json b/dependencies/eth-infinitism-account-abstraction-0.8.0/.solhint.json deleted file mode 100644 index 2b5dda0..0000000 --- a/dependencies/eth-infinitism-account-abstraction-0.8.0/.solhint.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "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/README.md b/dependencies/eth-infinitism-account-abstraction-0.8.0/README.md deleted file mode 100644 index 57216f8..0000000 --- a/dependencies/eth-infinitism-account-abstraction-0.8.0/README.md +++ /dev/null @@ -1,11 +0,0 @@ -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/contracts/interfaces/PackedUserOperation.sol b/dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/interfaces/PackedUserOperation.sol deleted file mode 100644 index eb12fb7..0000000 --- a/dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/interfaces/PackedUserOperation.sol +++ /dev/null @@ -1,28 +0,0 @@ -// 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/test/TestHelpers.sol b/dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/test/TestHelpers.sol deleted file mode 100644 index fea431f..0000000 --- a/dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/test/TestHelpers.sol +++ /dev/null @@ -1,19 +0,0 @@ -// 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/test/UserOperation.ts b/dependencies/eth-infinitism-account-abstraction-0.8.0/test/UserOperation.ts deleted file mode 100644 index 98bebbc..0000000 --- a/dependencies/eth-infinitism-account-abstraction-0.8.0/test/UserOperation.ts +++ /dev/null @@ -1,32 +0,0 @@ -import * as typ from './solidityTypes' - -export interface UserOperation { - - sender: typ.address - nonce: typ.uint256 - initCode: typ.bytes - callData: typ.bytes - callGasLimit: typ.uint128 - verificationGasLimit: typ.uint128 - preVerificationGas: typ.uint256 - maxFeePerGas: typ.uint256 - maxPriorityFeePerGas: typ.uint256 - paymaster: typ.address - paymasterVerificationGasLimit: typ.uint128 - paymasterPostOpGasLimit: typ.uint128 - paymasterData: typ.bytes - signature: typ.bytes -} - -export interface PackedUserOperation { - - sender: typ.address - nonce: typ.uint256 - initCode: typ.bytes - callData: typ.bytes - accountGasLimits: typ.bytes32 - preVerificationGas: typ.uint256 - gasFees: typ.bytes32 - paymasterAndData: typ.bytes - signature: typ.bytes -} diff --git a/dependencies/eth-infinitism-account-abstraction-0.8.0/.depcheckrc b/dependencies/eth-infinitism-account-abstraction-0.9.0/.depcheckrc similarity index 100% rename from dependencies/eth-infinitism-account-abstraction-0.8.0/.depcheckrc rename to dependencies/eth-infinitism-account-abstraction-0.9.0/.depcheckrc diff --git a/dependencies/eth-infinitism-account-abstraction-0.8.0/.eslintrc.js b/dependencies/eth-infinitism-account-abstraction-0.9.0/.eslintrc.js similarity index 100% rename from dependencies/eth-infinitism-account-abstraction-0.8.0/.eslintrc.js rename to dependencies/eth-infinitism-account-abstraction-0.9.0/.eslintrc.js diff --git a/dependencies/eth-infinitism-account-abstraction-0.8.0/.github/workflows/build.yml b/dependencies/eth-infinitism-account-abstraction-0.9.0/.github/workflows/build.yml similarity index 71% rename from dependencies/eth-infinitism-account-abstraction-0.8.0/.github/workflows/build.yml rename to dependencies/eth-infinitism-account-abstraction-0.9.0/.github/workflows/build.yml index 2d8896c..1cf53ad 100644 --- a/dependencies/eth-infinitism-account-abstraction-0.8.0/.github/workflows/build.yml +++ b/dependencies/eth-infinitism-account-abstraction-0.9.0/.github/workflows/build.yml @@ -65,29 +65,3 @@ jobs: - 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.9.0/.gitignore similarity index 100% rename from dependencies/eth-infinitism-account-abstraction-0.8.0/.gitignore rename to dependencies/eth-infinitism-account-abstraction-0.9.0/.gitignore diff --git a/dependencies/eth-infinitism-account-abstraction-0.8.0/.solcover.js b/dependencies/eth-infinitism-account-abstraction-0.9.0/.solcover.js similarity index 100% rename from dependencies/eth-infinitism-account-abstraction-0.8.0/.solcover.js rename to dependencies/eth-infinitism-account-abstraction-0.9.0/.solcover.js diff --git a/dependencies/eth-infinitism-account-abstraction-0.9.0/.solhint.json b/dependencies/eth-infinitism-account-abstraction-0.9.0/.solhint.json new file mode 100644 index 0000000..5025302 --- /dev/null +++ b/dependencies/eth-infinitism-account-abstraction-0.9.0/.solhint.json @@ -0,0 +1,19 @@ +{ + "extends": "solhint:recommended", + "rules": { + "compiler-version": ["error", ">=0.8.28"], + "explicit-types": ["warn", "explicit"], + "function-max-lines": "off", + "gas-increment-by-one": "off", + "gas-indexed-events": "off", + "gas-strict-inequalities": "off", + "immutable-vars-naming": ["off"], + "no-global-import": "off", + "use-natspec": "off", + "func-visibility": [ + "off", { + "ignoreConstructors": true + } + ] + } +} diff --git a/dependencies/eth-infinitism-account-abstraction-0.8.0/.solhintignore b/dependencies/eth-infinitism-account-abstraction-0.9.0/.solhintignore similarity index 100% rename from dependencies/eth-infinitism-account-abstraction-0.8.0/.solhintignore rename to dependencies/eth-infinitism-account-abstraction-0.9.0/.solhintignore diff --git a/dependencies/eth-infinitism-account-abstraction-0.8.0/LICENSE b/dependencies/eth-infinitism-account-abstraction-0.9.0/LICENSE similarity index 100% rename from dependencies/eth-infinitism-account-abstraction-0.8.0/LICENSE rename to dependencies/eth-infinitism-account-abstraction-0.9.0/LICENSE diff --git a/dependencies/eth-infinitism-account-abstraction-0.9.0/README.md b/dependencies/eth-infinitism-account-abstraction-0.9.0/README.md new file mode 100644 index 0000000..aadf91e --- /dev/null +++ b/dependencies/eth-infinitism-account-abstraction-0.9.0/README.md @@ -0,0 +1,147 @@ + +# Description + +This repository contains the tools and resources for working with [ERC-4337](https://eips.ethereum.org/EIPS/eip-4337) Account Abstraction smart contracts. This includes the code for the singleton `EntryPoint` contract that is deployed by our team on most EVM-compatible networks. + +# Overview + +Account abstraction allows users to interact with Ethereum using smart contract wallets instead of EOAs, without compromising decentralization, providing benefits like: + +- Social recovery +- Batched transactions +- Sponsored transactions (gas abstraction) +- Signature abstraction +- Advanced authorization logic + +# Repository Structure + +## Core Components + +- **EntryPoint Contract** (`contracts/core/EntryPoint.sol`): The central contract that processes UserOperations +- **BaseAccount** (`contracts/core/BaseAccount.sol`): Base implementation for smart contract accounts +- **BasePaymaster** (`contracts/core/BasePaymaster.sol`): Helper class for creating a paymaster +- **StakeManager** (`contracts/core/StakeManager.sol`): Manages deposits and stakes for accounts and paymasters +- **NonceManager** (`contracts/core/NonceManager.sol`): Handles nonce management for accounts +- **UserOperationLib** (`contracts/core/UserOperationLib.sol`): Utilities for working with UserOperations +- **Helpers** (`contracts/core/Helpers.sol`): Common constants and helper functions + + +## Sample Implementations + +- **SimpleAccount** (`contracts/accounts/SimpleAccount.sol`): Basic implementation of an ERC-4337 account + +- **Simple7702Account** (`contracts/accounts/Simple7702Account.sol`): A minimal account to be used with EIP-7702 (for batching) and ERC-4337 (for gas sponsoring) + +- **SimpleAccountFactory** (`contracts/accounts/SimpleAccountFactory.sol`): A sample factory contract for SimpleAccount + + +# Developer setup + +## Installation + +### Clone the repository: + +````bash +git clone https://github.com/eth-infinitism/account-abstraction.git +cd account-abstraction +yarn install +```` +### Compilation: + +```bash +yarn compile +``` + +### Testing: + +```bash +yarn test +``` + + +## Entrypoint Deployment + +The EntryPoint contract is the central hub for processing UserOperations. It: +- Validates UserOperations +- Handles account creation (if needed) +- Executes the requested operations +- Manages gas payments and refunds + +The EntryPoint is deployed by using + +```bash +hardhat deploy --network {net} +``` + +[EntryPoint v0.8](https://github.com/eth-infinitism/account-abstraction/releases/latest) is always deployed at address `0x4337084d9e255ff0702461cf8895ce9e3b5ff108` + +This repository also includes a number of audited base classes and utilities that can simplify the development of AA related contracts. + +## Usage +### For projects integrating the library + +If you are building a project that uses account abstraction and want to integrate our contracts: + +```bash +yarn add @account-abstraction/contracts +``` + +### For Paymaster development + +```solidity +import "@account-abstraction/contracts/core/BasePaymaster.sol"; + +contract MyCustomPaymaster is BasePaymaster { + /// implement your gas payment logic here + function _validatePaymasterUserOp( + PackedUserOperation calldata userOp, + bytes32 userOpHash, + uint256 maxCost + ) internal virtual override returns (bytes memory context, uint256 validationData) { + context = “”; // specify “context” if needed in postOp call. + validationData = _packValidationData( + false, + validUntil, + validAfter + ); + } +} + +``` + + + +### For Smart Contract Account development + +```bash +import "@account-abstraction/contracts/core/BaseAccount.sol"; + +contract MyAccount is BaseAccount { + + /// implement your authentication logic here + function _validateSignature(PackedUserOperation calldata userOp, bytes32 userOpHash) + internal override virtual returns (uint256 validationData) { + + // UserOpHash can be generated using eth_signTypedData_v4 + if (owner != ECDSA.recover(userOpHash, userOp.signature)) + return SIG_VALIDATION_FAILED; + return SIG_VALIDATION_SUCCESS; + } +} +``` + +# Resources + +- [Homepage](https://www.erc4337.io/) +- [Blog](https://erc4337.mirror.xyz/) +- [X Account](https://x.com/erc4337) +- [YouTube Channel](https://www.youtube.com/@ERC-4337) +- [Bundlebear](https://www.bundlebear.com/overview/all) +- [Vitalik Buterin - a history of account abstraction](https://www.youtube.com/watch?v=iLf8qpOmxQc) +- [Beyond 4337: Vitalik Buterin's Vision for the Future of Account Abstraction](https://www.youtube.com/watch?v=zpqa1Z4UpiA) +- [Exploring the Future of Account Abstraction by Yoav Weiss](https://www.youtube.com/watch?v=63Wd5mPla-M) +- [Native Account Abstraction in Pectra, rollups and beyond](https://www.youtube.com/watch?v=FYanFF-yU6w) +- [Vitalik Buterin - account abstraction without Ethereum protocol changes](https://medium.com/infinitism/erc-4337-account-abstraction-without-ethereum-protocol-changes-d75c9d94dc4a) +- [Unified ERC-4337 mempool](https://notes.ethereum.org/@yoav/unified-erc-4337-mempool) +- [Bundler reference implementation](https://github.com/eth-infinitism/bundler) +- [Discord server](http://discord.gg/fbDyENb6Y9) 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.9.0/audits/EIP_4337_\342\200\223_Ethereum_Account_Abstraction_Incremental_Audit_Feb_2023.pdf" similarity index 100% rename from "dependencies/eth-infinitism-account-abstraction-0.8.0/audits/EIP_4337_\342\200\223_Ethereum_Account_Abstraction_Incremental_Audit_Feb_2023.pdf" rename to "dependencies/eth-infinitism-account-abstraction-0.9.0/audits/EIP_4337_\342\200\223_Ethereum_Account_Abstraction_Incremental_Audit_Feb_2023.pdf" 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.9.0/audits/ERC-4337 Account Abstraction Incremental Audit Report Feb 20 2024.pdf similarity index 100% rename from dependencies/eth-infinitism-account-abstraction-0.8.0/audits/ERC-4337 Account Abstraction Incremental Audit Report Feb 20 2024.pdf rename to dependencies/eth-infinitism-account-abstraction-0.9.0/audits/ERC-4337 Account Abstraction Incremental Audit Report Feb 20 2024.pdf diff --git a/dependencies/eth-infinitism-account-abstraction-0.9.0/audits/SpearBit Account Abstraction Security Review - Mar 2025.pdf b/dependencies/eth-infinitism-account-abstraction-0.9.0/audits/SpearBit Account Abstraction Security Review - Mar 2025.pdf new file mode 100644 index 0000000..19f5214 Binary files /dev/null and b/dependencies/eth-infinitism-account-abstraction-0.9.0/audits/SpearBit Account Abstraction Security Review - Mar 2025.pdf differ diff --git a/dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/.npmignore b/dependencies/eth-infinitism-account-abstraction-0.9.0/contracts/.npmignore similarity index 100% rename from dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/.npmignore rename to dependencies/eth-infinitism-account-abstraction-0.9.0/contracts/.npmignore diff --git a/dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/accounts/Simple7702Account.sol b/dependencies/eth-infinitism-account-abstraction-0.9.0/contracts/accounts/Simple7702Account.sol similarity index 79% rename from dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/accounts/Simple7702Account.sol rename to dependencies/eth-infinitism-account-abstraction-0.9.0/contracts/accounts/Simple7702Account.sol index ce45bc2..74d9608 100644 --- a/dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/accounts/Simple7702Account.sol +++ b/dependencies/eth-infinitism-account-abstraction-0.9.0/contracts/accounts/Simple7702Account.sol @@ -15,9 +15,14 @@ import "../core/BaseAccount.sol"; */ contract Simple7702Account is BaseAccount, IERC165, IERC1271, ERC1155Holder, ERC721Holder { - // temporary address of entryPoint v0.8 - function entryPoint() public pure override returns (IEntryPoint) { - return IEntryPoint(0x4337084D9E255Ff0702461CF8895CE9E3b5Ff108); + IEntryPoint private immutable _entryPoint; + + constructor(IEntryPoint anEntryPoint) { + _entryPoint = anEntryPoint; + } + + function entryPoint() public view override returns (IEntryPoint) { + return _entryPoint; } /** @@ -32,7 +37,7 @@ contract Simple7702Account is BaseAccount, IERC165, IERC1271, ERC1155Holder, ERC return _checkSignature(userOpHash, userOp.signature) ? SIG_VALIDATION_SUCCESS : SIG_VALIDATION_FAILED; } - function isValidSignature(bytes32 hash, bytes memory signature) public view returns (bytes4 magicValue) { + function isValidSignature(bytes32 hash, bytes memory signature) public virtual view returns (bytes4 magicValue) { return _checkSignature(hash, signature) ? this.isValidSignature.selector : bytes4(0xffffffff); } @@ -44,11 +49,15 @@ contract Simple7702Account is BaseAccount, IERC165, IERC1271, ERC1155Holder, ERC require( msg.sender == address(this) || msg.sender == address(entryPoint()), - "not from self or EntryPoint" + NotFromEntryPoint( + msg.sender, + address(this), + address(entryPoint()) + ) ); } - function supportsInterface(bytes4 id) public override(ERC1155Holder, IERC165) pure returns (bool) { + function supportsInterface(bytes4 id) public virtual override(ERC1155Holder, IERC165) pure returns (bool) { return id == type(IERC165).interfaceId || id == type(IAccount).interfaceId || diff --git a/dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/accounts/SimpleAccount.sol b/dependencies/eth-infinitism-account-abstraction-0.9.0/contracts/accounts/SimpleAccount.sol similarity index 82% rename from dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/accounts/SimpleAccount.sol rename to dependencies/eth-infinitism-account-abstraction-0.9.0/contracts/accounts/SimpleAccount.sol index 3c9b3f5..82ccebf 100644 --- a/dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/accounts/SimpleAccount.sol +++ b/dependencies/eth-infinitism-account-abstraction-0.9.0/contracts/accounts/SimpleAccount.sol @@ -31,6 +31,9 @@ contract SimpleAccount is BaseAccount, TokenCallbackHandler, UUPSUpgradeable, In _; } + error NotOwner(address msgSender, address entity, address owner ); + error NotOwnerOrEntryPoint(address msgSender, address entity, address entryPoint, address owner); + /// @inheritdoc BaseAccount function entryPoint() public view virtual override returns (IEntryPoint) { return _entryPoint; @@ -46,7 +49,14 @@ contract SimpleAccount is BaseAccount, TokenCallbackHandler, UUPSUpgradeable, In function _onlyOwner() internal view { // Directly from EOA owner, or through the account itself (which gets redirected through execute()) - require(msg.sender == owner || msg.sender == address(this), "only owner"); + require( + msg.sender == owner || msg.sender == address(this), + NotOwner( + msg.sender, + address(this), + owner + ) + ); } /** @@ -61,12 +71,19 @@ contract SimpleAccount is BaseAccount, TokenCallbackHandler, UUPSUpgradeable, In function _initialize(address anOwner) internal virtual { owner = anOwner; - emit SimpleAccountInitialized(_entryPoint, owner); + emit SimpleAccountInitialized(entryPoint(), owner); } // Require the function call went through EntryPoint or owner function _requireForExecute() internal view override virtual { - require(msg.sender == address(entryPoint()) || msg.sender == owner, "account: not Owner or EntryPoint"); + require(msg.sender == address(entryPoint()) || msg.sender == owner, + NotOwnerOrEntryPoint( + msg.sender, + address(this), + address(entryPoint()), + owner + ) + ); } /// implement template method of BaseAccount @@ -82,7 +99,7 @@ contract SimpleAccount is BaseAccount, TokenCallbackHandler, UUPSUpgradeable, In /** * check current account deposit in the entryPoint */ - function getDeposit() public view returns (uint256) { + function getDeposit() public virtual view returns (uint256) { return entryPoint().balanceOf(address(this)); } @@ -98,7 +115,7 @@ contract SimpleAccount is BaseAccount, TokenCallbackHandler, UUPSUpgradeable, In * @param withdrawAddress target to send to * @param amount to withdraw */ - function withdrawDepositTo(address payable withdrawAddress, uint256 amount) public onlyOwner { + function withdrawDepositTo(address payable withdrawAddress, uint256 amount) public virtual onlyOwner { entryPoint().withdrawTo(withdrawAddress, amount); } diff --git a/dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/accounts/SimpleAccountFactory.sol b/dependencies/eth-infinitism-account-abstraction-0.9.0/contracts/accounts/SimpleAccountFactory.sol similarity index 81% rename from dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/accounts/SimpleAccountFactory.sol rename to dependencies/eth-infinitism-account-abstraction-0.9.0/contracts/accounts/SimpleAccountFactory.sol index 2f368f4..524fab5 100644 --- a/dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/accounts/SimpleAccountFactory.sol +++ b/dependencies/eth-infinitism-account-abstraction-0.9.0/contracts/accounts/SimpleAccountFactory.sol @@ -17,6 +17,8 @@ contract SimpleAccountFactory { SimpleAccount public immutable accountImplementation; ISenderCreator public immutable senderCreator; + error NotSenderCreator(address msgSender, address entity, address senderCreator); + constructor(IEntryPoint _entryPoint) { accountImplementation = new SimpleAccount(_entryPoint); senderCreator = _entryPoint.senderCreator(); @@ -28,8 +30,14 @@ contract SimpleAccountFactory { * 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 (SimpleAccount ret) { - require(msg.sender == address(senderCreator), "only callable from SenderCreator"); + function createAccount(address owner, uint256 salt) public returns (SimpleAccount ret) { + require(msg.sender == address(senderCreator), + NotSenderCreator( + msg.sender, + address(this), + address(senderCreator) + ) + ); address addr = getAddress(owner, salt); uint256 codeSize = addr.code.length; if (codeSize > 0) { @@ -44,7 +52,7 @@ contract SimpleAccountFactory { /** * calculate the counterfactual address of this account as it would be returned by createAccount() */ - function getAddress(address owner,uint256 salt) public view returns (address) { + function getAddress(address owner,uint256 salt) public virtual view returns (address) { return Create2.computeAddress(bytes32(salt), keccak256(abi.encodePacked( type(ERC1967Proxy).creationCode, abi.encode( diff --git a/dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/accounts/callback/TokenCallbackHandler.sol b/dependencies/eth-infinitism-account-abstraction-0.9.0/contracts/accounts/callback/TokenCallbackHandler.sol similarity index 100% rename from dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/accounts/callback/TokenCallbackHandler.sol rename to dependencies/eth-infinitism-account-abstraction-0.9.0/contracts/accounts/callback/TokenCallbackHandler.sol diff --git a/dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/core/BaseAccount.sol b/dependencies/eth-infinitism-account-abstraction-0.9.0/contracts/core/BaseAccount.sol similarity index 96% rename from dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/core/BaseAccount.sol rename to dependencies/eth-infinitism-account-abstraction-0.9.0/contracts/core/BaseAccount.sol index 60d0ccd..275b86d 100644 --- a/dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/core/BaseAccount.sol +++ b/dependencies/eth-infinitism-account-abstraction-0.9.0/contracts/core/BaseAccount.sol @@ -25,6 +25,7 @@ abstract contract BaseAccount is IAccount { } error ExecuteError(uint256 index, bytes error); + error NotFromEntryPoint(address msgSender, address entity, address entryPoint); /** * Return the account nonce. @@ -94,7 +95,11 @@ abstract contract BaseAccount is IAccount { function _requireFromEntryPoint() internal view virtual { require( msg.sender == address(entryPoint()), - "account: not from EntryPoint" + NotFromEntryPoint( + msg.sender, + address(this), + address(entryPoint()) + ) ); } diff --git a/dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/core/BasePaymaster.sol b/dependencies/eth-infinitism-account-abstraction-0.9.0/contracts/core/BasePaymaster.sol similarity index 69% rename from dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/core/BasePaymaster.sol rename to dependencies/eth-infinitism-account-abstraction-0.9.0/contracts/core/BasePaymaster.sol index dfaf555..5544a41 100644 --- a/dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/core/BasePaymaster.sol +++ b/dependencies/eth-infinitism-account-abstraction-0.9.0/contracts/core/BasePaymaster.sol @@ -7,28 +7,41 @@ import "@openzeppelin/contracts/access/Ownable2Step.sol"; import "@openzeppelin/contracts/utils/introspection/IERC165.sol"; import "../interfaces/IPaymaster.sol"; import "../interfaces/IEntryPoint.sol"; +import "./Stakeable.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; +abstract contract BasePaymaster is IPaymaster, Stakeable { + IEntryPoint internal 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; + error NotFromEntryPoint(address msgSender, address entity,address entryPoint); + error ERC165Error(address entryPoint, bytes4 interfaceId); + error MustOverride(); + + constructor(IEntryPoint __entryPoint, address owner) Ownable(owner) { + _validateEntryPointInterface(__entryPoint); + _entryPoint = __entryPoint; + } + + function entryPoint() public view override returns (IEntryPoint) { + return _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"); + function _validateEntryPointInterface(IEntryPoint __entryPoint) internal virtual { + bytes4 epInterfaceId = type(IEntryPoint).interfaceId; + require( + IERC165(address(__entryPoint)).supportsInterface(epInterfaceId), + ERC165Error(address(__entryPoint), epInterfaceId) + ); } /// @inheritdoc IPaymaster @@ -87,14 +100,14 @@ abstract contract BasePaymaster is IPaymaster, Ownable2Step { ) internal virtual { (mode, context, actualGasCost, actualUserOpFeePerGas); // unused params // subclass must override this method if validatePaymasterUserOp returns a context - revert("must override"); + revert MustOverride(); } /** * Add a deposit for this paymaster, used for paying for transaction fees. */ function deposit() public payable { - entryPoint.depositTo{value: msg.value}(address(this)); + entryPoint().depositTo{value: msg.value}(address(this)); } /** @@ -106,46 +119,26 @@ abstract contract BasePaymaster is IPaymaster, Ownable2Step { 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); + entryPoint().withdrawTo(withdrawAddress, amount); } /** * 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); + function getDeposit() public virtual view returns (uint256) { + return _entryPoint.balanceOf(address(this)); } /** * Validate the call is made from a valid entrypoint */ function _requireFromEntryPoint() internal virtual { - require(msg.sender == address(entryPoint), "Sender not EntryPoint"); + require(msg.sender == address(entryPoint()), + NotFromEntryPoint( + msg.sender, + address(this), + address(entryPoint()) + ) + ); } } diff --git a/dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/core/Eip7702Support.sol b/dependencies/eth-infinitism-account-abstraction-0.9.0/contracts/core/Eip7702Support.sol similarity index 92% rename from dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/core/Eip7702Support.sol rename to dependencies/eth-infinitism-account-abstraction-0.9.0/contracts/core/Eip7702Support.sol index bf8e035..51cabab 100644 --- a/dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/core/Eip7702Support.sol +++ b/dependencies/eth-infinitism-account-abstraction-0.9.0/contracts/core/Eip7702Support.sol @@ -1,5 +1,6 @@ -pragma solidity ^0.8.28; // SPDX-License-Identifier: MIT +pragma solidity ^0.8.28; + // solhint-disable no-inline-assembly import "../interfaces/PackedUserOperation.sol"; @@ -7,6 +8,9 @@ import "../core/UserOperationLib.sol"; library Eip7702Support { + error Eip7702SenderWithoutCode(address sender); + error Eip7702SenderNotDelegate(address sender); + // EIP-7702 code prefix before delegate address. bytes3 internal constant EIP7702_PREFIX = 0xef0100; @@ -72,9 +76,8 @@ library Eip7702Support { // 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"); + require(sender.code.length > 0, Eip7702SenderWithoutCode(sender)); + revert Eip7702SenderNotDelegate(sender); } 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.9.0/contracts/core/EntryPoint.sol similarity index 89% rename from dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/core/EntryPoint.sol rename to dependencies/eth-infinitism-account-abstraction-0.9.0/contracts/core/EntryPoint.sol index 7c2ddce..3b4feb6 100644 --- a/dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/core/EntryPoint.sol +++ b/dependencies/eth-infinitism-account-abstraction-0.9.0/contracts/core/EntryPoint.sol @@ -1,6 +1,8 @@ // SPDX-License-Identifier: GPL-3.0 pragma solidity ^0.8.28; + /* solhint-disable avoid-low-level-calls */ +/* solhint-disable gas-calldata-parameters */ /* solhint-disable no-inline-assembly */ import "../interfaces/IAccount.sol"; @@ -16,18 +18,20 @@ 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. + * Always verify the EntryPoint addresses across multiple trusted sources. + * Visit https://docs.erc4337.io/ for instructions and official documentation. + * Account-Abstraction (EIP-4337) singleton EntryPoint v0.9 implementation. * Only one instance required on each chain. * @custom:security-contact https://bounty.ethereum.org */ -contract EntryPoint is IEntryPoint, StakeManager, NonceManager, ReentrancyGuardTransient, ERC165, EIP712 { +contract EntryPoint is IEntryPoint, StakeManager, NonceManager, ERC165, EIP712 { using UserOperationLib for PackedUserOperation; + using Eip7702Support for address; /** * internal-use constants @@ -46,19 +50,35 @@ contract EntryPoint is IEntryPoint, StakeManager, NonceManager, ReentrancyGuardT // Threshold below which no penalty would be charged uint256 private constant PENALTY_GAS_THRESHOLD = 40000; + uint48 private constant VALIDITY_BLOCK_RANGE_FLAG = 0x800000000000; + uint48 private constant VALIDITY_BLOCK_RANGE_MASK = 0x7fffffffffff; + SenderCreator private immutable _senderCreator = new SenderCreator(); string constant internal DOMAIN_NAME = "ERC4337"; string constant internal DOMAIN_VERSION = "1"; + bytes32 transient private currentUserOpHash; + + error Reentrancy(); + constructor() EIP712(DOMAIN_NAME, DOMAIN_VERSION) { } + modifier nonReentrant() { + require( + // solhint-disable avoid-tx-origin + tx.origin == msg.sender && msg.sender.code.length == 0, + Reentrancy() + ); + _; + } + /// @inheritdoc IEntryPoint function handleOps( PackedUserOperation[] calldata ops, address payable beneficiary - ) external nonReentrant { + ) external virtual nonReentrant { uint256 opslen = ops.length; UserOpInfo[] memory opInfos = new UserOpInfo[](opslen); unchecked { @@ -79,7 +99,7 @@ contract EntryPoint is IEntryPoint, StakeManager, NonceManager, ReentrancyGuardT function handleAggregatedOps( UserOpsPerAggregator[] calldata opsPerAggregator, address payable beneficiary - ) external nonReentrant { + ) external virtual nonReentrant { unchecked { uint256 opasLen = opsPerAggregator.length; @@ -144,9 +164,14 @@ contract EntryPoint is IEntryPoint, StakeManager, NonceManager, ReentrancyGuardT return MessageHashUtils.toTypedDataHash(getDomainSeparatorV4(), userOp.hash(overrideInitCodeHash)); } + /// @inheritdoc IEntryPoint + function getCurrentUserOpHash( + ) public view returns (bytes32) { + return currentUserOpHash; + } /// @inheritdoc IEntryPoint - function getSenderAddress(bytes calldata initCode) external { + function getSenderAddress(bytes calldata initCode) external virtual { address sender = senderCreator().createSender(initCode); revert SenderAddressResult(sender); } @@ -157,12 +182,12 @@ contract EntryPoint is IEntryPoint, StakeManager, NonceManager, ReentrancyGuardT } /// @inheritdoc IEntryPoint - function delegateAndRevert(address target, bytes calldata data) external { + function delegateAndRevert(address target, bytes calldata data) external virtual { (bool success, bytes memory ret) = target.delegatecall(data); revert DelegateAndRevert(success, ret); } - function getPackedUserOpTypeHash() external pure returns (bytes32) { + function getPackedUserOpTypeHash() external virtual pure returns (bytes32) { return UserOperationLib.PACKED_USEROP_TYPEHASH; } @@ -186,9 +211,10 @@ contract EntryPoint is IEntryPoint, StakeManager, NonceManager, ReentrancyGuardT * @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"); + require(beneficiary != address(0), InvalidBeneficiary(beneficiary)); + currentUserOpHash = bytes32(0); + (bool success, bytes memory ret) = beneficiary.call{value: amount}(""); + require(success, FailedSendToBeneficiary(beneficiary, amount, ret)); } /** @@ -206,6 +232,7 @@ contract EntryPoint is IEntryPoint, StakeManager, NonceManager, ReentrancyGuardT internal virtual returns (uint256 collected) { uint256 preGas = gasleft(); + currentUserOpHash = opInfo.userOpHash; bytes memory context = _getMemoryBytesFromOffset(opInfo.contextOffset); bool success; { @@ -321,7 +348,7 @@ contract EntryPoint is IEntryPoint, StakeManager, NonceManager, ReentrancyGuardT UserOpInfo[] memory opInfos, address expectedAggregator, uint256 opIndexOffset - ) internal returns (uint256 opsLen){ + ) internal virtual returns (uint256 opsLen){ unchecked { opsLen = ops.length; for (uint256 i = 0; i < opsLen; i++) { @@ -377,9 +404,9 @@ contract EntryPoint is IEntryPoint, StakeManager, NonceManager, ReentrancyGuardT bytes memory callData, UserOpInfo memory opInfo, bytes calldata context - ) external returns (uint256 actualGasCost) { + ) external virtual returns (uint256 actualGasCost) { uint256 preGas = gasleft(); - require(msg.sender == address(this), "AA92 internal call only"); + require(msg.sender == address(this), InternalFunction()); MemoryUserOp memory mUserOp = opInfo.mUserOp; uint256 callGasLimit = mUserOp.callGasLimit; @@ -441,11 +468,11 @@ contract EntryPoint is IEntryPoint, StakeManager, NonceManager, ReentrancyGuardT if (paymasterAndData.length > 0) { require( paymasterAndData.length >= UserOperationLib.PAYMASTER_DATA_OFFSET, - "AA93 invalid paymasterAndData" + InvalidPaymasterData(paymasterAndData.length) ); address paymaster; (paymaster, mUserOp.paymasterVerificationGasLimit, mUserOp.paymasterPostOpGasLimit) = UserOperationLib.unpackPaymasterStaticFields(paymasterAndData); - require(paymaster != address(0), "AA98 invalid paymaster"); + require(paymaster != address(0), InvalidPaymaster(paymaster)); mUserOp.paymaster = paymaster; } } @@ -490,14 +517,24 @@ contract EntryPoint is IEntryPoint, StakeManager, NonceManager, ReentrancyGuardT senderCreator().initEip7702Sender{ gas: opInfo.mUserOp.verificationGasLimit }(sender, initCode[20 :]); + address delegate = sender._getEip7702Delegate(); + emit EIP7702AccountInitialized(opInfo.userOpHash, sender, delegate); } 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 factory = address(bytes20(initCode[0 : 20])); + if (sender.code.length != 0) { + // ignoring the initcode for an existing 'sender' contract + emit IgnoredInitCode( + opInfo.userOpHash, + sender, + factory + ); + return; + } address sender1 = senderCreator().createSender{ gas: opInfo.mUserOp.verificationGasLimit }(initCode); @@ -507,7 +544,6 @@ contract EntryPoint is IEntryPoint, StakeManager, NonceManager, ReentrancyGuardT 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, @@ -628,7 +664,7 @@ contract EntryPoint is IEntryPoint, StakeManager, NonceManager, ReentrancyGuardT uint256 pmVerificationGasLimit = mUserOp.paymasterVerificationGasLimit; (context, validationData) = _callValidatePaymasterUserOp(opIndex, op, opInfo); if (preGas - gasleft() > pmVerificationGasLimit) { - revert FailedOp(opIndex, "AA36 over paymasterVerificationGasLimit"); + revert FailedOp(opIndex, "AA36 over pmVerificationGasLimit"); } } } @@ -637,7 +673,7 @@ contract EntryPoint is IEntryPoint, StakeManager, NonceManager, ReentrancyGuardT uint256 opIndex, PackedUserOperation calldata op, UserOpInfo memory opInfo - ) internal returns (bytes memory context, uint256 validationData) { + ) internal virtual returns (bytes memory context, uint256 validationData) { uint256 freePtr = _getFreePtr(); bytes memory validatePaymasterCall = abi.encodeCall( IPaymaster.validatePaymasterUserOp, @@ -648,7 +684,6 @@ contract EntryPoint is IEntryPoint, StakeManager, NonceManager, ReentrancyGuardT 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) @@ -666,15 +701,19 @@ contract EntryPoint is IEntryPoint, StakeManager, NonceManager, ReentrancyGuardT 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) { + if (!success) { revert FailedOpWithRevert(opIndex, "AA33 reverted", Exec.getReturnData(REVERT_REASON_MAX_LEN)); } + // for a given 'contextLength', calculate the only valid 'returndatasize' value + uint256 expectedReturnDataSize = 96 + ((contextLength + 31) / 32) * 32; + if (contextOffset != 64 || len != expectedReturnDataSize) { + revert FailedOpWithRevert(opIndex, "AA35 malformed paymaster data", Exec.getReturnData(REVERT_REASON_MAX_LEN)); + } } finalizeAllocation(freePtr, len); } @@ -692,25 +731,32 @@ contract EntryPoint is IEntryPoint, StakeManager, NonceManager, ReentrancyGuardT uint256 paymasterValidationData, address expectedAggregator ) internal virtual view { - (address aggregator, bool outOfTimeRange) = _getValidationData( + (address aggregator, bool outOfValidityRange, bool isBlockRange) = _getValidationData( validationData ); if (expectedAggregator != aggregator) { revert FailedOp(opIndex, "AA24 signature error"); } - if (outOfTimeRange) { + if (outOfValidityRange) { + if (isBlockRange) { + revert FailedOp(opIndex, "AA27 outside valid block range"); + } 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( + (pmAggregator, outOfValidityRange, isBlockRange) = _getValidationData( paymasterValidationData ); if (pmAggregator != address(0)) { revert FailedOp(opIndex, "AA34 signature error"); } - if (outOfTimeRange) { + if (outOfValidityRange) { + if (isBlockRange) { + revert FailedOp(opIndex, "AA37 paymaster inval block range"); + } + // solhint-disable-next-line gas-small-strings revert FailedOp(opIndex, "AA32 paymaster expired or not due"); } } @@ -719,17 +765,26 @@ contract EntryPoint is IEntryPoint, StakeManager, NonceManager, ReentrancyGuardT * 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. + * @return outOfValidityRange true if current time is outside the time range of this validationData. */ function _getValidationData( uint256 validationData - ) internal virtual view returns (address aggregator, bool outOfTimeRange) { + ) internal virtual view returns (address aggregator, bool outOfValidityRange, bool isBlockRange) { if (validationData == 0) { - return (address(0), false); + return (address(0), false, false); } ValidationData memory data = _parseValidationData(validationData); - // solhint-disable-next-line not-rely-on-time - outOfTimeRange = block.timestamp > data.validUntil || block.timestamp <= data.validAfter; + // using top bit of 'validAfter' and 'validUntil' to indicate block-range instead of time-range + if (data.validAfter >= VALIDITY_BLOCK_RANGE_FLAG && data.validUntil >= VALIDITY_BLOCK_RANGE_FLAG) { + uint48 validAfterBlock = data.validAfter & VALIDITY_BLOCK_RANGE_MASK; + uint48 validUntilBlock = data.validUntil & VALIDITY_BLOCK_RANGE_MASK; + outOfValidityRange = block.number > validUntilBlock || block.number <= validAfterBlock; + isBlockRange = true; + } else { + // solhint-disable-next-line not-rely-on-time + outOfValidityRange = block.timestamp > data.validUntil || block.timestamp <= data.validAfter; + isBlockRange = false; + } aggregator = data.aggregator; } @@ -756,7 +811,7 @@ contract EntryPoint is IEntryPoint, StakeManager, NonceManager, ReentrancyGuardT MemoryUserOp memory mUserOp = outOpInfo.mUserOp; _copyUserOpToMemory(userOp, mUserOp); - // getUserOpHash uses temporary allocations, no required after it returns + // 'getUserOpHash' uses temporary memory allocation and all data allocated inside can be reused after it returns uint256 freePtr = _getFreePtr(); outOpInfo.userOpHash = getUserOpHash(userOp); _restoreFreePtr(freePtr); @@ -891,7 +946,7 @@ contract EntryPoint is IEntryPoint, StakeManager, NonceManager, ReentrancyGuardT */ function _getUserOpGasPrice( MemoryUserOp memory mUserOp - ) internal view returns (uint256) { + ) internal virtual view returns (uint256) { unchecked { uint256 maxFeePerGas = mUserOp.maxFeePerGas; uint256 maxPriorityFeePerGas = mUserOp.maxPriorityFeePerGas; @@ -945,7 +1000,7 @@ contract EntryPoint is IEntryPoint, StakeManager, NonceManager, ReentrancyGuardT } } - function _getUnusedGasPenalty(uint256 gasUsed, uint256 gasLimit) internal pure returns (uint256) { + function _getUnusedGasPenalty(uint256 gasUsed, uint256 gasLimit) internal virtual pure returns (uint256) { unchecked { if (gasLimit <= gasUsed + PENALTY_GAS_THRESHOLD) { return 0; diff --git a/dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/core/EntryPointSimulations.sol b/dependencies/eth-infinitism-account-abstraction-0.9.0/contracts/core/EntryPointSimulations.sol similarity index 93% rename from dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/core/EntryPointSimulations.sol rename to dependencies/eth-infinitism-account-abstraction-0.9.0/contracts/core/EntryPointSimulations.sol index 76e31d3..23e009b 100644 --- a/dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/core/EntryPointSimulations.sol +++ b/dependencies/eth-infinitism-account-abstraction-0.9.0/contracts/core/EntryPointSimulations.sol @@ -14,6 +14,9 @@ import "../interfaces/IEntryPointSimulations.sol"; */ contract EntryPointSimulations is EntryPoint, IEntryPointSimulations { + error NotImplemented(); + error PaymasterNotDeployed(address paymaster); + SenderCreator private _senderCreator; bytes32 private __domainSeparatorV4; @@ -32,14 +35,6 @@ contract EntryPointSimulations is EntryPoint, IEntryPointSimulations { 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 @@ -162,16 +157,17 @@ contract EntryPointSimulations is EntryPoint, IEntryPointSimulations { ) external view { if (initCode.length == 0 && sender.code.length == 0) { // it would revert anyway. but give a meaningful message - revert("AA20 account not deployed"); + revert FailedOp(0, "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"); + revert PaymasterNotDeployed(paymaster); } } // always revert + // solhint-disable-next-line gas-custom-errors revert(""); } @@ -192,6 +188,7 @@ contract EntryPointSimulations is EntryPoint, IEntryPointSimulations { // Copied from EIP712.sol bytes32 private constant TYPE_HASH = + // solhint-disable-next-line gas-small-strings keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)"); function __buildDomainSeparator() private view returns (bytes32) { @@ -212,4 +209,12 @@ contract EntryPointSimulations is EntryPoint, IEntryPointSimulations { function supportsInterface(bytes4) public view virtual override returns (bool) { return false; } + + function handleAggregatedOps( + UserOpsPerAggregator[] calldata, + address payable + ) external pure override(EntryPoint, IEntryPoint) { + revert NotImplemented(); + } + } diff --git a/dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/core/Helpers.sol b/dependencies/eth-infinitism-account-abstraction-0.9.0/contracts/core/Helpers.sol similarity index 63% rename from dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/core/Helpers.sol rename to dependencies/eth-infinitism-account-abstraction-0.9.0/contracts/core/Helpers.sol index 25f9fd3..b00524b 100644 --- a/dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/core/Helpers.sol +++ b/dependencies/eth-infinitism-account-abstraction-0.9.0/contracts/core/Helpers.sol @@ -1,8 +1,10 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.28; +import "./UserOperationLib.sol"; /* solhint-disable no-inline-assembly */ +using UserOperationLib for bytes; /* * For simulation purposes, validateUserOp (and validatePaymasterUserOp) @@ -92,14 +94,59 @@ function _packValidationData( * @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) +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) + } +} + +/** + * @notice Computes the Keccak-256 hash of a slice of calldata, followed by an 8-byte suffix. + * This function copies the first `len` bytes from the given calldata array `data` into memory. + * The assembly code is equivalent to: + * keccak256(abi.encodePacked(data[0:len], suffix)) + * But more efficient, and doesn't move the free memory pointer, allowing the memory to be reused later. + * + * @param data Calldata byte array to read from. + * @param len Number of bytes to copy from `data` starting at its offset. + * @param suffix 8-byte value appended to the data bytes before hashing. + * + * @return ret The hash of (data[0:len] || suffix). + */ +function calldataKeccakWithSuffix(bytes calldata data, uint256 len, bytes8 suffix) pure returns (bytes32 ret) { + assembly ("memory-safe") { + let mem := mload(0x40) + calldatacopy(mem, data.offset, len) + mstore(add(mem, len), suffix) + len := add(len, 8) + ret := keccak256(mem, len) + } +} + +/** + * Keccak function over paymaster data. + * If data ends with `PAYMASTER_SIG_MAGIC`, then + * read the previous 2 bytes as pmSignatureLength, + * and ignore this suffix from the hash. + * This means that the trailing pmSignatureLength+10 bytes are not covered by the UserOpHash, and thus are not signed. + * @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 paymasterDataKeccak(bytes calldata data) pure returns (bytes32 ret) { + uint256 pmSignatureLength = data.getPaymasterSignatureLength(); + if (pmSignatureLength > 0) { + unchecked { + //keccak everything up to the paymasterSignature, but still append the sig magic. + return calldataKeccakWithSuffix(data, data.length - (pmSignatureLength + UserOperationLib.PAYMASTER_SUFFIX_LEN), UserOperationLib.PAYMASTER_SIG_MAGIC); } } + return calldataKeccak(data); +} /** diff --git a/dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/core/NonceManager.sol b/dependencies/eth-infinitism-account-abstraction-0.9.0/contracts/core/NonceManager.sol similarity index 86% rename from dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/core/NonceManager.sol rename to dependencies/eth-infinitism-account-abstraction-0.9.0/contracts/core/NonceManager.sol index 461c795..4c0becd 100644 --- a/dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/core/NonceManager.sol +++ b/dependencies/eth-infinitism-account-abstraction-0.9.0/contracts/core/NonceManager.sol @@ -15,12 +15,12 @@ abstract contract NonceManager is INonceManager { /// @inheritdoc INonceManager function getNonce(address sender, uint192 key) - public view override returns (uint256 nonce) { + public virtual view override returns (uint256 nonce) { return nonceSequenceNumber[sender][key] | (uint256(key) << 64); } /// @inheritdoc INonceManager - function incrementNonce(uint192 key) external override { + function incrementNonce(uint192 key) external virtual override { nonceSequenceNumber[msg.sender][key]++; } @@ -30,7 +30,7 @@ abstract contract NonceManager is INonceManager { * @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) { + function _validateAndUpdateNonce(address sender, uint256 nonce) internal virtual returns (bool) { uint192 key = uint192(nonce >> 64); uint64 seq = uint64(nonce); diff --git a/dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/core/SenderCreator.sol b/dependencies/eth-infinitism-account-abstraction-0.9.0/contracts/core/SenderCreator.sol similarity index 86% rename from dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/core/SenderCreator.sol rename to dependencies/eth-infinitism-account-abstraction-0.9.0/contracts/core/SenderCreator.sol index 4268f79..1806989 100644 --- a/dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/core/SenderCreator.sol +++ b/dependencies/eth-infinitism-account-abstraction-0.9.0/contracts/core/SenderCreator.sol @@ -1,6 +1,8 @@ // SPDX-License-Identifier: GPL-3.0 pragma solidity ^0.8.28; + /* solhint-disable avoid-low-level-calls */ +/* solhint-disable gas-calldata-parameters */ /* solhint-disable no-inline-assembly */ import "../interfaces/ISenderCreator.sol"; @@ -12,6 +14,8 @@ import "../utils/Exec.sol"; * which is explicitly not the entryPoint itself. */ contract SenderCreator is ISenderCreator { + error NotFromEntryPoint(address msgSender, address entity, address entryPoint); + address public immutable entryPoint; constructor(){ @@ -29,7 +33,7 @@ contract SenderCreator is ISenderCreator { function createSender( bytes calldata initCode ) external returns (address sender) { - require(msg.sender == entryPoint, "AA97 should call from EntryPoint"); + require(msg.sender == entryPoint, NotFromEntryPoint(msg.sender, address(this), entryPoint)); address factory = address(bytes20(initCode[0 : 20])); bytes memory initCallData = initCode[20 :]; @@ -55,7 +59,7 @@ contract SenderCreator is ISenderCreator { address sender, bytes memory initCallData ) external { - require(msg.sender == entryPoint, "AA97 should call from EntryPoint"); + require(msg.sender == entryPoint, NotFromEntryPoint(msg.sender, address(this), entryPoint)); bool success; assembly ("memory-safe") { success := call( diff --git a/dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/core/StakeManager.sol b/dependencies/eth-infinitism-account-abstraction-0.9.0/contracts/core/StakeManager.sol similarity index 71% rename from dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/core/StakeManager.sol rename to dependencies/eth-infinitism-account-abstraction-0.9.0/contracts/core/StakeManager.sol index f5f8063..9731ea2 100644 --- a/dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/core/StakeManager.sol +++ b/dependencies/eth-infinitism-account-abstraction-0.9.0/contracts/core/StakeManager.sol @@ -18,7 +18,7 @@ abstract contract StakeManager is IStakeManager { /// @inheritdoc IStakeManager function getDepositInfo( address account - ) external view returns (DepositInfo memory info) { + ) external virtual view returns (DepositInfo memory info) { return deposits[account]; } @@ -28,14 +28,14 @@ abstract contract StakeManager is IStakeManager { */ function _getStakeInfo( address addr - ) internal view returns (StakeInfo memory info) { + ) internal virtual 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) { + function balanceOf(address account) public virtual view returns (uint256) { return deposits[account].deposit; } @@ -43,14 +43,13 @@ abstract contract StakeManager is IStakeManager { 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) { + function _incrementDeposit(address account, uint256 amount) internal virtual returns (uint256) { unchecked { DepositInfo storage info = deposits[account]; uint256 newAmount = info.deposit + amount; @@ -65,7 +64,7 @@ abstract contract StakeManager is IStakeManager { * @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) { + function _tryDecrementDeposit(address account, uint256 amount) internal virtual returns (bool) { unchecked { DepositInfo storage info = deposits[account]; uint256 currentDeposit = info.deposit; @@ -84,16 +83,16 @@ abstract contract StakeManager is IStakeManager { } /// @inheritdoc IStakeManager - function addStake(uint32 unstakeDelaySec) external payable { + function addStake(uint32 unstakeDelaySec) external virtual payable { DepositInfo storage info = deposits[msg.sender]; - require(unstakeDelaySec > 0, "must specify unstake delay"); + require(unstakeDelaySec > 0, InvalidUnstakeDelay(unstakeDelaySec, info.unstakeDelaySec)); require( unstakeDelaySec >= info.unstakeDelaySec, - "cannot decrease unstake time" + InvalidUnstakeDelay(unstakeDelaySec, info.unstakeDelaySec) ); uint256 stake = info.stake + msg.value; - require(stake > 0, "no stake specified"); - require(stake <= type(uint112).max, "stake overflow"); + require(stake > 0, InvalidStake(msg.value, info.stake)); + require(stake <= type(uint112).max, InvalidStake(msg.value, info.stake)); deposits[msg.sender] = DepositInfo( info.deposit, true, @@ -105,10 +104,10 @@ abstract contract StakeManager is IStakeManager { } /// @inheritdoc IStakeManager - function unlockStake() external { + function unlockStake() external virtual { DepositInfo storage info = deposits[msg.sender]; - require(info.unstakeDelaySec != 0, "not staked"); - require(info.staked, "already unstaking"); + require(info.unstakeDelaySec != 0, NotStaked(info.stake, info.unstakeDelaySec, info.staked)); + require(info.staked, NotStaked(info.stake, info.unstakeDelaySec, info.staked)); uint48 withdrawTime = uint48(block.timestamp) + info.unstakeDelaySec; info.withdrawTime = withdrawTime; info.staked = false; @@ -116,34 +115,34 @@ abstract contract StakeManager is IStakeManager { } /// @inheritdoc IStakeManager - function withdrawStake(address payable withdrawAddress) external { + function withdrawStake(address payable withdrawAddress) external virtual { 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(stake > 0, NotStaked(info.stake, info.unstakeDelaySec, info.staked)); + require(info.withdrawTime > 0, StakeNotUnlocked(info.withdrawTime, block.timestamp)); require( info.withdrawTime <= block.timestamp, - "Stake withdrawal is not due" + WithdrawalNotDue(info.withdrawTime, block.timestamp) ); 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"); + (bool success, bytes memory ret) = withdrawAddress.call{value: stake}(""); + require(success, StakeWithdrawalFailed(msg.sender, withdrawAddress, stake, ret)); } /// @inheritdoc IStakeManager function withdrawTo( address payable withdrawAddress, uint256 withdrawAmount - ) external { + ) external virtual { DepositInfo storage info = deposits[msg.sender]; uint256 currentDeposit = info.deposit; - require(withdrawAmount <= currentDeposit, "Withdraw amount too large"); + require(withdrawAmount <= currentDeposit, InsufficientDeposit(currentDeposit, withdrawAmount)); info.deposit = currentDeposit - withdrawAmount; emit Withdrawn(msg.sender, withdrawAddress, withdrawAmount); - (bool success,) = withdrawAddress.call{value: withdrawAmount}(""); - require(success, "failed to withdraw"); + (bool success, bytes memory ret) = withdrawAddress.call{value: withdrawAmount}(""); + require(success, DepositWithdrawalFailed(msg.sender, withdrawAddress, withdrawAmount, ret)); } } diff --git a/dependencies/eth-infinitism-account-abstraction-0.9.0/contracts/core/Stakeable.sol b/dependencies/eth-infinitism-account-abstraction-0.9.0/contracts/core/Stakeable.sol new file mode 100644 index 0000000..0db71e0 --- /dev/null +++ b/dependencies/eth-infinitism-account-abstraction-0.9.0/contracts/core/Stakeable.sol @@ -0,0 +1,44 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.28; + +import "../interfaces/IEntryPoint.sol"; +import "@openzeppelin/contracts/access/Ownable2Step.sol"; + +/** + * @title Stakeable + * @notice Helper that lets a contract add stake on the configured EntryPoint + * for itself. Intended for factories or paymasters so their owner can call + * the contract directly instead of interacting with EntryPoint. + */ +abstract contract Stakeable is Ownable2Step { + /** + * @dev Implementations must supply the EntryPoint instance that should receive the stake. + */ + function entryPoint() public view virtual returns (IEntryPoint); + + /** + * Add stake for this contract. + * This method can also carry eth value to add to the current stake. + * @param unstakeDelaySec - The unstake delay for this contract. Can only be increased. + */ + function addStake(uint32 unstakeDelaySec) external payable onlyOwner { + entryPoint().addStake{value: msg.value}(unstakeDelaySec); + } + + /** + * Unlock the stake, in order to withdraw it. + * The contract can't serve requests once unlocked, until it calls addStake again + */ + function unlockStake() external onlyOwner { + entryPoint().unlockStake(); + } + + /** + * Withdraw the entire contract'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); + } +} diff --git a/dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/core/UserOperationLib.sol b/dependencies/eth-infinitism-account-abstraction-0.9.0/contracts/core/UserOperationLib.sol similarity index 51% rename from dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/core/UserOperationLib.sol rename to dependencies/eth-infinitism-account-abstraction-0.9.0/contracts/core/UserOperationLib.sol index e6f50c6..c3fda26 100644 --- a/dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/core/UserOperationLib.sol +++ b/dependencies/eth-infinitism-account-abstraction-0.9.0/contracts/core/UserOperationLib.sol @@ -4,17 +4,24 @@ pragma solidity ^0.8.28; /* solhint-disable no-inline-assembly */ import "../interfaces/PackedUserOperation.sol"; -import {calldataKeccak, min} from "./Helpers.sol"; +import "./Helpers.sol"; /** * Utility functions helpful when working with UserOperation structs. */ library UserOperationLib { + error InvalidPaymasterSignatureLength(uint256 dataLength, uint256 pmSignatureLength); + uint256 public constant PAYMASTER_VALIDATION_GAS_OFFSET = 20; uint256 public constant PAYMASTER_POSTOP_GAS_OFFSET = 36; uint256 public constant PAYMASTER_DATA_OFFSET = 52; + uint256 constant internal PAYMASTER_SIG_MAGIC_LEN = 8; + uint256 constant internal PAYMASTER_SUFFIX_LEN = PAYMASTER_SIG_MAGIC_LEN + 2; // suffix length (signature length + magic) + bytes8 constant internal PAYMASTER_SIG_MAGIC = 0x22e325a297439656; // keccak("PaymasterSignature")[:8] + uint256 constant internal MIN_PAYMASTER_DATA_WITH_SUFFIX_LEN = PAYMASTER_DATA_OFFSET + PAYMASTER_SUFFIX_LEN; // minimum length of paymasterData that can contain a paymaster signature. + /** * Relayer/block builder might submit the TX with higher priorityFee, * but the user should not pay above what he signed for. @@ -30,6 +37,7 @@ library UserOperationLib { } bytes32 internal constant PACKED_USEROP_TYPEHASH = + // solhint-disable-next-line gas-small-strings keccak256( "PackedUserOperation(address sender,uint256 nonce,bytes initCode,bytes callData,bytes32 accountGasLimits,uint256 preVerificationGas,bytes32 gasFees,bytes paymasterAndData)" ); @@ -50,7 +58,7 @@ library UserOperationLib { bytes32 accountGasLimits = userOp.accountGasLimits; uint256 preVerificationGas = userOp.preVerificationGas; bytes32 gasFees = userOp.gasFees; - bytes32 hashPaymasterAndData = calldataKeccak(userOp.paymasterAndData); + bytes32 hashPaymasterAndData = paymasterDataKeccak(userOp.paymasterAndData); return abi.encode( UserOperationLib.PACKED_USEROP_TYPEHASH, @@ -117,6 +125,98 @@ library UserOperationLib { ); } + /** + * return the length of the paymaster signature appended in paymasterAndData. + * return 0 if no signature. + * note that this signature is not part of the userOpHash, and thus not signed by the user. + */ + function getPaymasterSignatureLength( + bytes calldata paymasterAndData + ) internal pure returns (uint256 paymasterSignatureLength) { + unchecked { + uint256 dataLength = paymasterAndData.length; + if (dataLength < MIN_PAYMASTER_DATA_WITH_SUFFIX_LEN) { + return 0; + } + bytes8 suffix8 = bytes8(paymasterAndData[dataLength - PAYMASTER_SIG_MAGIC_LEN : dataLength]); + if (suffix8 != PAYMASTER_SIG_MAGIC) { + return 0; + } + uint256 pmSignatureLength = uint16(bytes2(paymasterAndData[dataLength - PAYMASTER_SUFFIX_LEN :])); + + if (pmSignatureLength > dataLength - MIN_PAYMASTER_DATA_WITH_SUFFIX_LEN) { + // paymasterSignature cannot extend before the paymasterData + revert InvalidPaymasterSignatureLength(dataLength, pmSignatureLength); + } + return pmSignatureLength; + } + } + + /** + * return the paymasterData that is signed by the user's signature + * this data excludes the paymaster signature appended at the end of paymasterAndData + */ + function getSignedPaymasterData( + bytes calldata paymasterAndData + ) internal pure returns (bytes calldata signedPaymasterData) { + uint256 sigLen = getPaymasterSignatureLength(paymasterAndData); + uint256 paymasterDataLen = paymasterAndData.length; + if (sigLen != 0) { + paymasterDataLen -= (sigLen + PAYMASTER_SUFFIX_LEN); + } + return paymasterAndData[PAYMASTER_DATA_OFFSET : paymasterDataLen]; + } + + /** + * decodes dynamic signature appended to paymasterAndData + * note that this signature is not part of the userOpHash, and thus not signed by the user. + * @param paymasterAndData - The paymasterAndData field of the user operation + * @return pmSig the paymaster-specific signature (may be empty) + */ + function getPaymasterSignature(bytes calldata paymasterAndData + ) internal pure returns (bytes calldata pmSig) { + uint256 len = getPaymasterSignatureLength(paymasterAndData); + return getPaymasterSignatureWithLength(paymasterAndData, len); + } + + /** + * decodes dynamic signature appended to paymasterAndData + * Assumes the length field is valid, and was obtained from getPaymasterSignatureLength + * @param paymasterAndData - The paymasterAndData field of the user operation + * @param paymasterSignatureLength - length of the signature (as returned by getPaymasterSignatureLength) + * @return pmSig the paymaster-specific signature (may be empty) + */ + function getPaymasterSignatureWithLength( + bytes calldata paymasterAndData, uint256 paymasterSignatureLength + ) internal pure returns (bytes calldata pmSig) { + if (paymasterSignatureLength == 0) { + return paymasterAndData[0 : 0]; + } + uint256 dataLen = paymasterAndData.length; + unchecked { + uint256 pmSigEnd = dataLen - PAYMASTER_SUFFIX_LEN; + uint256 pmSigBegin = pmSigEnd - paymasterSignatureLength; + return paymasterAndData[pmSigBegin : pmSigEnd]; + } + } + + /** + * encode the paymaster signature as suffix to append to paymasterAndData + * This method is a reference for off-chain encoding of paymaster signature. + */ + function encodePaymasterSignature(bytes calldata paymasterSignature) internal pure returns (bytes memory) { + uint256 len = paymasterSignature.length; + if (len == 0) { + return ""; + } + + return abi.encodePacked( + paymasterSignature, + uint16(len), + PAYMASTER_SIG_MAGIC + ); + } + /** * Hash the user operation data. * @param userOp - The user operation data. diff --git a/dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/interfaces/IAccount.sol b/dependencies/eth-infinitism-account-abstraction-0.9.0/contracts/interfaces/IAccount.sol similarity index 100% rename from dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/interfaces/IAccount.sol rename to dependencies/eth-infinitism-account-abstraction-0.9.0/contracts/interfaces/IAccount.sol diff --git a/dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/interfaces/IAccountExecute.sol b/dependencies/eth-infinitism-account-abstraction-0.9.0/contracts/interfaces/IAccountExecute.sol similarity index 100% rename from dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/interfaces/IAccountExecute.sol rename to dependencies/eth-infinitism-account-abstraction-0.9.0/contracts/interfaces/IAccountExecute.sol diff --git a/dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/interfaces/IAggregator.sol b/dependencies/eth-infinitism-account-abstraction-0.9.0/contracts/interfaces/IAggregator.sol similarity index 100% rename from dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/interfaces/IAggregator.sol rename to dependencies/eth-infinitism-account-abstraction-0.9.0/contracts/interfaces/IAggregator.sol diff --git a/dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/interfaces/IEntryPoint.sol b/dependencies/eth-infinitism-account-abstraction-0.9.0/contracts/interfaces/IEntryPoint.sol similarity index 79% rename from dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/interfaces/IEntryPoint.sol rename to dependencies/eth-infinitism-account-abstraction-0.9.0/contracts/interfaces/IEntryPoint.sol index 81f7ca3..7d5f568 100644 --- a/dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/interfaces/IEntryPoint.sol +++ b/dependencies/eth-infinitism-account-abstraction-0.9.0/contracts/interfaces/IEntryPoint.sol @@ -51,6 +51,29 @@ interface IEntryPoint is IStakeManager, INonceManager { address paymaster ); + /** + * Account "sender" already exists and the 'initCode' was ignored. + * @param userOpHash - The current userOp. UserOperationEvent will follow. + * @param sender - The account that was supposed to be deployed. + * @param unusedFactory - The factory contract that was not used but was specified in the 'initCode'. + */ + event IgnoredInitCode( + bytes32 indexed userOpHash, + address indexed sender, + address unusedFactory + ); + + /** + * Account "sender" is an EIP-7702 account that was initialized during this UserOperation. + * @param userOpHash - The current userOp. UserOperationEvent will follow. + * @param sender - The account that was supposed to be deployed. + */ + event EIP7702AccountInitialized( + bytes32 indexed userOpHash, + address indexed sender, + address indexed delegate + ); + /** * An event emitted if the UserOperation "callData" reverted with non-zero length. * @param userOpHash - The request unique identifier. @@ -104,22 +127,32 @@ interface IEntryPoint is IStakeManager, INonceManager { 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. + * A custom revert error of 'handleOps' and 'handleAggregatedOps', to identify the offending UserOperation. + * Should be caught in off-chain 'handleOps'/'handleAggregatedOps' simulation and should 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). + * NOTE: If 'simulateValidation' passes successfully, there should be no reason for 'handleOps' to revert as well. + * + * @param opIndex - Index into the array of ops to the failed one. + * When using 'simulateValidation', this value 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, + * where "m" is "1" for factory, "2" for account, "3" for paymaster, and "9" for other issues, * so a failure can be attributed to the correct entity. */ error FailedOp(uint256 opIndex, string reason); + error InvalidBeneficiary(address beneficiary); + error FailedSendToBeneficiary(address beneficiary, uint256 amount, bytes revertData); + error InternalFunction(); + error InvalidPaymasterData(uint256 paymasterAndDataLength); + error InvalidPaymaster(address paymaster); + /** * 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 + * @param opIndex - Index of the failed UserOperation in the array of ops. In simulateValidation, this value is always zero. + * @param reason - Revert reason. See the 'FailedOp(uint256,string)' error above. + * @param inner - Revert data caught from the inner revert reason of an entity contract. * @dev note that inner is truncated to 2048 bytes */ error FailedOpWithRevert(uint256 opIndex, string reason, bytes inner); @@ -177,6 +210,12 @@ interface IEntryPoint is IStakeManager, INonceManager { PackedUserOperation calldata userOp ) external view returns (bytes32); + /** + * Allows the AA-aware contracts to query the hash of the currently running UserOperation. + * @return hash - the hash of the currently running UserOperation, or 0 if none. + */ + function getCurrentUserOpHash() external view returns (bytes32); + /** * Gas and return values during simulation. * @param preOpGas - The gas used for validation (including preValidationGas) diff --git a/dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/interfaces/IEntryPointSimulations.sol b/dependencies/eth-infinitism-account-abstraction-0.9.0/contracts/interfaces/IEntryPointSimulations.sol similarity index 82% rename from dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/interfaces/IEntryPointSimulations.sol rename to dependencies/eth-infinitism-account-abstraction-0.9.0/contracts/interfaces/IEntryPointSimulations.sol index 60cab7d..9e54c2a 100644 --- a/dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/interfaces/IEntryPointSimulations.sol +++ b/dependencies/eth-infinitism-account-abstraction-0.9.0/contracts/interfaces/IEntryPointSimulations.sol @@ -58,13 +58,11 @@ interface IEntryPointSimulations is IEntryPoint { ); /** - * 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. + * Simulate the full execution of a UserOperation, including both validation and target execution. + * It performs a full validation of the UserOperation, but ignores signature error. + * An optional target address is called after the UserOperation succeeds, + * and this call's status and returned data value are returned as part of the `ExecutionResult` struct. + * @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. diff --git a/dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/interfaces/INonceManager.sol b/dependencies/eth-infinitism-account-abstraction-0.9.0/contracts/interfaces/INonceManager.sol similarity index 95% rename from dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/interfaces/INonceManager.sol rename to dependencies/eth-infinitism-account-abstraction-0.9.0/contracts/interfaces/INonceManager.sol index 8f2cb1b..dd13609 100644 --- a/dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/interfaces/INonceManager.sol +++ b/dependencies/eth-infinitism-account-abstraction-0.9.0/contracts/interfaces/INonceManager.sol @@ -17,7 +17,7 @@ interface INonceManager { /** * Manually increment the nonce of the sender. - * This method is exposed just for completeness.. + * 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 diff --git a/dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/interfaces/IPaymaster.sol b/dependencies/eth-infinitism-account-abstraction-0.9.0/contracts/interfaces/IPaymaster.sol similarity index 100% rename from dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/interfaces/IPaymaster.sol rename to dependencies/eth-infinitism-account-abstraction-0.9.0/contracts/interfaces/IPaymaster.sol diff --git a/dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/interfaces/ISenderCreator.sol b/dependencies/eth-infinitism-account-abstraction-0.9.0/contracts/interfaces/ISenderCreator.sol similarity index 100% rename from dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/interfaces/ISenderCreator.sol rename to dependencies/eth-infinitism-account-abstraction-0.9.0/contracts/interfaces/ISenderCreator.sol diff --git a/dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/interfaces/IStakeManager.sol b/dependencies/eth-infinitism-account-abstraction-0.9.0/contracts/interfaces/IStakeManager.sol similarity index 83% rename from dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/interfaces/IStakeManager.sol rename to dependencies/eth-infinitism-account-abstraction-0.9.0/contracts/interfaces/IStakeManager.sol index 8128feb..f16d4c5 100644 --- a/dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/interfaces/IStakeManager.sol +++ b/dependencies/eth-infinitism-account-abstraction-0.9.0/contracts/interfaces/IStakeManager.sol @@ -7,6 +7,15 @@ pragma solidity ^0.8.28; * Stake is value locked for at least "unstakeDelay" by the staked entity. */ interface IStakeManager { + error InvalidUnstakeDelay(uint256 newUnstakeDelaySec, uint256 currentUnstakeDelaySec); + error InvalidStake(uint256 msgValue, uint256 currentStake); + error NotStaked(uint256 currentStake, uint256 unstakeDelaySec, bool staked); + error InsufficientDeposit(uint256 currentDeposit, uint256 withdrawAmount); + error StakeNotUnlocked(uint256 withdrawTime, uint256 blockTimestamp); + error WithdrawalNotDue(uint256 withdrawTime, uint256 blockTimestamp); + error StakeWithdrawalFailed(address account, address withdrawAddress, uint256 amount, bytes revertReason); + error DepositWithdrawalFailed(address account, address withdrawAddress, uint256 amount, bytes revertReason); + event Deposited(address indexed account, uint256 totalDeposit); event Withdrawn( diff --git a/dependencies/eth-infinitism-account-abstraction-0.9.0/contracts/interfaces/PackedUserOperation.sol b/dependencies/eth-infinitism-account-abstraction-0.9.0/contracts/interfaces/PackedUserOperation.sol new file mode 100644 index 0000000..bc14fb3 --- /dev/null +++ b/dependencies/eth-infinitism-account-abstraction-0.9.0/contracts/interfaces/PackedUserOperation.sol @@ -0,0 +1,46 @@ +// 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. + * + * + * Field layout (enforced on-chain by EntryPoint): + * - sender: must already be deployed, or be the address that `initCode` will deploy; for EIP-7702 onboarding, `initCode = 0x7702 || optionalPayload` + * and `sender.code` must begin `0xef0100 || delegate`. + * - nonce = uint192(key) || uint64(sequence); EntryPoint tracks sequential values of `sequence` separately for each `key` value. + * - initCode: + * * non-7702: `initCode = factory(20) || factoryCalldata`; the factory must return `sender` and deploy code. + * * The `initCode` will be ignored if the `sender` is already deployed. + * * 7702: `0x7702` (magic prefix), optionally padded to 20 bytes and followed by the actual `initializationCode` data. This optional payload is executed on `sender` to finalise delegate setup. + * - callData: executed verbatim; if it starts with `IAccountExecute.executeUserOp.selector` (0x8dd7712f), EntryPoint wraps and forwards `(userOp, userOpHash)`. + * - accountGasLimits =`uint128(verificationGasLimit) || uint128(callGasLimit)` + * - gasFees = `uint128(maxPriorityFeePerGas) || uint128(maxFeePerGas)` + * - paymasterAndData (if non-empty) = `paymaster(20) || verificationGasLimit(16) || postOpGasLimit(16) || paymasterData` + * * an optional paymasterSignature may be added by appending: + * `paymasterSignature || uint16(paymasterSignature.length) || PAYMASTER_SIG_MAGIC (0x22e325a297439656)` + * - signature: Used by the account to validate the UserOperation against the `userOpHash`. + * The hash covers all UserOperation fields, except `signature` and `paymasterSignature` + */ +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.9.0/contracts/legacy/v06/IAccount06.sol similarity index 98% rename from dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/legacy/v06/IAccount06.sol rename to dependencies/eth-infinitism-account-abstraction-0.9.0/contracts/legacy/v06/IAccount06.sol index a8c4bda..a27038a 100644 --- a/dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/legacy/v06/IAccount06.sol +++ b/dependencies/eth-infinitism-account-abstraction-0.9.0/contracts/legacy/v06/IAccount06.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity ^0.8.12; +pragma solidity ^0.8.28; import "./UserOperation06.sol"; diff --git a/dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/legacy/v06/IAggregator06.sol b/dependencies/eth-infinitism-account-abstraction-0.9.0/contracts/legacy/v06/IAggregator06.sol similarity index 98% rename from dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/legacy/v06/IAggregator06.sol rename to dependencies/eth-infinitism-account-abstraction-0.9.0/contracts/legacy/v06/IAggregator06.sol index dab1d30..edee606 100644 --- a/dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/legacy/v06/IAggregator06.sol +++ b/dependencies/eth-infinitism-account-abstraction-0.9.0/contracts/legacy/v06/IAggregator06.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity ^0.8.12; +pragma solidity ^0.8.28; import "./UserOperation06.sol"; diff --git a/dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/legacy/v06/IEntryPoint06.sol b/dependencies/eth-infinitism-account-abstraction-0.9.0/contracts/legacy/v06/IEntryPoint06.sol similarity index 99% rename from dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/legacy/v06/IEntryPoint06.sol rename to dependencies/eth-infinitism-account-abstraction-0.9.0/contracts/legacy/v06/IEntryPoint06.sol index 6b53fd6..c9caaf4 100644 --- a/dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/legacy/v06/IEntryPoint06.sol +++ b/dependencies/eth-infinitism-account-abstraction-0.9.0/contracts/legacy/v06/IEntryPoint06.sol @@ -3,7 +3,7 @@ ** Only one instance required on each chain. **/ // SPDX-License-Identifier: MIT -pragma solidity ^0.8.12; +pragma solidity ^0.8.28; /* solhint-disable avoid-low-level-calls */ /* solhint-disable no-inline-assembly */ diff --git a/dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/legacy/v06/INonceManager06.sol b/dependencies/eth-infinitism-account-abstraction-0.9.0/contracts/legacy/v06/INonceManager06.sol similarity index 97% rename from dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/legacy/v06/INonceManager06.sol rename to dependencies/eth-infinitism-account-abstraction-0.9.0/contracts/legacy/v06/INonceManager06.sol index dd7f576..dfdfc82 100644 --- a/dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/legacy/v06/INonceManager06.sol +++ b/dependencies/eth-infinitism-account-abstraction-0.9.0/contracts/legacy/v06/INonceManager06.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity ^0.8.12; +pragma solidity ^0.8.28; interface INonceManager06 { diff --git a/dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/legacy/v06/IPaymaster06.sol b/dependencies/eth-infinitism-account-abstraction-0.9.0/contracts/legacy/v06/IPaymaster06.sol similarity index 99% rename from dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/legacy/v06/IPaymaster06.sol rename to dependencies/eth-infinitism-account-abstraction-0.9.0/contracts/legacy/v06/IPaymaster06.sol index e111b00..c3d598d 100644 --- a/dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/legacy/v06/IPaymaster06.sol +++ b/dependencies/eth-infinitism-account-abstraction-0.9.0/contracts/legacy/v06/IPaymaster06.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity ^0.8.12; +pragma solidity ^0.8.28; import "./UserOperation06.sol"; diff --git a/dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/legacy/v06/IStakeManager06.sol b/dependencies/eth-infinitism-account-abstraction-0.9.0/contracts/legacy/v06/IStakeManager06.sol similarity index 99% rename from dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/legacy/v06/IStakeManager06.sol rename to dependencies/eth-infinitism-account-abstraction-0.9.0/contracts/legacy/v06/IStakeManager06.sol index c07c25f..90c9909 100644 --- a/dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/legacy/v06/IStakeManager06.sol +++ b/dependencies/eth-infinitism-account-abstraction-0.9.0/contracts/legacy/v06/IStakeManager06.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity ^0.8.12; +pragma solidity ^0.8.28; /** * manage deposits and stakes. diff --git a/dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/legacy/v06/UserOperation06.sol b/dependencies/eth-infinitism-account-abstraction-0.9.0/contracts/legacy/v06/UserOperation06.sol similarity index 98% rename from dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/legacy/v06/UserOperation06.sol rename to dependencies/eth-infinitism-account-abstraction-0.9.0/contracts/legacy/v06/UserOperation06.sol index 1479bcc..9277fdd 100644 --- a/dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/legacy/v06/UserOperation06.sol +++ b/dependencies/eth-infinitism-account-abstraction-0.9.0/contracts/legacy/v06/UserOperation06.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity ^0.8.12; +pragma solidity ^0.8.28; /** * User Operation struct diff --git a/dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/test/GasCalcPaymasterWithPostOp.sol b/dependencies/eth-infinitism-account-abstraction-0.9.0/contracts/test/GasCalcPaymasterWithPostOp.sol similarity index 100% rename from dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/test/GasCalcPaymasterWithPostOp.sol rename to dependencies/eth-infinitism-account-abstraction-0.9.0/contracts/test/GasCalcPaymasterWithPostOp.sol diff --git a/dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/test/MaliciousAccount.sol b/dependencies/eth-infinitism-account-abstraction-0.9.0/contracts/test/MaliciousAccount.sol similarity index 97% rename from dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/test/MaliciousAccount.sol rename to dependencies/eth-infinitism-account-abstraction-0.9.0/contracts/test/MaliciousAccount.sol index dbb3a2c..f94a8f6 100644 --- a/dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/test/MaliciousAccount.sol +++ b/dependencies/eth-infinitism-account-abstraction-0.9.0/contracts/test/MaliciousAccount.sol @@ -1,6 +1,8 @@ // SPDX-License-Identifier: GPL-3.0 pragma solidity ^0.8.28; +/* solhint-disable gas-custom-errors */ + import "../interfaces/IAccount.sol"; import "../interfaces/IEntryPoint.sol"; import "../core/UserOperationLib.sol"; diff --git a/dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/test/TestAggregatedAccount.sol b/dependencies/eth-infinitism-account-abstraction-0.9.0/contracts/test/TestAggregatedAccount.sol similarity index 100% rename from dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/test/TestAggregatedAccount.sol rename to dependencies/eth-infinitism-account-abstraction-0.9.0/contracts/test/TestAggregatedAccount.sol diff --git a/dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/test/TestAggregatedAccountFactory.sol b/dependencies/eth-infinitism-account-abstraction-0.9.0/contracts/test/TestAggregatedAccountFactory.sol similarity index 95% rename from dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/test/TestAggregatedAccountFactory.sol rename to dependencies/eth-infinitism-account-abstraction-0.9.0/contracts/test/TestAggregatedAccountFactory.sol index d1cda5e..37a9865 100644 --- a/dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/test/TestAggregatedAccountFactory.sol +++ b/dependencies/eth-infinitism-account-abstraction-0.9.0/contracts/test/TestAggregatedAccountFactory.sol @@ -39,7 +39,7 @@ contract TestAggregatedAccountFactory { /** * calculate the counterfactual address of this account as it would be returned by createAccount() */ - function getAddress(address owner,uint256 salt) public view returns (address) { + function getAddress(address owner,uint256 salt) public virtual view returns (address) { return Create2.computeAddress(bytes32(salt), keccak256(abi.encodePacked( type(ERC1967Proxy).creationCode, abi.encode( diff --git a/dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/test/TestCounter.sol b/dependencies/eth-infinitism-account-abstraction-0.9.0/contracts/test/TestCounter.sol similarity index 95% rename from dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/test/TestCounter.sol rename to dependencies/eth-infinitism-account-abstraction-0.9.0/contracts/test/TestCounter.sol index c56a934..153d040 100644 --- a/dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/test/TestCounter.sol +++ b/dependencies/eth-infinitism-account-abstraction-0.9.0/contracts/test/TestCounter.sol @@ -1,6 +1,8 @@ // SPDX-License-Identifier: GPL-3.0 pragma solidity ^0.8.28; +/* solhint-disable gas-custom-errors */ + // Sample "receiver" contract, for testing "exec" from account. contract TestCounter { mapping(address => uint256) public counters; diff --git a/dependencies/eth-infinitism-account-abstraction-0.9.0/contracts/test/TestCurrentUserOpHash.sol b/dependencies/eth-infinitism-account-abstraction-0.9.0/contracts/test/TestCurrentUserOpHash.sol new file mode 100644 index 0000000..859697e --- /dev/null +++ b/dependencies/eth-infinitism-account-abstraction-0.9.0/contracts/test/TestCurrentUserOpHash.sol @@ -0,0 +1,16 @@ +// SPDX-License-Identifier: GPL-3.0 +pragma solidity ^0.8.28; + +import "../interfaces/IEntryPoint.sol"; + +// A test "receiver" contract for testing the "getCurrentUserOpHash" function. +contract TestCurrentUserOpHash { + uint256 private counter; + + event GotCurrentUserOpHash(uint256 count, bytes32 userOpHash); + + function getCurrentUserOpHashFromEntryPoint(IEntryPoint entryPoint) public { + bytes32 userOpHash = entryPoint.getCurrentUserOpHash(); + emit GotCurrentUserOpHash(counter++, userOpHash); + } +} diff --git a/dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/test/TestERC20.sol b/dependencies/eth-infinitism-account-abstraction-0.9.0/contracts/test/TestERC20.sol similarity index 100% rename from dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/test/TestERC20.sol rename to dependencies/eth-infinitism-account-abstraction-0.9.0/contracts/test/TestERC20.sol diff --git a/dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/test/TestEip7702DelegateAccount.sol b/dependencies/eth-infinitism-account-abstraction-0.9.0/contracts/test/TestEip7702DelegateAccount.sol similarity index 84% rename from dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/test/TestEip7702DelegateAccount.sol rename to dependencies/eth-infinitism-account-abstraction-0.9.0/contracts/test/TestEip7702DelegateAccount.sol index cd87cbc..441bbe1 100644 --- a/dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/test/TestEip7702DelegateAccount.sol +++ b/dependencies/eth-infinitism-account-abstraction-0.9.0/contracts/test/TestEip7702DelegateAccount.sol @@ -1,5 +1,7 @@ -pragma solidity ^0.8.28; // SPDX-License-Identifier: GPL-3.0 +pragma solidity ^0.8.28; + +/* solhint-disable gas-custom-errors */ import "../accounts/Simple7702Account.sol"; @@ -7,6 +9,8 @@ contract TestEip7702DelegateAccount is Simple7702Account { bool public testInitCalled; + constructor(IEntryPoint anEntryPoint) Simple7702Account(anEntryPoint) {} + function testInit() public { testInitCalled = true; } diff --git a/dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/test/TestExecAccount.sol b/dependencies/eth-infinitism-account-abstraction-0.9.0/contracts/test/TestExecAccount.sol similarity index 52% rename from dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/test/TestExecAccount.sol rename to dependencies/eth-infinitism-account-abstraction-0.9.0/contracts/test/TestExecAccount.sol index a3fa6a1..3dddc0a 100644 --- a/dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/test/TestExecAccount.sol +++ b/dependencies/eth-infinitism-account-abstraction-0.9.0/contracts/test/TestExecAccount.sol @@ -1,10 +1,9 @@ // SPDX-License-Identifier: GPL-3.0 +pragma solidity ^0.8.28; -/* solhint-disable one-contract-per-file */ /* solhint-disable avoid-low-level-calls */ -pragma solidity ^0.8.28; +/* solhint-disable gas-custom-errors */ -import "@openzeppelin/contracts/utils/Create2.sol"; import "@openzeppelin/contracts/proxy/ERC1967/ERC1967Proxy.sol"; import "../accounts/SimpleAccount.sol"; @@ -41,35 +40,3 @@ contract TestExecAccount is SimpleAccount, IAccountExecute { } } -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.9.0/contracts/test/TestExecAccountFactory.sol b/dependencies/eth-infinitism-account-abstraction-0.9.0/contracts/test/TestExecAccountFactory.sol new file mode 100644 index 0000000..b377eb1 --- /dev/null +++ b/dependencies/eth-infinitism-account-abstraction-0.9.0/contracts/test/TestExecAccountFactory.sol @@ -0,0 +1,42 @@ +// SPDX-License-Identifier: GPL-3.0 +pragma solidity ^0.8.28; + +/* solhint-disable avoid-low-level-calls */ +/* solhint-disable gas-custom-errors */ + +import "@openzeppelin/contracts/utils/Create2.sol"; + +import "./TestExecAccount.sol"; + +contract TestExecAccountFactory { + TestExecAccount public immutable accountImplementation; + + constructor(IEntryPoint _entryPoint) { + accountImplementation = new TestExecAccount(_entryPoint); + } + + function createAccount(address owner, uint256 salt) public virtual 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.9.0/contracts/test/TestExpirePaymaster.sol similarity index 98% rename from dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/test/TestExpirePaymaster.sol rename to dependencies/eth-infinitism-account-abstraction-0.9.0/contracts/test/TestExpirePaymaster.sol index 103a0b5..479e4a6 100644 --- a/dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/test/TestExpirePaymaster.sol +++ b/dependencies/eth-infinitism-account-abstraction-0.9.0/contracts/test/TestExpirePaymaster.sol @@ -10,7 +10,7 @@ import "../core/Helpers.sol"; */ contract TestExpirePaymaster is BasePaymaster { // solhint-disable no-empty-blocks - constructor(IEntryPoint _entryPoint) BasePaymaster(_entryPoint) + constructor(IEntryPoint _entryPoint) BasePaymaster(_entryPoint, msg.sender) {} function _validatePaymasterUserOp(PackedUserOperation calldata userOp, bytes32 userOpHash, uint256 maxCost) diff --git a/dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/test/TestExpiryAccount.sol b/dependencies/eth-infinitism-account-abstraction-0.9.0/contracts/test/TestExpiryAccount.sol similarity index 97% rename from dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/test/TestExpiryAccount.sol rename to dependencies/eth-infinitism-account-abstraction-0.9.0/contracts/test/TestExpiryAccount.sol index 53c849e..0a9f48a 100644 --- a/dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/test/TestExpiryAccount.sol +++ b/dependencies/eth-infinitism-account-abstraction-0.9.0/contracts/test/TestExpiryAccount.sol @@ -1,6 +1,8 @@ // SPDX-License-Identifier: GPL-3.0 pragma solidity ^0.8.28; +/* solhint-disable gas-custom-errors */ + import "../accounts/SimpleAccount.sol"; import "../core/Helpers.sol"; diff --git a/dependencies/eth-infinitism-account-abstraction-0.9.0/contracts/test/TestHelpers.sol b/dependencies/eth-infinitism-account-abstraction-0.9.0/contracts/test/TestHelpers.sol new file mode 100644 index 0000000..d5230d5 --- /dev/null +++ b/dependencies/eth-infinitism-account-abstraction-0.9.0/contracts/test/TestHelpers.sol @@ -0,0 +1,39 @@ +// 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); + } + + function getPaymasterSignatureLength( + bytes calldata paymasterAndData + ) public pure returns (uint256 paymasterSignatureLength) { + return UserOperationLib.getPaymasterSignatureLength(paymasterAndData); + } + + function getPaymasterSignatureWithLength( + bytes calldata paymasterAndData, uint256 paymasterSignatureLength + ) public pure returns (bytes calldata) { + return UserOperationLib.getPaymasterSignatureWithLength(paymasterAndData, paymasterSignatureLength); + } + + function encodePaymasterSignature(bytes calldata paymasterSignature) public pure returns (bytes memory) { + return UserOperationLib.encodePaymasterSignature(paymasterSignature); + } + + function _calldataKeccakWithSuffix(bytes calldata data, uint256 len, bytes8 suffix) public pure returns (bytes32 ret) { + return calldataKeccakWithSuffix(data, len, suffix); + } +} diff --git a/dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/test/TestPaymasterAcceptAll.sol b/dependencies/eth-infinitism-account-abstraction-0.9.0/contracts/test/TestPaymasterAcceptAll.sol similarity index 97% rename from dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/test/TestPaymasterAcceptAll.sol rename to dependencies/eth-infinitism-account-abstraction-0.9.0/contracts/test/TestPaymasterAcceptAll.sol index 6a388ab..673b06b 100644 --- a/dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/test/TestPaymasterAcceptAll.sol +++ b/dependencies/eth-infinitism-account-abstraction-0.9.0/contracts/test/TestPaymasterAcceptAll.sol @@ -9,7 +9,7 @@ import "../core/Helpers.sol"; */ contract TestPaymasterAcceptAll is BasePaymaster { - constructor(IEntryPoint _entryPoint) BasePaymaster(_entryPoint) { + constructor(IEntryPoint _entryPoint) BasePaymaster(_entryPoint, msg.sender) { // to support "deterministic address" factory // solhint-disable avoid-tx-origin if (tx.origin != msg.sender) { diff --git a/dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/test/TestPaymasterRevertCustomError.sol b/dependencies/eth-infinitism-account-abstraction-0.9.0/contracts/test/TestPaymasterRevertCustomError.sol similarity index 94% rename from dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/test/TestPaymasterRevertCustomError.sol rename to dependencies/eth-infinitism-account-abstraction-0.9.0/contracts/test/TestPaymasterRevertCustomError.sol index 8a7171e..0e61f1d 100644 --- a/dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/test/TestPaymasterRevertCustomError.sol +++ b/dependencies/eth-infinitism-account-abstraction-0.9.0/contracts/test/TestPaymasterRevertCustomError.sol @@ -19,7 +19,7 @@ contract TestPaymasterRevertCustomError is BasePaymaster { RevertType private revertType; // solhint-disable no-empty-blocks - constructor(IEntryPoint _entryPoint) BasePaymaster(_entryPoint) + constructor(IEntryPoint _entryPoint) BasePaymaster(_entryPoint, msg.sender) {} function _validatePaymasterUserOp(PackedUserOperation calldata userOp, bytes32, uint256) @@ -35,6 +35,7 @@ contract TestPaymasterRevertCustomError is BasePaymaster { function _postOp(PostOpMode, bytes calldata, uint256, uint256) internal view override { if (revertType == RevertType.customError){ + // solhint-disable-next-line gas-small-strings revert CustomError("this is a long revert reason string we are looking for"); } else if (revertType == RevertType.entryPointError){ diff --git a/dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/test/TestPaymasterWithPostOp.sol b/dependencies/eth-infinitism-account-abstraction-0.9.0/contracts/test/TestPaymasterWithPostOp.sol similarity index 99% rename from dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/test/TestPaymasterWithPostOp.sol rename to dependencies/eth-infinitism-account-abstraction-0.9.0/contracts/test/TestPaymasterWithPostOp.sol index a7a513d..32af5fe 100644 --- a/dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/test/TestPaymasterWithPostOp.sol +++ b/dependencies/eth-infinitism-account-abstraction-0.9.0/contracts/test/TestPaymasterWithPostOp.sol @@ -1,9 +1,10 @@ // SPDX-License-Identifier: GPL-3.0 pragma solidity ^0.8.28; -import "./TestPaymasterAcceptAll.sol"; /* solhint-disable no-empty-blocks */ +import "./TestPaymasterAcceptAll.sol"; + /** * test paymaster, that pays for everything, without any check. * explicitly returns a context, to test cost (for entrypoint) to call postOp diff --git a/dependencies/eth-infinitism-account-abstraction-0.9.0/contracts/test/TestPaymasterWithSig.sol b/dependencies/eth-infinitism-account-abstraction-0.9.0/contracts/test/TestPaymasterWithSig.sol new file mode 100644 index 0000000..590baf7 --- /dev/null +++ b/dependencies/eth-infinitism-account-abstraction-0.9.0/contracts/test/TestPaymasterWithSig.sol @@ -0,0 +1,38 @@ +// SPDX-License-Identifier: GPL-3.0 +pragma solidity ^0.8.28; + +import "../core/BasePaymaster.sol"; +import "../core/UserOperationLib.sol"; +import "../core/Helpers.sol"; + +/* solhint-disable gas-custom-errors */ + +/** + * test paymaster sig: + * a paymaster that handles different "signature" appended after the UserOperation was signed by the user. + * valid signature is when the two uint256 numbers in the signature add to 100... + */ +contract TestPaymasterWithSig is BasePaymaster { + + // solhint-disable no-empty-blocks + constructor(IEntryPoint _entryPoint) BasePaymaster(_entryPoint, msg.sender) + {} + + function _validatePaymasterUserOp(PackedUserOperation calldata userOp, bytes32 userOpHash, uint256 maxCost) + internal virtual override view + returns (bytes memory context, uint256 validationData) { + (userOpHash, maxCost); + bytes memory signedPaymasterData = UserOperationLib.getSignedPaymasterData(userOp.paymasterAndData); + (uint256 testData) = abi.decode(signedPaymasterData, (uint256)); + require(testData & 0xff == 0x11, "expected testData=0x11"); + + uint256 len = UserOperationLib.getPaymasterSignatureLength(userOp.paymasterAndData); + require(len > 0, "missing paymasterSig"); + bytes calldata paymasterSignature = UserOperationLib.getPaymasterSignatureWithLength(userOp.paymasterAndData, len); + (uint256 a, uint256 b) = abi.decode(paymasterSignature, (uint256, uint256)); + if (a + b != 100) { + return ("", SIG_VALIDATION_FAILED); + } + return ("", SIG_VALIDATION_SUCCESS); + } +} diff --git a/dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/test/TestRevertAccount.sol b/dependencies/eth-infinitism-account-abstraction-0.9.0/contracts/test/TestRevertAccount.sol similarity index 99% rename from dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/test/TestRevertAccount.sol rename to dependencies/eth-infinitism-account-abstraction-0.9.0/contracts/test/TestRevertAccount.sol index 8648e22..14b186e 100644 --- a/dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/test/TestRevertAccount.sol +++ b/dependencies/eth-infinitism-account-abstraction-0.9.0/contracts/test/TestRevertAccount.sol @@ -1,8 +1,10 @@ // 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 { diff --git a/dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/test/TestSignatureAggregator.sol b/dependencies/eth-infinitism-account-abstraction-0.9.0/contracts/test/TestSignatureAggregator.sol similarity index 95% rename from dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/test/TestSignatureAggregator.sol rename to dependencies/eth-infinitism-account-abstraction-0.9.0/contracts/test/TestSignatureAggregator.sol index 0b91346..9a7ff2b 100644 --- a/dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/test/TestSignatureAggregator.sol +++ b/dependencies/eth-infinitism-account-abstraction-0.9.0/contracts/test/TestSignatureAggregator.sol @@ -1,6 +1,8 @@ // SPDX-License-Identifier: GPL-3.0 pragma solidity ^0.8.28; +/* solhint-disable gas-custom-errors */ +/* solhint-disable gas-small-strings */ /* solhint-disable reason-string */ import "../interfaces/IAggregator.sol"; diff --git a/dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/test/TestToken.sol b/dependencies/eth-infinitism-account-abstraction-0.9.0/contracts/test/TestToken.sol similarity index 100% rename from dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/test/TestToken.sol rename to dependencies/eth-infinitism-account-abstraction-0.9.0/contracts/test/TestToken.sol diff --git a/dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/test/TestUniswap.sol b/dependencies/eth-infinitism-account-abstraction-0.9.0/contracts/test/TestUniswap.sol similarity index 98% rename from dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/test/TestUniswap.sol rename to dependencies/eth-infinitism-account-abstraction-0.9.0/contracts/test/TestUniswap.sol index 1bae614..af83394 100644 --- a/dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/test/TestUniswap.sol +++ b/dependencies/eth-infinitism-account-abstraction-0.9.0/contracts/test/TestUniswap.sol @@ -1,6 +1,8 @@ // SPDX-License-Identifier: GPL-3.0 pragma solidity ^0.8.28; +/* solhint-disable gas-custom-errors */ + import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import "@uniswap/v3-periphery/contracts/interfaces/ISwapRouter.sol"; diff --git a/dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/test/TestUtil.sol b/dependencies/eth-infinitism-account-abstraction-0.9.0/contracts/test/TestUtil.sol similarity index 100% rename from dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/test/TestUtil.sol rename to dependencies/eth-infinitism-account-abstraction-0.9.0/contracts/test/TestUtil.sol diff --git a/dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/test/TestWarmColdAccount.sol b/dependencies/eth-infinitism-account-abstraction-0.9.0/contracts/test/TestWarmColdAccount.sol similarity index 99% rename from dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/test/TestWarmColdAccount.sol rename to dependencies/eth-infinitism-account-abstraction-0.9.0/contracts/test/TestWarmColdAccount.sol index 9201d71..00ea76d 100644 --- a/dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/test/TestWarmColdAccount.sol +++ b/dependencies/eth-infinitism-account-abstraction-0.9.0/contracts/test/TestWarmColdAccount.sol @@ -1,5 +1,6 @@ // SPDX-License-Identifier: GPL-3.0 pragma solidity ^0.8.28; + /* solhint-disable no-inline-assembly */ import "../interfaces/IEntryPoint.sol"; diff --git a/dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/test/TestWrappedNativeToken.sol b/dependencies/eth-infinitism-account-abstraction-0.9.0/contracts/test/TestWrappedNativeToken.sol similarity index 94% rename from dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/test/TestWrappedNativeToken.sol rename to dependencies/eth-infinitism-account-abstraction-0.9.0/contracts/test/TestWrappedNativeToken.sol index 3070525..d405160 100644 --- a/dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/test/TestWrappedNativeToken.sol +++ b/dependencies/eth-infinitism-account-abstraction-0.9.0/contracts/test/TestWrappedNativeToken.sol @@ -1,6 +1,8 @@ // SPDX-License-Identifier:GPL-3.0 pragma solidity ^0.8.28; +/* solhint-disable gas-custom-errors */ + import "@openzeppelin/contracts/token/ERC20/ERC20.sol"; /** diff --git a/dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/utils/Exec.sol b/dependencies/eth-infinitism-account-abstraction-0.9.0/contracts/utils/Exec.sol similarity index 100% rename from dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/utils/Exec.sol rename to dependencies/eth-infinitism-account-abstraction-0.9.0/contracts/utils/Exec.sol diff --git a/dependencies/eth-infinitism-account-abstraction-0.8.0/deploy/1_deploy_entrypoint.ts b/dependencies/eth-infinitism-account-abstraction-0.9.0/deploy/1_deploy_entrypoint.ts similarity index 100% rename from dependencies/eth-infinitism-account-abstraction-0.8.0/deploy/1_deploy_entrypoint.ts rename to dependencies/eth-infinitism-account-abstraction-0.9.0/deploy/1_deploy_entrypoint.ts diff --git a/dependencies/eth-infinitism-account-abstraction-0.8.0/deploy/2_deploy_SimpleAccountFactory.ts b/dependencies/eth-infinitism-account-abstraction-0.9.0/deploy/2_deploy_SimpleAccountFactory.ts similarity index 100% rename from dependencies/eth-infinitism-account-abstraction-0.8.0/deploy/2_deploy_SimpleAccountFactory.ts rename to dependencies/eth-infinitism-account-abstraction-0.9.0/deploy/2_deploy_SimpleAccountFactory.ts diff --git a/dependencies/eth-infinitism-account-abstraction-0.9.0/deploy/3_deploy_Simple7702Account.ts b/dependencies/eth-infinitism-account-abstraction-0.9.0/deploy/3_deploy_Simple7702Account.ts new file mode 100644 index 0000000..52b229e --- /dev/null +++ b/dependencies/eth-infinitism-account-abstraction-0.9.0/deploy/3_deploy_Simple7702Account.ts @@ -0,0 +1,23 @@ +import { HardhatRuntimeEnvironment } from 'hardhat/types' +import { DeployFunction } from 'hardhat-deploy/types' +import { ethers } from 'hardhat' + +const deploySimple7702Account: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { + const provider = ethers.provider + const from = await provider.getSigner().getAddress() + + // Get the deployed EntryPoint address + const entryPointDeployment = await hre.deployments.get('EntryPoint') + const entryPointAddress = entryPointDeployment.address + + await hre.deployments.deploy( + 'Simple7702Account', { + from, + args: [entryPointAddress], + gasLimit: 6e6, + deterministicDeployment: true, + log: true + }) +} + +export default deploySimple7702Account diff --git a/dependencies/eth-infinitism-account-abstraction-0.8.0/deployments/ethereum/.chainId b/dependencies/eth-infinitism-account-abstraction-0.9.0/deployments/ethereum/.chainId similarity index 100% rename from dependencies/eth-infinitism-account-abstraction-0.8.0/deployments/ethereum/.chainId rename to dependencies/eth-infinitism-account-abstraction-0.9.0/deployments/ethereum/.chainId diff --git a/dependencies/eth-infinitism-account-abstraction-0.8.0/deployments/ethereum/EntryPoint.json b/dependencies/eth-infinitism-account-abstraction-0.9.0/deployments/ethereum/EntryPoint.json similarity index 100% rename from dependencies/eth-infinitism-account-abstraction-0.8.0/deployments/ethereum/EntryPoint.json rename to dependencies/eth-infinitism-account-abstraction-0.9.0/deployments/ethereum/EntryPoint.json diff --git a/dependencies/eth-infinitism-account-abstraction-0.9.0/deployments/ethereum/Simple7702Account.json b/dependencies/eth-infinitism-account-abstraction-0.9.0/deployments/ethereum/Simple7702Account.json new file mode 100644 index 0000000..584fe60 --- /dev/null +++ b/dependencies/eth-infinitism-account-abstraction-0.9.0/deployments/ethereum/Simple7702Account.json @@ -0,0 +1,458 @@ +{ + "address": "0x4Cd241E8d1510e30b2076397afc7508Ae59C66c9", + "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": "uint256", + "name": "index", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "error", + "type": "bytes" + } + ], + "name": "ExecuteError", + "type": "error" + }, + { + "stateMutability": "payable", + "type": "fallback" + }, + { + "inputs": [], + "name": "entryPoint", + "outputs": [ + { + "internalType": "contract IEntryPoint", + "name": "", + "type": "address" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "target", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "execute", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "address", + "name": "target", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "internalType": "struct BaseAccount.Call[]", + "name": "calls", + "type": "tuple[]" + } + ], + "name": "executeBatch", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "getNonce", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "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": "magicValue", + "type": "bytes4" + } + ], + "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": "bytes4", + "name": "id", + "type": "bytes4" + } + ], + "name": "supportsInterface", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "pure", + "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": "validationData", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "stateMutability": "payable", + "type": "receive" + } + ], + "transactionHash": "0x1efb9325969e404763015f96c6b86e8d5c6ba2c3fa92ef72ce663e786a18c8df", + "receipt": { + "to": "0x4e59b44847b379578588920cA78FbF26c0B4956C", + "from": "0x81ead4918134AE386dbd04346216E20AB8F822C4", + "contractAddress": null, + "transactionIndex": 90, + "gasUsed": "834744", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0xb5b953a7f27d7126f73e1d52dbb54defdf279d06a932fb60a43fc2731d37755e", + "transactionHash": "0x1efb9325969e404763015f96c6b86e8d5c6ba2c3fa92ef72ce663e786a18c8df", + "logs": [], + "blockNumber": 22123040, + "cumulativeGasUsed": "13844041", + "status": 1, + "byzantium": true + }, + "args": [], + "numDeployments": 1, + "solcInputHash": "cb85b40843950870cf56fe06c365e4cb", + "metadata": "{\"compiler\":{\"version\":\"0.8.28+commit.7893614a\"},\"language\":\"Solidity\",\"output\":{\"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\":\"uint256\",\"name\":\"index\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"error\",\"type\":\"bytes\"}],\"name\":\"ExecuteError\",\"type\":\"error\"},{\"stateMutability\":\"payable\",\"type\":\"fallback\"},{\"inputs\":[],\"name\":\"entryPoint\",\"outputs\":[{\"internalType\":\"contract IEntryPoint\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"target\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"execute\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"target\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"internalType\":\"struct BaseAccount.Call[]\",\"name\":\"calls\",\"type\":\"tuple[]\"}],\"name\":\"executeBatch\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getNonce\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"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\":\"magicValue\",\"type\":\"bytes4\"}],\"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\":\"bytes4\",\"name\":\"id\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"pure\",\"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\":\"validationData\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"stateMutability\":\"payable\",\"type\":\"receive\"}],\"devdoc\":{\"errors\":{\"ECDSAInvalidSignature()\":[{\"details\":\"The signature derives the `address(0)`.\"}],\"ECDSAInvalidSignatureLength(uint256)\":[{\"details\":\"The signature has an invalid length.\"}],\"ECDSAInvalidSignatureS(bytes32)\":[{\"details\":\"The signature has an S value that is in the upper half order.\"}]},\"kind\":\"dev\",\"methods\":{\"isValidSignature(bytes32,bytes)\":{\"details\":\"Should return whether the signature provided is valid for the provided data\",\"params\":{\"hash\":\"Hash of the data to be signed\",\"signature\":\"Signature byte array associated with _data\"}},\"onERC721Received(address,address,uint256,bytes)\":{\"details\":\"See {IERC721Receiver-onERC721Received}. Always returns `IERC721Receiver.onERC721Received.selector`.\"},\"validateUserOp((address,uint256,bytes,bytes,bytes32,uint256,bytes32,bytes,bytes),bytes32,uint256)\":{\"details\":\"Must validate caller is the entryPoint. Must validate the signature and nonce\",\"params\":{\"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.\",\"userOp\":\"- The operation that is about to be executed.\",\"userOpHash\":\"- Hash of the user's request data. can be used as the basis for signature.\"},\"returns\":{\"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.\"}}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"entryPoint()\":{\"notice\":\"Return the entryPoint used by this account. Subclass should return the current entryPoint used by this account.\"},\"execute(address,uint256,bytes)\":{\"notice\":\"execute a single call from the account.\"},\"executeBatch((address,uint256,bytes)[])\":{\"notice\":\"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.\"},\"getNonce()\":{\"notice\":\"Return the account nonce. This method returns the next sequential nonce. For a nonce of a specific key, use `entrypoint.getNonce(account, key)`\"},\"validateUserOp((address,uint256,bytes,bytes,bytes32,uint256,bytes32,bytes,bytes),bytes32,uint256)\":{\"notice\":\"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.\"}},\"notice\":\"Simple7702Account.sol A minimal account to be used with EIP-7702 (for batching) and ERC-4337 (for gas sponsoring)\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/accounts/Simple7702Account.sol\":\"Simple7702Account\"},\"evmVersion\":\"cancun\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":1000000},\"remappings\":[],\"viaIR\":true},\"sources\":{\"@openzeppelin/contracts/interfaces/IERC1271.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.1.0) (interfaces/IERC1271.sol)\\n\\npragma solidity ^0.8.20;\\n\\n/**\\n * @dev Interface of the ERC-1271 standard signature validation method for\\n * contracts as defined in https://eips.ethereum.org/EIPS/eip-1271[ERC-1271].\\n */\\ninterface IERC1271 {\\n /**\\n * @dev Should return whether the signature provided is valid for the provided data\\n * @param hash Hash of the data to be signed\\n * @param signature Signature byte array associated with _data\\n */\\n function isValidSignature(bytes32 hash, bytes memory signature) external view returns (bytes4 magicValue);\\n}\\n\",\"keccak256\":\"0x4aaaf1c0737dd16e81f0d2b9833c549747a5ede6873bf1444bc72aa572d03e98\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC1155/IERC1155Receiver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.1.0) (token/ERC1155/IERC1155Receiver.sol)\\n\\npragma solidity ^0.8.20;\\n\\nimport {IERC165} from \\\"../../utils/introspection/IERC165.sol\\\";\\n\\n/**\\n * @dev Interface that must be implemented by smart contracts in order to receive\\n * ERC-1155 token transfers.\\n */\\ninterface IERC1155Receiver is IERC165 {\\n /**\\n * @dev Handles the receipt of a single ERC-1155 token type. This function is\\n * called at the end of a `safeTransferFrom` after the balance has been updated.\\n *\\n * NOTE: To accept the transfer, this must return\\n * `bytes4(keccak256(\\\"onERC1155Received(address,address,uint256,uint256,bytes)\\\"))`\\n * (i.e. 0xf23a6e61, or its own function selector).\\n *\\n * @param operator The address which initiated the transfer (i.e. msg.sender)\\n * @param from The address which previously owned the token\\n * @param id The ID of the token being transferred\\n * @param value The amount of tokens being transferred\\n * @param data Additional data with no specified format\\n * @return `bytes4(keccak256(\\\"onERC1155Received(address,address,uint256,uint256,bytes)\\\"))` if transfer is allowed\\n */\\n function onERC1155Received(\\n address operator,\\n address from,\\n uint256 id,\\n uint256 value,\\n bytes calldata data\\n ) external returns (bytes4);\\n\\n /**\\n * @dev Handles the receipt of a multiple ERC-1155 token types. This function\\n * is called at the end of a `safeBatchTransferFrom` after the balances have\\n * been updated.\\n *\\n * NOTE: To accept the transfer(s), this must return\\n * `bytes4(keccak256(\\\"onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)\\\"))`\\n * (i.e. 0xbc197c81, or its own function selector).\\n *\\n * @param operator The address which initiated the batch transfer (i.e. msg.sender)\\n * @param from The address which previously owned the token\\n * @param ids An array containing ids of each token being transferred (order and length must match values array)\\n * @param values An array containing amounts of each token being transferred (order and length must match ids array)\\n * @param data Additional data with no specified format\\n * @return `bytes4(keccak256(\\\"onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)\\\"))` if transfer is allowed\\n */\\n function onERC1155BatchReceived(\\n address operator,\\n address from,\\n uint256[] calldata ids,\\n uint256[] calldata values,\\n bytes calldata data\\n ) external returns (bytes4);\\n}\\n\",\"keccak256\":\"0x61a23d601c2ab69dd726ac55058604cbda98e1d728ba31a51c379a3f9eeea715\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC1155/utils/ERC1155Holder.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.1.0) (token/ERC1155/utils/ERC1155Holder.sol)\\n\\npragma solidity ^0.8.20;\\n\\nimport {IERC165, ERC165} from \\\"../../../utils/introspection/ERC165.sol\\\";\\nimport {IERC1155Receiver} from \\\"../IERC1155Receiver.sol\\\";\\n\\n/**\\n * @dev Simple implementation of `IERC1155Receiver` that will allow a contract to hold ERC-1155 tokens.\\n *\\n * IMPORTANT: When inheriting this contract, you must include a way to use the received tokens, otherwise they will be\\n * stuck.\\n */\\nabstract contract ERC1155Holder is ERC165, IERC1155Receiver {\\n /**\\n * @dev See {IERC165-supportsInterface}.\\n */\\n function supportsInterface(bytes4 interfaceId) public view virtual override(ERC165, IERC165) returns (bool) {\\n return interfaceId == type(IERC1155Receiver).interfaceId || super.supportsInterface(interfaceId);\\n }\\n\\n function onERC1155Received(\\n address,\\n address,\\n uint256,\\n uint256,\\n bytes memory\\n ) public virtual override returns (bytes4) {\\n return this.onERC1155Received.selector;\\n }\\n\\n function onERC1155BatchReceived(\\n address,\\n address,\\n uint256[] memory,\\n uint256[] memory,\\n bytes memory\\n ) public virtual override returns (bytes4) {\\n return this.onERC1155BatchReceived.selector;\\n }\\n}\\n\",\"keccak256\":\"0xe103e95f854ef0cd1bba5f469175f67cd332f5c2561941f165e3dd65cee94d6d\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.1.0) (token/ERC721/IERC721Receiver.sol)\\n\\npragma solidity ^0.8.20;\\n\\n/**\\n * @title ERC-721 token receiver interface\\n * @dev Interface for any contract that wants to support safeTransfers\\n * from ERC-721 asset contracts.\\n */\\ninterface IERC721Receiver {\\n /**\\n * @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom}\\n * by `operator` from `from`, this function is called.\\n *\\n * It must return its Solidity selector to confirm the token transfer.\\n * If any other value is returned or the interface is not implemented by the recipient, the transfer will be\\n * reverted.\\n *\\n * The selector can be obtained in Solidity with `IERC721Receiver.onERC721Received.selector`.\\n */\\n function onERC721Received(\\n address operator,\\n address from,\\n uint256 tokenId,\\n bytes calldata data\\n ) external returns (bytes4);\\n}\\n\",\"keccak256\":\"0xb5afb8e8eebc4d1c6404df2f5e1e6d2c3d24fd01e5dfc855314951ecfaae462d\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC721/utils/ERC721Holder.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC721/utils/ERC721Holder.sol)\\n\\npragma solidity ^0.8.20;\\n\\nimport {IERC721Receiver} from \\\"../IERC721Receiver.sol\\\";\\n\\n/**\\n * @dev Implementation of the {IERC721Receiver} interface.\\n *\\n * Accepts all token transfers.\\n * Make sure the contract is able to use its token with {IERC721-safeTransferFrom}, {IERC721-approve} or\\n * {IERC721-setApprovalForAll}.\\n */\\nabstract contract ERC721Holder is IERC721Receiver {\\n /**\\n * @dev See {IERC721Receiver-onERC721Received}.\\n *\\n * Always returns `IERC721Receiver.onERC721Received.selector`.\\n */\\n function onERC721Received(address, address, uint256, bytes memory) public virtual returns (bytes4) {\\n return this.onERC721Received.selector;\\n }\\n}\\n\",\"keccak256\":\"0xaad20f8713b5cd98114278482d5d91b9758f9727048527d582e8e88fd4901fd8\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/cryptography/ECDSA.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.1.0) (utils/cryptography/ECDSA.sol)\\n\\npragma solidity ^0.8.20;\\n\\n/**\\n * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations.\\n *\\n * These functions can be used to verify that a message was signed by the holder\\n * of the private keys of a given address.\\n */\\nlibrary ECDSA {\\n enum RecoverError {\\n NoError,\\n InvalidSignature,\\n InvalidSignatureLength,\\n InvalidSignatureS\\n }\\n\\n /**\\n * @dev The signature derives the `address(0)`.\\n */\\n error ECDSAInvalidSignature();\\n\\n /**\\n * @dev The signature has an invalid length.\\n */\\n error ECDSAInvalidSignatureLength(uint256 length);\\n\\n /**\\n * @dev The signature has an S value that is in the upper half order.\\n */\\n error ECDSAInvalidSignatureS(bytes32 s);\\n\\n /**\\n * @dev Returns the address that signed a hashed message (`hash`) with `signature` or an error. This will not\\n * return address(0) without also returning an error description. Errors are documented using an enum (error type)\\n * and a bytes32 providing additional information about the error.\\n *\\n * If no error is returned, then the address can be used for verification purposes.\\n *\\n * The `ecrecover` EVM precompile allows for malleable (non-unique) signatures:\\n * this function rejects them by requiring the `s` value to be in the lower\\n * half order, and the `v` value to be either 27 or 28.\\n *\\n * IMPORTANT: `hash` _must_ be the result of a hash operation for the\\n * verification to be secure: it is possible to craft signatures that\\n * recover to arbitrary addresses for non-hashed data. A safe way to ensure\\n * this is by receiving a hash of the original message (which may otherwise\\n * be too long), and then calling {MessageHashUtils-toEthSignedMessageHash} on it.\\n *\\n * Documentation for signature generation:\\n * - with https://web3js.readthedocs.io/en/v1.3.4/web3-eth-accounts.html#sign[Web3.js]\\n * - with https://docs.ethers.io/v5/api/signer/#Signer-signMessage[ethers]\\n */\\n function tryRecover(\\n bytes32 hash,\\n bytes memory signature\\n ) internal pure returns (address recovered, RecoverError err, bytes32 errArg) {\\n if (signature.length == 65) {\\n bytes32 r;\\n bytes32 s;\\n uint8 v;\\n // ecrecover takes the signature parameters, and the only way to get them\\n // currently is to use assembly.\\n assembly (\\\"memory-safe\\\") {\\n r := mload(add(signature, 0x20))\\n s := mload(add(signature, 0x40))\\n v := byte(0, mload(add(signature, 0x60)))\\n }\\n return tryRecover(hash, v, r, s);\\n } else {\\n return (address(0), RecoverError.InvalidSignatureLength, bytes32(signature.length));\\n }\\n }\\n\\n /**\\n * @dev Returns the address that signed a hashed message (`hash`) with\\n * `signature`. This address can then be used for verification purposes.\\n *\\n * The `ecrecover` EVM precompile allows for malleable (non-unique) signatures:\\n * this function rejects them by requiring the `s` value to be in the lower\\n * half order, and the `v` value to be either 27 or 28.\\n *\\n * IMPORTANT: `hash` _must_ be the result of a hash operation for the\\n * verification to be secure: it is possible to craft signatures that\\n * recover to arbitrary addresses for non-hashed data. A safe way to ensure\\n * this is by receiving a hash of the original message (which may otherwise\\n * be too long), and then calling {MessageHashUtils-toEthSignedMessageHash} on it.\\n */\\n function recover(bytes32 hash, bytes memory signature) internal pure returns (address) {\\n (address recovered, RecoverError error, bytes32 errorArg) = tryRecover(hash, signature);\\n _throwError(error, errorArg);\\n return recovered;\\n }\\n\\n /**\\n * @dev Overload of {ECDSA-tryRecover} that receives the `r` and `vs` short-signature fields separately.\\n *\\n * See https://eips.ethereum.org/EIPS/eip-2098[ERC-2098 short signatures]\\n */\\n function tryRecover(\\n bytes32 hash,\\n bytes32 r,\\n bytes32 vs\\n ) internal pure returns (address recovered, RecoverError err, bytes32 errArg) {\\n unchecked {\\n bytes32 s = vs & bytes32(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff);\\n // We do not check for an overflow here since the shift operation results in 0 or 1.\\n uint8 v = uint8((uint256(vs) >> 255) + 27);\\n return tryRecover(hash, v, r, s);\\n }\\n }\\n\\n /**\\n * @dev Overload of {ECDSA-recover} that receives the `r and `vs` short-signature fields separately.\\n */\\n function recover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address) {\\n (address recovered, RecoverError error, bytes32 errorArg) = tryRecover(hash, r, vs);\\n _throwError(error, errorArg);\\n return recovered;\\n }\\n\\n /**\\n * @dev Overload of {ECDSA-tryRecover} that receives the `v`,\\n * `r` and `s` signature fields separately.\\n */\\n function tryRecover(\\n bytes32 hash,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) internal pure returns (address recovered, RecoverError err, bytes32 errArg) {\\n // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature\\n // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines\\n // the valid range for s in (301): 0 < s < secp256k1n \\u00f7 2 + 1, and for v in (302): v \\u2208 {27, 28}. Most\\n // signatures from current libraries generate a unique signature with an s-value in the lower half order.\\n //\\n // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value\\n // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or\\n // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept\\n // these malleable signatures as well.\\n if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) {\\n return (address(0), RecoverError.InvalidSignatureS, s);\\n }\\n\\n // If the signature is valid (and not malleable), return the signer address\\n address signer = ecrecover(hash, v, r, s);\\n if (signer == address(0)) {\\n return (address(0), RecoverError.InvalidSignature, bytes32(0));\\n }\\n\\n return (signer, RecoverError.NoError, bytes32(0));\\n }\\n\\n /**\\n * @dev Overload of {ECDSA-recover} that receives the `v`,\\n * `r` and `s` signature fields separately.\\n */\\n function recover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address) {\\n (address recovered, RecoverError error, bytes32 errorArg) = tryRecover(hash, v, r, s);\\n _throwError(error, errorArg);\\n return recovered;\\n }\\n\\n /**\\n * @dev Optionally reverts with the corresponding custom error according to the `error` argument provided.\\n */\\n function _throwError(RecoverError error, bytes32 errorArg) private pure {\\n if (error == RecoverError.NoError) {\\n return; // no error: do nothing\\n } else if (error == RecoverError.InvalidSignature) {\\n revert ECDSAInvalidSignature();\\n } else if (error == RecoverError.InvalidSignatureLength) {\\n revert ECDSAInvalidSignatureLength(uint256(errorArg));\\n } else if (error == RecoverError.InvalidSignatureS) {\\n revert ECDSAInvalidSignatureS(errorArg);\\n }\\n }\\n}\\n\",\"keccak256\":\"0x69f54c02b7d81d505910ec198c11ed4c6a728418a868b906b4a0cf29946fda84\",\"license\":\"MIT\"},\"@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\",\"keccak256\":\"0xddce8e17e3d3f9ed818b4f4c4478a8262aab8b11ed322f1bf5ed705bb4bd97fa\",\"license\":\"MIT\"},\"@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\",\"keccak256\":\"0x79796192ec90263f21b464d5bc90b777a525971d3de8232be80d9c4f9fb353b8\",\"license\":\"MIT\"},\"contracts/accounts/Simple7702Account.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.28;\\n\\nimport \\\"@openzeppelin/contracts/utils/introspection/IERC165.sol\\\";\\nimport \\\"@openzeppelin/contracts/interfaces/IERC1271.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC1155/utils/ERC1155Holder.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC721/utils/ERC721Holder.sol\\\";\\nimport \\\"@openzeppelin/contracts/utils/cryptography/ECDSA.sol\\\";\\nimport \\\"../core/Helpers.sol\\\";\\nimport \\\"../core/BaseAccount.sol\\\";\\n\\n/**\\n * Simple7702Account.sol\\n * A minimal account to be used with EIP-7702 (for batching) and ERC-4337 (for gas sponsoring)\\n */\\ncontract Simple7702Account is BaseAccount, IERC165, IERC1271, ERC1155Holder, ERC721Holder {\\n\\n // address of entryPoint v0.8\\n function entryPoint() public pure override returns (IEntryPoint) {\\n return IEntryPoint(0x4337084D9E255Ff0702461CF8895CE9E3b5Ff108);\\n }\\n\\n /**\\n * Make this account callable through ERC-4337 EntryPoint.\\n * The UserOperation should be signed by this account's private key.\\n */\\n function _validateSignature(\\n PackedUserOperation calldata userOp,\\n bytes32 userOpHash\\n ) internal virtual override returns (uint256 validationData) {\\n\\n return _checkSignature(userOpHash, userOp.signature) ? SIG_VALIDATION_SUCCESS : SIG_VALIDATION_FAILED;\\n }\\n\\n function isValidSignature(bytes32 hash, bytes memory signature) public view returns (bytes4 magicValue) {\\n return _checkSignature(hash, signature) ? this.isValidSignature.selector : bytes4(0xffffffff);\\n }\\n\\n function _checkSignature(bytes32 hash, bytes memory signature) internal view returns (bool) {\\n return ECDSA.recover(hash, signature) == address(this);\\n }\\n\\n function _requireForExecute() internal view virtual override {\\n require(\\n msg.sender == address(this) ||\\n msg.sender == address(entryPoint()),\\n \\\"not from self or EntryPoint\\\"\\n );\\n }\\n\\n function supportsInterface(bytes4 id) public override(ERC1155Holder, IERC165) pure returns (bool) {\\n return\\n id == type(IERC165).interfaceId ||\\n id == type(IAccount).interfaceId ||\\n id == type(IERC1271).interfaceId ||\\n id == type(IERC1155Receiver).interfaceId ||\\n id == type(IERC721Receiver).interfaceId;\\n }\\n\\n // accept incoming calls (with or without value), to mimic an EOA.\\n fallback() external payable {\\n }\\n\\n receive() external payable {\\n }\\n}\\n\",\"keccak256\":\"0x565e1434a6befd9d0bfe6ed53685f159bb416d8d226f368584541ecaea05745e\",\"license\":\"MIT\"},\"contracts/core/BaseAccount.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.28;\\n\\n/* solhint-disable avoid-low-level-calls */\\n/* solhint-disable no-empty-blocks */\\n/* solhint-disable no-inline-assembly */\\n\\nimport \\\"../interfaces/IAccount.sol\\\";\\nimport \\\"../interfaces/IEntryPoint.sol\\\";\\nimport \\\"../utils/Exec.sol\\\";\\nimport \\\"./UserOperationLib.sol\\\";\\n\\n/**\\n * Basic account implementation.\\n * This contract provides the basic logic for implementing the IAccount interface - validateUserOp\\n * Specific account implementation should inherit it and provide the account-specific logic.\\n */\\nabstract contract BaseAccount is IAccount {\\n using UserOperationLib for PackedUserOperation;\\n\\n struct Call {\\n address target;\\n uint256 value;\\n bytes data;\\n }\\n\\n error ExecuteError(uint256 index, bytes error);\\n\\n /**\\n * Return the account nonce.\\n * This method returns the next sequential nonce.\\n * For a nonce of a specific key, use `entrypoint.getNonce(account, key)`\\n */\\n function getNonce() public view virtual returns (uint256) {\\n return entryPoint().getNonce(address(this), 0);\\n }\\n\\n /**\\n * Return the entryPoint used by this account.\\n * Subclass should return the current entryPoint used by this account.\\n */\\n function entryPoint() public view virtual returns (IEntryPoint);\\n\\n /**\\n * execute a single call from the account.\\n */\\n function execute(address target, uint256 value, bytes calldata data) virtual external {\\n _requireForExecute();\\n\\n bool ok = Exec.call(target, value, data, gasleft());\\n if (!ok) {\\n Exec.revertWithReturnData();\\n }\\n }\\n\\n /**\\n * execute a batch of calls.\\n * revert on the first call that fails.\\n * If the batch reverts, and it contains more than a single call, then wrap the revert with ExecuteError,\\n * to mark the failing call index.\\n */\\n function executeBatch(Call[] calldata calls) virtual external {\\n _requireForExecute();\\n\\n uint256 callsLength = calls.length;\\n for (uint256 i = 0; i < callsLength; i++) {\\n Call calldata call = calls[i];\\n bool ok = Exec.call(call.target, call.value, call.data, gasleft());\\n if (!ok) {\\n if (callsLength == 1) {\\n Exec.revertWithReturnData();\\n } else {\\n revert ExecuteError(i, Exec.getReturnData(0));\\n }\\n }\\n }\\n }\\n\\n /// @inheritdoc IAccount\\n function validateUserOp(\\n PackedUserOperation calldata userOp,\\n bytes32 userOpHash,\\n uint256 missingAccountFunds\\n ) external virtual override returns (uint256 validationData) {\\n _requireFromEntryPoint();\\n validationData = _validateSignature(userOp, userOpHash);\\n _validateNonce(userOp.nonce);\\n _payPrefund(missingAccountFunds);\\n }\\n\\n /**\\n * Ensure the request comes from the known entrypoint.\\n */\\n function _requireFromEntryPoint() internal view virtual {\\n require(\\n msg.sender == address(entryPoint()),\\n \\\"account: not from EntryPoint\\\"\\n );\\n }\\n\\n function _requireForExecute() internal view virtual {\\n _requireFromEntryPoint();\\n }\\n\\n /**\\n * Validate the signature is valid for this message.\\n * @param userOp - Validate the userOp.signature field.\\n * @param userOpHash - Convenient field: the hash of the request, to check the signature against.\\n * (also hashes the entrypoint and chain id)\\n * @return validationData - Signature and time-range of this operation.\\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 the account doesn't use time-range, it is enough to return\\n * 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 _validateSignature(\\n PackedUserOperation calldata userOp,\\n bytes32 userOpHash\\n ) internal virtual returns (uint256 validationData);\\n\\n /**\\n * Validate the nonce of the UserOperation.\\n * This method may validate the nonce requirement of this account.\\n * e.g.\\n * To limit the nonce to use sequenced UserOps only (no \\\"out of order\\\" UserOps):\\n * `require(nonce < type(uint64).max)`\\n * For a hypothetical account that *requires* the nonce to be out-of-order:\\n * `require(nonce & type(uint64).max == 0)`\\n *\\n * The actual nonce uniqueness is managed by the EntryPoint, and thus no other\\n * action is needed by the account itself.\\n *\\n * @param nonce to validate\\n *\\n * solhint-disable-next-line no-empty-blocks\\n */\\n function _validateNonce(uint256 nonce) internal view virtual {\\n }\\n\\n /**\\n * Sends to the entrypoint (msg.sender) the missing funds for this transaction.\\n * SubClass MAY override this method for better funds management\\n * (e.g. send to the entryPoint more than the minimum required, so that in future transactions\\n * it will not be required to send again).\\n * @param missingAccountFunds - The minimum value this method should send the entrypoint.\\n * This value MAY be zero, in case there is enough deposit,\\n * or the userOp has a paymaster.\\n */\\n function _payPrefund(uint256 missingAccountFunds) internal virtual {\\n if (missingAccountFunds != 0) {\\n (bool success,) = payable(msg.sender).call{\\n value: missingAccountFunds\\n }(\\\"\\\");\\n (success);\\n // Ignore failure (its EntryPoint's job to verify, not account.)\\n }\\n }\\n}\\n\",\"keccak256\":\"0x071e38cf697bedbfe021955879277620ff763ecca1a1143ce14792e8c86c6d94\",\"license\":\"MIT\"},\"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\",\"keccak256\":\"0x42b948af5fa14a96149611595df1186800c7558b2de8762e4b45a7c45c16f65e\",\"license\":\"MIT\"},\"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\",\"keccak256\":\"0x2d3450fa3906422b6fdbbe7f2a2a9e36d6f3751bfa9cd80af88befd6a5be78c1\",\"license\":\"MIT\"},\"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\",\"keccak256\":\"0x1030b464b49ce80da46b5b6c9af357c2d526f308de61391db6a4ec767d33b864\",\"license\":\"MIT\"},\"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\",\"keccak256\":\"0xdf580eafa015b81bde436d6a5468cc92b531ada84007cef885e923f6dfc5e8bf\",\"license\":\"MIT\"},\"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\",\"keccak256\":\"0x3b0423737e810dd886183ed32cfed9b45edd315f5fb3e1076fc19f86791adc64\",\"license\":\"MIT\"},\"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\",\"keccak256\":\"0xee493ae200b8c675bdc0da66f7ac6bb883ecea33672d7d0a95526b9eecdedf87\",\"license\":\"MIT\"},\"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\",\"keccak256\":\"0x677f651d733162b80d1af7901e4f36469e362737a8353d1d0cc7bb94489e4ba4\",\"license\":\"MIT\"},\"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\",\"keccak256\":\"0xe48e904fcac02295aad07fbfa1c1d449a74bf44c04e432afef6f34d1ef726ae0\",\"license\":\"MIT\"},\"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\",\"keccak256\":\"0xb15188e25e45fe73097e279675b6c0beccbd4133ead2260f8f0c4ba840046800\",\"license\":\"MIT\"},\"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\",\"keccak256\":\"0x9c724ee22011193ea7f92d3c3c467ee6aa27139d3ddc225c7f1254d241e6ccdd\",\"license\":\"MIT\"}},\"version\":1}", + "bytecode": "0x60808060405234601557610e37908161001a8239f35b5f80fdfe6080806040526004361015610011575b005b5f3560e01c90816301ffc9a71461087057508063150b7a02146107e45780631626ba7e146106f557806319822f7c1461056557806334fcd5be146103b7578063b0d691fe1461036b578063b61d27f6146102b8578063bc197c81146101ea578063d087d288146101175763f23a6e611461008757005b346101135760a07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610113576100be6109bf565b506100c76109e2565b5060843567ffffffffffffffff8111610113576100e8903690600401610ae3565b5060206040517ff23a6e61000000000000000000000000000000000000000000000000000000008152f35b5f80fd5b34610113575f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610113576040517f35567e1a0000000000000000000000000000000000000000000000000000000081523060048201525f6024820152602081604481734337084d9e255ff0702461cf8895ce9e3b5ff1085afa80156101df575f906101ac575b602090604051908152f35b506020813d6020116101d7575b816101c660209383610a05565b8101031261011357602090516101a1565b3d91506101b9565b6040513d5f823e3d90fd5b346101135760a07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610113576102216109bf565b5061022a6109e2565b5060443567ffffffffffffffff81116101135761024b903690600401610b01565b5060643567ffffffffffffffff81116101135761026c903690600401610b01565b5060843567ffffffffffffffff81116101135761028d903690600401610ae3565b5060206040517fbc197c81000000000000000000000000000000000000000000000000000000008152f35b346101135760607ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610113576102ef6109bf565b60443567ffffffffffffffff8111610113573660238201121561011357806004013567ffffffffffffffff8111610113573660248284010111610113575f92610347849361033b610bba565b5a936024369201610aad565b916020835193019160243591f11561035b57005b610363610c46565b602081519101fd5b34610113575f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610113576020604051734337084d9e255ff0702461cf8895ce9e3b5ff1088152f35b346101135760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101135760043567ffffffffffffffff8111610113573660238201121561011357806004013567ffffffffffffffff8111610113573660248260051b840101116101135761042e610bba565b5f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7d83360301905b8281101561000f5760248160051b850101358281121561011357840160248101803573ffffffffffffffffffffffffffffffffffffffff8116810361011357826104b56104aa5f9594606487960190610b69565b91905a923691610aad565b92604460208551950193013591f1156104d057600101610456565b600183036104e057610363610c46565b60646104ea610c46565b917fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f60206040519586947f5a1546750000000000000000000000000000000000000000000000000000000086526004860152604060248601528051918291826044880152018686015e5f85828601015201168101030190fd5b346101135760607ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101135760043567ffffffffffffffff8111610113576101207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc823603011261011357604435734337084d9e255ff0702461cf8895ce9e3b5ff10833036106975761062661061d61061561060e856101046020970190600401610b69565b3691610aad565b602435610c60565b90929192610c9a565b73ffffffffffffffffffffffffffffffffffffffff16300361068f575f905b80610654575b50604051908152f35b5f80808093335af1503d1561068a573d61066d81610a73565b9061067b6040519283610a05565b81525f833d92013e5b8261064b565b610684565b600190610645565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601c60248201527f6163636f756e743a206e6f742066726f6d20456e747279506f696e74000000006044820152fd5b346101135760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101135760243567ffffffffffffffff81116101135761061d61074a610752923690600401610ae3565b600435610c60565b73ffffffffffffffffffffffffffffffffffffffff1630036107bc5760207f1626ba7e000000000000000000000000000000000000000000000000000000005b7fffffffff0000000000000000000000000000000000000000000000000000000060405191168152f35b60207fffffffff00000000000000000000000000000000000000000000000000000000610792565b346101135760807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101135761081b6109bf565b506108246109e2565b5060643567ffffffffffffffff811161011357610845903690600401610ae3565b5060206040517f150b7a02000000000000000000000000000000000000000000000000000000008152f35b346101135760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261011357600435907fffffffff00000000000000000000000000000000000000000000000000000000821680920361011357817f01ffc9a70000000000000000000000000000000000000000000000000000000060209314908115610995575b811561096b575b8115610941575b8115610917575b5015158152f35b7f150b7a020000000000000000000000000000000000000000000000000000000091501483610910565b7f4e2312e00000000000000000000000000000000000000000000000000000000081149150610909565b7f1626ba7e0000000000000000000000000000000000000000000000000000000081149150610902565b7f19822f7c00000000000000000000000000000000000000000000000000000000811491506108fb565b6004359073ffffffffffffffffffffffffffffffffffffffff8216820361011357565b6024359073ffffffffffffffffffffffffffffffffffffffff8216820361011357565b90601f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0910116810190811067ffffffffffffffff821117610a4657604052565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b67ffffffffffffffff8111610a4657601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200190565b929192610ab982610a73565b91610ac76040519384610a05565b829481845281830111610113578281602093845f960137010152565b9080601f8301121561011357816020610afe93359101610aad565b90565b9080601f830112156101135781359167ffffffffffffffff8311610a46578260051b9060405193610b356020840186610a05565b845260208085019282010192831161011357602001905b828210610b595750505090565b8135815260209182019101610b4c565b9035907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe181360301821215610113570180359067ffffffffffffffff82116101135760200191813603831361011357565b3033148015610c29575b15610bcb57565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601b60248201527f6e6f742066726f6d2073656c66206f7220456e747279506f696e7400000000006044820152fd5b50734337084d9e255ff0702461cf8895ce9e3b5ff1083314610bc4565b3d604051906020818301016040528082525f602083013e90565b8151919060418303610c9057610c899250602082015190606060408401519301515f1a90610d72565b9192909190565b50505f9160029190565b6004811015610d455780610cac575050565b60018103610cdc577ff645eedf000000000000000000000000000000000000000000000000000000005f5260045ffd5b60028103610d1057507ffce698f7000000000000000000000000000000000000000000000000000000005f5260045260245ffd5b600314610d1a5750565b7fd78bce0c000000000000000000000000000000000000000000000000000000005f5260045260245ffd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602160045260245ffd5b91907f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a08411610df6579160209360809260ff5f9560405194855216868401526040830152606082015282805260015afa156101df575f5173ffffffffffffffffffffffffffffffffffffffff811615610dec57905f905f90565b505f906001905f90565b5050505f916003919056fea2646970667358221220fe34a5691b8e36f81dd408d2f00c415ef4c0e37911899a8a46286019e63e38df64736f6c634300081c0033", + "deployedBytecode": "0x6080806040526004361015610011575b005b5f3560e01c90816301ffc9a71461087057508063150b7a02146107e45780631626ba7e146106f557806319822f7c1461056557806334fcd5be146103b7578063b0d691fe1461036b578063b61d27f6146102b8578063bc197c81146101ea578063d087d288146101175763f23a6e611461008757005b346101135760a07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610113576100be6109bf565b506100c76109e2565b5060843567ffffffffffffffff8111610113576100e8903690600401610ae3565b5060206040517ff23a6e61000000000000000000000000000000000000000000000000000000008152f35b5f80fd5b34610113575f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610113576040517f35567e1a0000000000000000000000000000000000000000000000000000000081523060048201525f6024820152602081604481734337084d9e255ff0702461cf8895ce9e3b5ff1085afa80156101df575f906101ac575b602090604051908152f35b506020813d6020116101d7575b816101c660209383610a05565b8101031261011357602090516101a1565b3d91506101b9565b6040513d5f823e3d90fd5b346101135760a07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610113576102216109bf565b5061022a6109e2565b5060443567ffffffffffffffff81116101135761024b903690600401610b01565b5060643567ffffffffffffffff81116101135761026c903690600401610b01565b5060843567ffffffffffffffff81116101135761028d903690600401610ae3565b5060206040517fbc197c81000000000000000000000000000000000000000000000000000000008152f35b346101135760607ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610113576102ef6109bf565b60443567ffffffffffffffff8111610113573660238201121561011357806004013567ffffffffffffffff8111610113573660248284010111610113575f92610347849361033b610bba565b5a936024369201610aad565b916020835193019160243591f11561035b57005b610363610c46565b602081519101fd5b34610113575f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610113576020604051734337084d9e255ff0702461cf8895ce9e3b5ff1088152f35b346101135760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101135760043567ffffffffffffffff8111610113573660238201121561011357806004013567ffffffffffffffff8111610113573660248260051b840101116101135761042e610bba565b5f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7d83360301905b8281101561000f5760248160051b850101358281121561011357840160248101803573ffffffffffffffffffffffffffffffffffffffff8116810361011357826104b56104aa5f9594606487960190610b69565b91905a923691610aad565b92604460208551950193013591f1156104d057600101610456565b600183036104e057610363610c46565b60646104ea610c46565b917fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f60206040519586947f5a1546750000000000000000000000000000000000000000000000000000000086526004860152604060248601528051918291826044880152018686015e5f85828601015201168101030190fd5b346101135760607ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101135760043567ffffffffffffffff8111610113576101207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc823603011261011357604435734337084d9e255ff0702461cf8895ce9e3b5ff10833036106975761062661061d61061561060e856101046020970190600401610b69565b3691610aad565b602435610c60565b90929192610c9a565b73ffffffffffffffffffffffffffffffffffffffff16300361068f575f905b80610654575b50604051908152f35b5f80808093335af1503d1561068a573d61066d81610a73565b9061067b6040519283610a05565b81525f833d92013e5b8261064b565b610684565b600190610645565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601c60248201527f6163636f756e743a206e6f742066726f6d20456e747279506f696e74000000006044820152fd5b346101135760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101135760243567ffffffffffffffff81116101135761061d61074a610752923690600401610ae3565b600435610c60565b73ffffffffffffffffffffffffffffffffffffffff1630036107bc5760207f1626ba7e000000000000000000000000000000000000000000000000000000005b7fffffffff0000000000000000000000000000000000000000000000000000000060405191168152f35b60207fffffffff00000000000000000000000000000000000000000000000000000000610792565b346101135760807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101135761081b6109bf565b506108246109e2565b5060643567ffffffffffffffff811161011357610845903690600401610ae3565b5060206040517f150b7a02000000000000000000000000000000000000000000000000000000008152f35b346101135760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261011357600435907fffffffff00000000000000000000000000000000000000000000000000000000821680920361011357817f01ffc9a70000000000000000000000000000000000000000000000000000000060209314908115610995575b811561096b575b8115610941575b8115610917575b5015158152f35b7f150b7a020000000000000000000000000000000000000000000000000000000091501483610910565b7f4e2312e00000000000000000000000000000000000000000000000000000000081149150610909565b7f1626ba7e0000000000000000000000000000000000000000000000000000000081149150610902565b7f19822f7c00000000000000000000000000000000000000000000000000000000811491506108fb565b6004359073ffffffffffffffffffffffffffffffffffffffff8216820361011357565b6024359073ffffffffffffffffffffffffffffffffffffffff8216820361011357565b90601f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0910116810190811067ffffffffffffffff821117610a4657604052565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b67ffffffffffffffff8111610a4657601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200190565b929192610ab982610a73565b91610ac76040519384610a05565b829481845281830111610113578281602093845f960137010152565b9080601f8301121561011357816020610afe93359101610aad565b90565b9080601f830112156101135781359167ffffffffffffffff8311610a46578260051b9060405193610b356020840186610a05565b845260208085019282010192831161011357602001905b828210610b595750505090565b8135815260209182019101610b4c565b9035907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe181360301821215610113570180359067ffffffffffffffff82116101135760200191813603831361011357565b3033148015610c29575b15610bcb57565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601b60248201527f6e6f742066726f6d2073656c66206f7220456e747279506f696e7400000000006044820152fd5b50734337084d9e255ff0702461cf8895ce9e3b5ff1083314610bc4565b3d604051906020818301016040528082525f602083013e90565b8151919060418303610c9057610c899250602082015190606060408401519301515f1a90610d72565b9192909190565b50505f9160029190565b6004811015610d455780610cac575050565b60018103610cdc577ff645eedf000000000000000000000000000000000000000000000000000000005f5260045ffd5b60028103610d1057507ffce698f7000000000000000000000000000000000000000000000000000000005f5260045260245ffd5b600314610d1a5750565b7fd78bce0c000000000000000000000000000000000000000000000000000000005f5260045260245ffd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602160045260245ffd5b91907f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a08411610df6579160209360809260ff5f9560405194855216868401526040830152606082015282805260015afa156101df575f5173ffffffffffffffffffffffffffffffffffffffff811615610dec57905f905f90565b505f906001905f90565b5050505f916003919056fea2646970667358221220fe34a5691b8e36f81dd408d2f00c415ef4c0e37911899a8a46286019e63e38df64736f6c634300081c0033", + "devdoc": { + "errors": { + "ECDSAInvalidSignature()": [ + { + "details": "The signature derives the `address(0)`." + } + ], + "ECDSAInvalidSignatureLength(uint256)": [ + { + "details": "The signature has an invalid length." + } + ], + "ECDSAInvalidSignatureS(bytes32)": [ + { + "details": "The signature has an S value that is in the upper half order." + } + ] + }, + "kind": "dev", + "methods": { + "isValidSignature(bytes32,bytes)": { + "details": "Should return whether the signature provided is valid for the provided data", + "params": { + "hash": "Hash of the data to be signed", + "signature": "Signature byte array associated with _data" + } + }, + "onERC721Received(address,address,uint256,bytes)": { + "details": "See {IERC721Receiver-onERC721Received}. Always returns `IERC721Receiver.onERC721Received.selector`." + }, + "validateUserOp((address,uint256,bytes,bytes,bytes32,uint256,bytes32,bytes,bytes),bytes32,uint256)": { + "details": "Must validate caller is the entryPoint. Must validate the signature and nonce", + "params": { + "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.", + "userOp": "- The operation that is about to be executed.", + "userOpHash": "- Hash of the user's request data. can be used as the basis for signature." + }, + "returns": { + "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." + } + } + }, + "version": 1 + }, + "userdoc": { + "kind": "user", + "methods": { + "entryPoint()": { + "notice": "Return the entryPoint used by this account. Subclass should return the current entryPoint used by this account." + }, + "execute(address,uint256,bytes)": { + "notice": "execute a single call from the account." + }, + "executeBatch((address,uint256,bytes)[])": { + "notice": "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." + }, + "getNonce()": { + "notice": "Return the account nonce. This method returns the next sequential nonce. For a nonce of a specific key, use `entrypoint.getNonce(account, key)`" + }, + "validateUserOp((address,uint256,bytes,bytes,bytes32,uint256,bytes32,bytes,bytes),bytes32,uint256)": { + "notice": "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." + } + }, + "notice": "Simple7702Account.sol A minimal account to be used with EIP-7702 (for batching) and ERC-4337 (for gas sponsoring)", + "version": 1 + }, + "storageLayout": { + "storage": [], + "types": null + } +} diff --git a/dependencies/eth-infinitism-account-abstraction-0.9.0/deployments/ethereum/SimpleAccountFactory.json b/dependencies/eth-infinitism-account-abstraction-0.9.0/deployments/ethereum/SimpleAccountFactory.json new file mode 100644 index 0000000..d72e0a3 --- /dev/null +++ b/dependencies/eth-infinitism-account-abstraction-0.9.0/deployments/ethereum/SimpleAccountFactory.json @@ -0,0 +1,120 @@ +{ + "address": "0x13E9ed32155810FDbd067D4522C492D6f68E5944", + "abi": [ + { + "inputs": [ + { + "internalType": "contract IEntryPoint", + "name": "_entryPoint", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [], + "name": "accountImplementation", + "outputs": [ + { + "internalType": "contract SimpleAccount", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "uint256", + "name": "salt", + "type": "uint256" + } + ], + "name": "createAccount", + "outputs": [ + { + "internalType": "contract SimpleAccount", + "name": "ret", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "uint256", + "name": "salt", + "type": "uint256" + } + ], + "name": "getAddress", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "senderCreator", + "outputs": [ + { + "internalType": "contract ISenderCreator", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + } + ], + "args": [ + "0x4337084D9E255Ff0702461CF8895CE9E3b5Ff108" + ], + "numDeployments": 1, + "solcInputHash": "f3ea4a3777acfe47e254273e0629af04", + "metadata": "{\"compiler\":{\"version\":\"0.8.28+commit.7893614a\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"contract IEntryPoint\",\"name\":\"_entryPoint\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"accountImplementation\",\"outputs\":[{\"internalType\":\"contract SimpleAccount\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"salt\",\"type\":\"uint256\"}],\"name\":\"createAccount\",\"outputs\":[{\"internalType\":\"contract SimpleAccount\",\"name\":\"ret\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"salt\",\"type\":\"uint256\"}],\"name\":\"getAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"senderCreator\",\"outputs\":[{\"internalType\":\"contract ISenderCreator\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"createAccount(address,uint256)\":{\"notice\":\"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\"},\"getAddress(address,uint256)\":{\"notice\":\"calculate the counterfactual address of this account as it would be returned by createAccount()\"}},\"notice\":\"A sample factory contract for SimpleAccount A UserOperations \\\"initCode\\\" holds the address of the factory, and a method call (to createAccount, in this sample factory). The factory's createAccount returns the target account address even if it is already installed. This way, the entryPoint.getSenderAddress() can be called either before or after the account is created.\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/accounts/SimpleAccountFactory.sol\":\"SimpleAccountFactory\"},\"evmVersion\":\"cancun\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":1000000},\"remappings\":[],\"viaIR\":true},\"sources\":{\"@openzeppelin/contracts/interfaces/IERC1967.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.0.0) (interfaces/IERC1967.sol)\\n\\npragma solidity ^0.8.20;\\n\\n/**\\n * @dev ERC-1967: Proxy Storage Slots. This interface contains the events defined in the ERC.\\n */\\ninterface IERC1967 {\\n /**\\n * @dev Emitted when the implementation is upgraded.\\n */\\n event Upgraded(address indexed implementation);\\n\\n /**\\n * @dev Emitted when the admin account has changed.\\n */\\n event AdminChanged(address previousAdmin, address newAdmin);\\n\\n /**\\n * @dev Emitted when the beacon is changed.\\n */\\n event BeaconUpgraded(address indexed beacon);\\n}\\n\",\"keccak256\":\"0xb25a4f11fa80c702bf5cd85adec90e6f6f507f32f4a8e6f5dbc31e8c10029486\",\"license\":\"MIT\"},\"@openzeppelin/contracts/interfaces/draft-IERC1822.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.1.0) (interfaces/draft-IERC1822.sol)\\n\\npragma solidity ^0.8.20;\\n\\n/**\\n * @dev ERC-1822: Universal Upgradeable Proxy Standard (UUPS) documents a method for upgradeability through a simplified\\n * proxy whose upgrades are fully controlled by the current implementation.\\n */\\ninterface IERC1822Proxiable {\\n /**\\n * @dev Returns the storage slot that the proxiable contract assumes is being used to store the implementation\\n * address.\\n *\\n * IMPORTANT: A proxy pointing at a proxiable contract should not be considered proxiable itself, because this risks\\n * bricking a proxy that upgrades to it, by delegating to itself until out of gas. Thus it is critical that this\\n * function revert if invoked through a proxy.\\n */\\n function proxiableUUID() external view returns (bytes32);\\n}\\n\",\"keccak256\":\"0xc42facb5094f2f35f066a7155bda23545e39a3156faef3ddc00185544443ba7d\",\"license\":\"MIT\"},\"@openzeppelin/contracts/proxy/ERC1967/ERC1967Proxy.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.1.0) (proxy/ERC1967/ERC1967Proxy.sol)\\n\\npragma solidity ^0.8.20;\\n\\nimport {Proxy} from \\\"../Proxy.sol\\\";\\nimport {ERC1967Utils} from \\\"./ERC1967Utils.sol\\\";\\n\\n/**\\n * @dev This contract implements an upgradeable proxy. It is upgradeable because calls are delegated to an\\n * implementation address that can be changed. This address is stored in storage in the location specified by\\n * https://eips.ethereum.org/EIPS/eip-1967[ERC-1967], so that it doesn't conflict with the storage layout of the\\n * implementation behind the proxy.\\n */\\ncontract ERC1967Proxy is Proxy {\\n /**\\n * @dev Initializes the upgradeable proxy with an initial implementation specified by `implementation`.\\n *\\n * If `_data` is nonempty, it's used as data in a delegate call to `implementation`. This will typically be an\\n * encoded function call, and allows initializing the storage of the proxy like a Solidity constructor.\\n *\\n * Requirements:\\n *\\n * - If `data` is empty, `msg.value` must be zero.\\n */\\n constructor(address implementation, bytes memory _data) payable {\\n ERC1967Utils.upgradeToAndCall(implementation, _data);\\n }\\n\\n /**\\n * @dev Returns the current implementation address.\\n *\\n * TIP: To get this value clients can read directly from the storage slot shown below (specified by ERC-1967) using\\n * the https://eth.wiki/json-rpc/API#eth_getstorageat[`eth_getStorageAt`] RPC call.\\n * `0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc`\\n */\\n function _implementation() internal view virtual override returns (address) {\\n return ERC1967Utils.getImplementation();\\n }\\n}\\n\",\"keccak256\":\"0x0a8a5b994d4c4da9f61d128945cc8c9e60dcbc72bf532f72ae42a48ea90eed9a\",\"license\":\"MIT\"},\"@openzeppelin/contracts/proxy/ERC1967/ERC1967Utils.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.1.0) (proxy/ERC1967/ERC1967Utils.sol)\\n\\npragma solidity ^0.8.21;\\n\\nimport {IBeacon} from \\\"../beacon/IBeacon.sol\\\";\\nimport {IERC1967} from \\\"../../interfaces/IERC1967.sol\\\";\\nimport {Address} from \\\"../../utils/Address.sol\\\";\\nimport {StorageSlot} from \\\"../../utils/StorageSlot.sol\\\";\\n\\n/**\\n * @dev This library provides getters and event emitting update functions for\\n * https://eips.ethereum.org/EIPS/eip-1967[ERC-1967] slots.\\n */\\nlibrary ERC1967Utils {\\n /**\\n * @dev Storage slot with the address of the current implementation.\\n * This is the keccak-256 hash of \\\"eip1967.proxy.implementation\\\" subtracted by 1.\\n */\\n // solhint-disable-next-line private-vars-leading-underscore\\n bytes32 internal constant IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;\\n\\n /**\\n * @dev The `implementation` of the proxy is invalid.\\n */\\n error ERC1967InvalidImplementation(address implementation);\\n\\n /**\\n * @dev The `admin` of the proxy is invalid.\\n */\\n error ERC1967InvalidAdmin(address admin);\\n\\n /**\\n * @dev The `beacon` of the proxy is invalid.\\n */\\n error ERC1967InvalidBeacon(address beacon);\\n\\n /**\\n * @dev An upgrade function sees `msg.value > 0` that may be lost.\\n */\\n error ERC1967NonPayable();\\n\\n /**\\n * @dev Returns the current implementation address.\\n */\\n function getImplementation() internal view returns (address) {\\n return StorageSlot.getAddressSlot(IMPLEMENTATION_SLOT).value;\\n }\\n\\n /**\\n * @dev Stores a new address in the ERC-1967 implementation slot.\\n */\\n function _setImplementation(address newImplementation) private {\\n if (newImplementation.code.length == 0) {\\n revert ERC1967InvalidImplementation(newImplementation);\\n }\\n StorageSlot.getAddressSlot(IMPLEMENTATION_SLOT).value = newImplementation;\\n }\\n\\n /**\\n * @dev Performs implementation upgrade with additional setup call if data is nonempty.\\n * This function is payable only if the setup call is performed, otherwise `msg.value` is rejected\\n * to avoid stuck value in the contract.\\n *\\n * Emits an {IERC1967-Upgraded} event.\\n */\\n function upgradeToAndCall(address newImplementation, bytes memory data) internal {\\n _setImplementation(newImplementation);\\n emit IERC1967.Upgraded(newImplementation);\\n\\n if (data.length > 0) {\\n Address.functionDelegateCall(newImplementation, data);\\n } else {\\n _checkNonPayable();\\n }\\n }\\n\\n /**\\n * @dev Storage slot with the admin of the contract.\\n * This is the keccak-256 hash of \\\"eip1967.proxy.admin\\\" subtracted by 1.\\n */\\n // solhint-disable-next-line private-vars-leading-underscore\\n bytes32 internal constant ADMIN_SLOT = 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103;\\n\\n /**\\n * @dev Returns the current admin.\\n *\\n * TIP: To get this value clients can read directly from the storage slot shown below (specified by ERC-1967) using\\n * the https://eth.wiki/json-rpc/API#eth_getstorageat[`eth_getStorageAt`] RPC call.\\n * `0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103`\\n */\\n function getAdmin() internal view returns (address) {\\n return StorageSlot.getAddressSlot(ADMIN_SLOT).value;\\n }\\n\\n /**\\n * @dev Stores a new address in the ERC-1967 admin slot.\\n */\\n function _setAdmin(address newAdmin) private {\\n if (newAdmin == address(0)) {\\n revert ERC1967InvalidAdmin(address(0));\\n }\\n StorageSlot.getAddressSlot(ADMIN_SLOT).value = newAdmin;\\n }\\n\\n /**\\n * @dev Changes the admin of the proxy.\\n *\\n * Emits an {IERC1967-AdminChanged} event.\\n */\\n function changeAdmin(address newAdmin) internal {\\n emit IERC1967.AdminChanged(getAdmin(), newAdmin);\\n _setAdmin(newAdmin);\\n }\\n\\n /**\\n * @dev The storage slot of the UpgradeableBeacon contract which defines the implementation for this proxy.\\n * This is the keccak-256 hash of \\\"eip1967.proxy.beacon\\\" subtracted by 1.\\n */\\n // solhint-disable-next-line private-vars-leading-underscore\\n bytes32 internal constant BEACON_SLOT = 0xa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d50;\\n\\n /**\\n * @dev Returns the current beacon.\\n */\\n function getBeacon() internal view returns (address) {\\n return StorageSlot.getAddressSlot(BEACON_SLOT).value;\\n }\\n\\n /**\\n * @dev Stores a new beacon in the ERC-1967 beacon slot.\\n */\\n function _setBeacon(address newBeacon) private {\\n if (newBeacon.code.length == 0) {\\n revert ERC1967InvalidBeacon(newBeacon);\\n }\\n\\n StorageSlot.getAddressSlot(BEACON_SLOT).value = newBeacon;\\n\\n address beaconImplementation = IBeacon(newBeacon).implementation();\\n if (beaconImplementation.code.length == 0) {\\n revert ERC1967InvalidImplementation(beaconImplementation);\\n }\\n }\\n\\n /**\\n * @dev Change the beacon and trigger a setup call if data is nonempty.\\n * This function is payable only if the setup call is performed, otherwise `msg.value` is rejected\\n * to avoid stuck value in the contract.\\n *\\n * Emits an {IERC1967-BeaconUpgraded} event.\\n *\\n * CAUTION: Invoking this function has no effect on an instance of {BeaconProxy} since v5, since\\n * it uses an immutable beacon without looking at the value of the ERC-1967 beacon slot for\\n * efficiency.\\n */\\n function upgradeBeaconToAndCall(address newBeacon, bytes memory data) internal {\\n _setBeacon(newBeacon);\\n emit IERC1967.BeaconUpgraded(newBeacon);\\n\\n if (data.length > 0) {\\n Address.functionDelegateCall(IBeacon(newBeacon).implementation(), data);\\n } else {\\n _checkNonPayable();\\n }\\n }\\n\\n /**\\n * @dev Reverts if `msg.value` is not zero. It can be used to avoid `msg.value` stuck in the contract\\n * if an upgrade doesn't perform an initialization call.\\n */\\n function _checkNonPayable() private {\\n if (msg.value > 0) {\\n revert ERC1967NonPayable();\\n }\\n }\\n}\\n\",\"keccak256\":\"0x911c3346ee26afe188f3b9dc267ef62a7ccf940aba1afa963e3922f0ca3d8a06\",\"license\":\"MIT\"},\"@openzeppelin/contracts/proxy/Proxy.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.0.0) (proxy/Proxy.sol)\\n\\npragma solidity ^0.8.20;\\n\\n/**\\n * @dev This abstract contract provides a fallback function that delegates all calls to another contract using the EVM\\n * instruction `delegatecall`. We refer to the second contract as the _implementation_ behind the proxy, and it has to\\n * be specified by overriding the virtual {_implementation} function.\\n *\\n * Additionally, delegation to the implementation can be triggered manually through the {_fallback} function, or to a\\n * different contract through the {_delegate} function.\\n *\\n * The success and return data of the delegated call will be returned back to the caller of the proxy.\\n */\\nabstract contract Proxy {\\n /**\\n * @dev Delegates the current call to `implementation`.\\n *\\n * This function does not return to its internal call site, it will return directly to the external caller.\\n */\\n function _delegate(address implementation) internal virtual {\\n assembly {\\n // Copy msg.data. We take full control of memory in this inline assembly\\n // block because it will not return to Solidity code. We overwrite the\\n // Solidity scratch pad at memory position 0.\\n calldatacopy(0, 0, calldatasize())\\n\\n // Call the implementation.\\n // out and outsize are 0 because we don't know the size yet.\\n let result := delegatecall(gas(), implementation, 0, calldatasize(), 0, 0)\\n\\n // Copy the returned data.\\n returndatacopy(0, 0, returndatasize())\\n\\n switch result\\n // delegatecall returns 0 on error.\\n case 0 {\\n revert(0, returndatasize())\\n }\\n default {\\n return(0, returndatasize())\\n }\\n }\\n }\\n\\n /**\\n * @dev This is a virtual function that should be overridden so it returns the address to which the fallback\\n * function and {_fallback} should delegate.\\n */\\n function _implementation() internal view virtual returns (address);\\n\\n /**\\n * @dev Delegates the current call to the address returned by `_implementation()`.\\n *\\n * This function does not return to its internal call site, it will return directly to the external caller.\\n */\\n function _fallback() internal virtual {\\n _delegate(_implementation());\\n }\\n\\n /**\\n * @dev Fallback function that delegates calls to the address returned by `_implementation()`. Will run if no other\\n * function in the contract matches the call data.\\n */\\n fallback() external payable virtual {\\n _fallback();\\n }\\n}\\n\",\"keccak256\":\"0xc3f2ec76a3de8ed7a7007c46166f5550c72c7709e3fc7e8bb3111a7191cdedbd\",\"license\":\"MIT\"},\"@openzeppelin/contracts/proxy/beacon/IBeacon.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.0.0) (proxy/beacon/IBeacon.sol)\\n\\npragma solidity ^0.8.20;\\n\\n/**\\n * @dev This is the interface that {BeaconProxy} expects of its beacon.\\n */\\ninterface IBeacon {\\n /**\\n * @dev Must return an address that can be used as a delegate call target.\\n *\\n * {UpgradeableBeacon} will check that this address is a contract.\\n */\\n function implementation() external view returns (address);\\n}\\n\",\"keccak256\":\"0xc59a78b07b44b2cf2e8ab4175fca91e8eca1eee2df7357b8d2a8833e5ea1f64c\",\"license\":\"MIT\"},\"@openzeppelin/contracts/proxy/utils/Initializable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.0.0) (proxy/utils/Initializable.sol)\\n\\npragma solidity ^0.8.20;\\n\\n/**\\n * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed\\n * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an\\n * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer\\n * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.\\n *\\n * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be\\n * reused. This mechanism prevents re-execution of each \\\"step\\\" but allows the creation of new initialization steps in\\n * case an upgrade adds a module that needs to be initialized.\\n *\\n * For example:\\n *\\n * [.hljs-theme-light.nopadding]\\n * ```solidity\\n * contract MyToken is ERC20Upgradeable {\\n * function initialize() initializer public {\\n * __ERC20_init(\\\"MyToken\\\", \\\"MTK\\\");\\n * }\\n * }\\n *\\n * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable {\\n * function initializeV2() reinitializer(2) public {\\n * __ERC20Permit_init(\\\"MyToken\\\");\\n * }\\n * }\\n * ```\\n *\\n * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as\\n * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}.\\n *\\n * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure\\n * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.\\n *\\n * [CAUTION]\\n * ====\\n * Avoid leaving a contract uninitialized.\\n *\\n * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation\\n * contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke\\n * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed:\\n *\\n * [.hljs-theme-light.nopadding]\\n * ```\\n * /// @custom:oz-upgrades-unsafe-allow constructor\\n * constructor() {\\n * _disableInitializers();\\n * }\\n * ```\\n * ====\\n */\\nabstract contract Initializable {\\n /**\\n * @dev Storage of the initializable contract.\\n *\\n * It's implemented on a custom ERC-7201 namespace to reduce the risk of storage collisions\\n * when using with upgradeable contracts.\\n *\\n * @custom:storage-location erc7201:openzeppelin.storage.Initializable\\n */\\n struct InitializableStorage {\\n /**\\n * @dev Indicates that the contract has been initialized.\\n */\\n uint64 _initialized;\\n /**\\n * @dev Indicates that the contract is in the process of being initialized.\\n */\\n bool _initializing;\\n }\\n\\n // keccak256(abi.encode(uint256(keccak256(\\\"openzeppelin.storage.Initializable\\\")) - 1)) & ~bytes32(uint256(0xff))\\n bytes32 private constant INITIALIZABLE_STORAGE = 0xf0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00;\\n\\n /**\\n * @dev The contract is already initialized.\\n */\\n error InvalidInitialization();\\n\\n /**\\n * @dev The contract is not initializing.\\n */\\n error NotInitializing();\\n\\n /**\\n * @dev Triggered when the contract has been initialized or reinitialized.\\n */\\n event Initialized(uint64 version);\\n\\n /**\\n * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope,\\n * `onlyInitializing` functions can be used to initialize parent contracts.\\n *\\n * Similar to `reinitializer(1)`, except that in the context of a constructor an `initializer` may be invoked any\\n * number of times. This behavior in the constructor can be useful during testing and is not expected to be used in\\n * production.\\n *\\n * Emits an {Initialized} event.\\n */\\n modifier initializer() {\\n // solhint-disable-next-line var-name-mixedcase\\n InitializableStorage storage $ = _getInitializableStorage();\\n\\n // Cache values to avoid duplicated sloads\\n bool isTopLevelCall = !$._initializing;\\n uint64 initialized = $._initialized;\\n\\n // Allowed calls:\\n // - initialSetup: the contract is not in the initializing state and no previous version was\\n // initialized\\n // - construction: the contract is initialized at version 1 (no reininitialization) and the\\n // current contract is just being deployed\\n bool initialSetup = initialized == 0 && isTopLevelCall;\\n bool construction = initialized == 1 && address(this).code.length == 0;\\n\\n if (!initialSetup && !construction) {\\n revert InvalidInitialization();\\n }\\n $._initialized = 1;\\n if (isTopLevelCall) {\\n $._initializing = true;\\n }\\n _;\\n if (isTopLevelCall) {\\n $._initializing = false;\\n emit Initialized(1);\\n }\\n }\\n\\n /**\\n * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the\\n * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be\\n * used to initialize parent contracts.\\n *\\n * A reinitializer may be used after the original initialization step. This is essential to configure modules that\\n * are added through upgrades and that require initialization.\\n *\\n * When `version` is 1, this modifier is similar to `initializer`, except that functions marked with `reinitializer`\\n * cannot be nested. If one is invoked in the context of another, execution will revert.\\n *\\n * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in\\n * a contract, executing them in the right order is up to the developer or operator.\\n *\\n * WARNING: Setting the version to 2**64 - 1 will prevent any future reinitialization.\\n *\\n * Emits an {Initialized} event.\\n */\\n modifier reinitializer(uint64 version) {\\n // solhint-disable-next-line var-name-mixedcase\\n InitializableStorage storage $ = _getInitializableStorage();\\n\\n if ($._initializing || $._initialized >= version) {\\n revert InvalidInitialization();\\n }\\n $._initialized = version;\\n $._initializing = true;\\n _;\\n $._initializing = false;\\n emit Initialized(version);\\n }\\n\\n /**\\n * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the\\n * {initializer} and {reinitializer} modifiers, directly or indirectly.\\n */\\n modifier onlyInitializing() {\\n _checkInitializing();\\n _;\\n }\\n\\n /**\\n * @dev Reverts if the contract is not in an initializing state. See {onlyInitializing}.\\n */\\n function _checkInitializing() internal view virtual {\\n if (!_isInitializing()) {\\n revert NotInitializing();\\n }\\n }\\n\\n /**\\n * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call.\\n * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized\\n * to any version. It is recommended to use this to lock implementation contracts that are designed to be called\\n * through proxies.\\n *\\n * Emits an {Initialized} event the first time it is successfully executed.\\n */\\n function _disableInitializers() internal virtual {\\n // solhint-disable-next-line var-name-mixedcase\\n InitializableStorage storage $ = _getInitializableStorage();\\n\\n if ($._initializing) {\\n revert InvalidInitialization();\\n }\\n if ($._initialized != type(uint64).max) {\\n $._initialized = type(uint64).max;\\n emit Initialized(type(uint64).max);\\n }\\n }\\n\\n /**\\n * @dev Returns the highest version that has been initialized. See {reinitializer}.\\n */\\n function _getInitializedVersion() internal view returns (uint64) {\\n return _getInitializableStorage()._initialized;\\n }\\n\\n /**\\n * @dev Returns `true` if the contract is currently initializing. See {onlyInitializing}.\\n */\\n function _isInitializing() internal view returns (bool) {\\n return _getInitializableStorage()._initializing;\\n }\\n\\n /**\\n * @dev Returns a pointer to the storage namespace.\\n */\\n // solhint-disable-next-line var-name-mixedcase\\n function _getInitializableStorage() private pure returns (InitializableStorage storage $) {\\n assembly {\\n $.slot := INITIALIZABLE_STORAGE\\n }\\n }\\n}\\n\",\"keccak256\":\"0x631188737069917d2f909d29ce62c4d48611d326686ba6683e26b72a23bfac0b\",\"license\":\"MIT\"},\"@openzeppelin/contracts/proxy/utils/UUPSUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.1.0) (proxy/utils/UUPSUpgradeable.sol)\\n\\npragma solidity ^0.8.20;\\n\\nimport {IERC1822Proxiable} from \\\"../../interfaces/draft-IERC1822.sol\\\";\\nimport {ERC1967Utils} from \\\"../ERC1967/ERC1967Utils.sol\\\";\\n\\n/**\\n * @dev An upgradeability mechanism designed for UUPS proxies. The functions included here can perform an upgrade of an\\n * {ERC1967Proxy}, when this contract is set as the implementation behind such a proxy.\\n *\\n * A security mechanism ensures that an upgrade does not turn off upgradeability accidentally, although this risk is\\n * reinstated if the upgrade retains upgradeability but removes the security mechanism, e.g. by replacing\\n * `UUPSUpgradeable` with a custom implementation of upgrades.\\n *\\n * The {_authorizeUpgrade} function must be overridden to include access restriction to the upgrade mechanism.\\n */\\nabstract contract UUPSUpgradeable is IERC1822Proxiable {\\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\\n address private immutable __self = address(this);\\n\\n /**\\n * @dev The version of the upgrade interface of the contract. If this getter is missing, both `upgradeTo(address)`\\n * and `upgradeToAndCall(address,bytes)` are present, and `upgradeTo` must be used if no function should be called,\\n * while `upgradeToAndCall` will invoke the `receive` function if the second argument is the empty byte string.\\n * If the getter returns `\\\"5.0.0\\\"`, only `upgradeToAndCall(address,bytes)` is present, and the second argument must\\n * be the empty byte string if no function should be called, making it impossible to invoke the `receive` function\\n * during an upgrade.\\n */\\n string public constant UPGRADE_INTERFACE_VERSION = \\\"5.0.0\\\";\\n\\n /**\\n * @dev The call is from an unauthorized context.\\n */\\n error UUPSUnauthorizedCallContext();\\n\\n /**\\n * @dev The storage `slot` is unsupported as a UUID.\\n */\\n error UUPSUnsupportedProxiableUUID(bytes32 slot);\\n\\n /**\\n * @dev Check that the execution is being performed through a delegatecall call and that the execution context is\\n * a proxy contract with an implementation (as defined in ERC-1967) pointing to self. This should only be the case\\n * for UUPS and transparent proxies that are using the current contract as their implementation. Execution of a\\n * function through ERC-1167 minimal proxies (clones) would not normally pass this test, but is not guaranteed to\\n * fail.\\n */\\n modifier onlyProxy() {\\n _checkProxy();\\n _;\\n }\\n\\n /**\\n * @dev Check that the execution is not being performed through a delegate call. This allows a function to be\\n * callable on the implementing contract but not through proxies.\\n */\\n modifier notDelegated() {\\n _checkNotDelegated();\\n _;\\n }\\n\\n /**\\n * @dev Implementation of the ERC-1822 {proxiableUUID} function. This returns the storage slot used by the\\n * implementation. It is used to validate the implementation's compatibility when performing an upgrade.\\n *\\n * IMPORTANT: A proxy pointing at a proxiable contract should not be considered proxiable itself, because this risks\\n * bricking a proxy that upgrades to it, by delegating to itself until out of gas. Thus it is critical that this\\n * function revert if invoked through a proxy. This is guaranteed by the `notDelegated` modifier.\\n */\\n function proxiableUUID() external view virtual notDelegated returns (bytes32) {\\n return ERC1967Utils.IMPLEMENTATION_SLOT;\\n }\\n\\n /**\\n * @dev Upgrade the implementation of the proxy to `newImplementation`, and subsequently execute the function call\\n * encoded in `data`.\\n *\\n * Calls {_authorizeUpgrade}.\\n *\\n * Emits an {Upgraded} event.\\n *\\n * @custom:oz-upgrades-unsafe-allow-reachable delegatecall\\n */\\n function upgradeToAndCall(address newImplementation, bytes memory data) public payable virtual onlyProxy {\\n _authorizeUpgrade(newImplementation);\\n _upgradeToAndCallUUPS(newImplementation, data);\\n }\\n\\n /**\\n * @dev Reverts if the execution is not performed via delegatecall or the execution\\n * context is not of a proxy with an ERC-1967 compliant implementation pointing to self.\\n * See {_onlyProxy}.\\n */\\n function _checkProxy() internal view virtual {\\n if (\\n address(this) == __self || // Must be called through delegatecall\\n ERC1967Utils.getImplementation() != __self // Must be called through an active proxy\\n ) {\\n revert UUPSUnauthorizedCallContext();\\n }\\n }\\n\\n /**\\n * @dev Reverts if the execution is performed via delegatecall.\\n * See {notDelegated}.\\n */\\n function _checkNotDelegated() internal view virtual {\\n if (address(this) != __self) {\\n // Must not be called through delegatecall\\n revert UUPSUnauthorizedCallContext();\\n }\\n }\\n\\n /**\\n * @dev Function that should revert when `msg.sender` is not authorized to upgrade the contract. Called by\\n * {upgradeToAndCall}.\\n *\\n * Normally, this function will use an xref:access.adoc[access control] modifier such as {Ownable-onlyOwner}.\\n *\\n * ```solidity\\n * function _authorizeUpgrade(address) internal onlyOwner {}\\n * ```\\n */\\n function _authorizeUpgrade(address newImplementation) internal virtual;\\n\\n /**\\n * @dev Performs an implementation upgrade with a security check for UUPS proxies, and additional setup call.\\n *\\n * As a security check, {proxiableUUID} is invoked in the new implementation, and the return value\\n * is expected to be the implementation slot in ERC-1967.\\n *\\n * Emits an {IERC1967-Upgraded} event.\\n */\\n function _upgradeToAndCallUUPS(address newImplementation, bytes memory data) private {\\n try IERC1822Proxiable(newImplementation).proxiableUUID() returns (bytes32 slot) {\\n if (slot != ERC1967Utils.IMPLEMENTATION_SLOT) {\\n revert UUPSUnsupportedProxiableUUID(slot);\\n }\\n ERC1967Utils.upgradeToAndCall(newImplementation, data);\\n } catch {\\n // The implementation is not UUPS\\n revert ERC1967Utils.ERC1967InvalidImplementation(newImplementation);\\n }\\n }\\n}\\n\",\"keccak256\":\"0xb3f8fb5dc1c423373e346c4eccd6dc74ed858d70d58fb35cb721d1c56ca19bdf\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC1155/IERC1155Receiver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.1.0) (token/ERC1155/IERC1155Receiver.sol)\\n\\npragma solidity ^0.8.20;\\n\\nimport {IERC165} from \\\"../../utils/introspection/IERC165.sol\\\";\\n\\n/**\\n * @dev Interface that must be implemented by smart contracts in order to receive\\n * ERC-1155 token transfers.\\n */\\ninterface IERC1155Receiver is IERC165 {\\n /**\\n * @dev Handles the receipt of a single ERC-1155 token type. This function is\\n * called at the end of a `safeTransferFrom` after the balance has been updated.\\n *\\n * NOTE: To accept the transfer, this must return\\n * `bytes4(keccak256(\\\"onERC1155Received(address,address,uint256,uint256,bytes)\\\"))`\\n * (i.e. 0xf23a6e61, or its own function selector).\\n *\\n * @param operator The address which initiated the transfer (i.e. msg.sender)\\n * @param from The address which previously owned the token\\n * @param id The ID of the token being transferred\\n * @param value The amount of tokens being transferred\\n * @param data Additional data with no specified format\\n * @return `bytes4(keccak256(\\\"onERC1155Received(address,address,uint256,uint256,bytes)\\\"))` if transfer is allowed\\n */\\n function onERC1155Received(\\n address operator,\\n address from,\\n uint256 id,\\n uint256 value,\\n bytes calldata data\\n ) external returns (bytes4);\\n\\n /**\\n * @dev Handles the receipt of a multiple ERC-1155 token types. This function\\n * is called at the end of a `safeBatchTransferFrom` after the balances have\\n * been updated.\\n *\\n * NOTE: To accept the transfer(s), this must return\\n * `bytes4(keccak256(\\\"onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)\\\"))`\\n * (i.e. 0xbc197c81, or its own function selector).\\n *\\n * @param operator The address which initiated the batch transfer (i.e. msg.sender)\\n * @param from The address which previously owned the token\\n * @param ids An array containing ids of each token being transferred (order and length must match values array)\\n * @param values An array containing amounts of each token being transferred (order and length must match ids array)\\n * @param data Additional data with no specified format\\n * @return `bytes4(keccak256(\\\"onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)\\\"))` if transfer is allowed\\n */\\n function onERC1155BatchReceived(\\n address operator,\\n address from,\\n uint256[] calldata ids,\\n uint256[] calldata values,\\n bytes calldata data\\n ) external returns (bytes4);\\n}\\n\",\"keccak256\":\"0x61a23d601c2ab69dd726ac55058604cbda98e1d728ba31a51c379a3f9eeea715\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.1.0) (token/ERC721/IERC721Receiver.sol)\\n\\npragma solidity ^0.8.20;\\n\\n/**\\n * @title ERC-721 token receiver interface\\n * @dev Interface for any contract that wants to support safeTransfers\\n * from ERC-721 asset contracts.\\n */\\ninterface IERC721Receiver {\\n /**\\n * @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom}\\n * by `operator` from `from`, this function is called.\\n *\\n * It must return its Solidity selector to confirm the token transfer.\\n * If any other value is returned or the interface is not implemented by the recipient, the transfer will be\\n * reverted.\\n *\\n * The selector can be obtained in Solidity with `IERC721Receiver.onERC721Received.selector`.\\n */\\n function onERC721Received(\\n address operator,\\n address from,\\n uint256 tokenId,\\n bytes calldata data\\n ) external returns (bytes4);\\n}\\n\",\"keccak256\":\"0xb5afb8e8eebc4d1c6404df2f5e1e6d2c3d24fd01e5dfc855314951ecfaae462d\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Address.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.1.0) (utils/Address.sol)\\n\\npragma solidity ^0.8.20;\\n\\nimport {Errors} from \\\"./Errors.sol\\\";\\n\\n/**\\n * @dev Collection of functions related to the address type\\n */\\nlibrary Address {\\n /**\\n * @dev There's no code at `target` (it is not a contract).\\n */\\n error AddressEmptyCode(address target);\\n\\n /**\\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\\n * `recipient`, forwarding all available gas and reverting on errors.\\n *\\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\\n * imposed by `transfer`, making them unable to receive funds via\\n * `transfer`. {sendValue} removes this limitation.\\n *\\n * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].\\n *\\n * IMPORTANT: because control is transferred to `recipient`, care must be\\n * taken to not create reentrancy vulnerabilities. Consider using\\n * {ReentrancyGuard} or the\\n * https://solidity.readthedocs.io/en/v0.8.20/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\\n */\\n function sendValue(address payable recipient, uint256 amount) internal {\\n if (address(this).balance < amount) {\\n revert Errors.InsufficientBalance(address(this).balance, amount);\\n }\\n\\n (bool success, ) = recipient.call{value: amount}(\\\"\\\");\\n if (!success) {\\n revert Errors.FailedCall();\\n }\\n }\\n\\n /**\\n * @dev Performs a Solidity function call using a low level `call`. A\\n * plain `call` is an unsafe replacement for a function call: use this\\n * function instead.\\n *\\n * If `target` reverts with a revert reason or custom error, it is bubbled\\n * up by this function (like regular Solidity function calls). However, if\\n * the call reverted with no returned reason, this function reverts with a\\n * {Errors.FailedCall} error.\\n *\\n * Returns the raw returned data. To convert to the expected return value,\\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\\n *\\n * Requirements:\\n *\\n * - `target` must be a contract.\\n * - calling `target` with `data` must not revert.\\n */\\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but also transferring `value` wei to `target`.\\n *\\n * Requirements:\\n *\\n * - the calling contract must have an ETH balance of at least `value`.\\n * - the called Solidity function must be `payable`.\\n */\\n function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\\n if (address(this).balance < value) {\\n revert Errors.InsufficientBalance(address(this).balance, value);\\n }\\n (bool success, bytes memory returndata) = target.call{value: value}(data);\\n return verifyCallResultFromTarget(target, success, returndata);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a static call.\\n */\\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\\n (bool success, bytes memory returndata) = target.staticcall(data);\\n return verifyCallResultFromTarget(target, success, returndata);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a delegate call.\\n */\\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\\n (bool success, bytes memory returndata) = target.delegatecall(data);\\n return verifyCallResultFromTarget(target, success, returndata);\\n }\\n\\n /**\\n * @dev Tool to verify that a low level call to smart-contract was successful, and reverts if the target\\n * was not a contract or bubbling up the revert reason (falling back to {Errors.FailedCall}) in case\\n * of an unsuccessful call.\\n */\\n function verifyCallResultFromTarget(\\n address target,\\n bool success,\\n bytes memory returndata\\n ) internal view returns (bytes memory) {\\n if (!success) {\\n _revert(returndata);\\n } else {\\n // only check if target is a contract if the call was successful and the return data is empty\\n // otherwise we already know that it was a contract\\n if (returndata.length == 0 && target.code.length == 0) {\\n revert AddressEmptyCode(target);\\n }\\n return returndata;\\n }\\n }\\n\\n /**\\n * @dev Tool to verify that a low level call was successful, and reverts if it wasn't, either by bubbling the\\n * revert reason or with a default {Errors.FailedCall} error.\\n */\\n function verifyCallResult(bool success, bytes memory returndata) internal pure returns (bytes memory) {\\n if (!success) {\\n _revert(returndata);\\n } else {\\n return returndata;\\n }\\n }\\n\\n /**\\n * @dev Reverts with returndata if present. Otherwise reverts with {Errors.FailedCall}.\\n */\\n function _revert(bytes memory returndata) private pure {\\n // Look for revert reason and bubble it up if present\\n if (returndata.length > 0) {\\n // The easiest way to bubble the revert reason is using memory via assembly\\n assembly (\\\"memory-safe\\\") {\\n let returndata_size := mload(returndata)\\n revert(add(32, returndata), returndata_size)\\n }\\n } else {\\n revert Errors.FailedCall();\\n }\\n }\\n}\\n\",\"keccak256\":\"0x9d8da059267bac779a2dbbb9a26c2acf00ca83085e105d62d5d4ef96054a47f5\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Create2.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.1.0) (utils/Create2.sol)\\n\\npragma solidity ^0.8.20;\\n\\nimport {Errors} from \\\"./Errors.sol\\\";\\n\\n/**\\n * @dev Helper to make usage of the `CREATE2` EVM opcode easier and safer.\\n * `CREATE2` can be used to compute in advance the address where a smart\\n * contract will be deployed, which allows for interesting new mechanisms known\\n * as 'counterfactual interactions'.\\n *\\n * See the https://eips.ethereum.org/EIPS/eip-1014#motivation[EIP] for more\\n * information.\\n */\\nlibrary Create2 {\\n /**\\n * @dev There's no code to deploy.\\n */\\n error Create2EmptyBytecode();\\n\\n /**\\n * @dev Deploys a contract using `CREATE2`. The address where the contract\\n * will be deployed can be known in advance via {computeAddress}.\\n *\\n * The bytecode for a contract can be obtained from Solidity with\\n * `type(contractName).creationCode`.\\n *\\n * Requirements:\\n *\\n * - `bytecode` must not be empty.\\n * - `salt` must have not been used for `bytecode` already.\\n * - the factory must have a balance of at least `amount`.\\n * - if `amount` is non-zero, `bytecode` must have a `payable` constructor.\\n */\\n function deploy(uint256 amount, bytes32 salt, bytes memory bytecode) internal returns (address addr) {\\n if (address(this).balance < amount) {\\n revert Errors.InsufficientBalance(address(this).balance, amount);\\n }\\n if (bytecode.length == 0) {\\n revert Create2EmptyBytecode();\\n }\\n assembly (\\\"memory-safe\\\") {\\n addr := create2(amount, add(bytecode, 0x20), mload(bytecode), salt)\\n // if no address was created, and returndata is not empty, bubble revert\\n if and(iszero(addr), not(iszero(returndatasize()))) {\\n let p := mload(0x40)\\n returndatacopy(p, 0, returndatasize())\\n revert(p, returndatasize())\\n }\\n }\\n if (addr == address(0)) {\\n revert Errors.FailedDeployment();\\n }\\n }\\n\\n /**\\n * @dev Returns the address where a contract will be stored if deployed via {deploy}. Any change in the\\n * `bytecodeHash` or `salt` will result in a new destination address.\\n */\\n function computeAddress(bytes32 salt, bytes32 bytecodeHash) internal view returns (address) {\\n return computeAddress(salt, bytecodeHash, address(this));\\n }\\n\\n /**\\n * @dev Returns the address where a contract will be stored if deployed via {deploy} from a contract located at\\n * `deployer`. If `deployer` is this contract's address, returns the same value as {computeAddress}.\\n */\\n function computeAddress(bytes32 salt, bytes32 bytecodeHash, address deployer) internal pure returns (address addr) {\\n assembly (\\\"memory-safe\\\") {\\n let ptr := mload(0x40) // Get free memory pointer\\n\\n // | | \\u2193 ptr ... \\u2193 ptr + 0x0B (start) ... \\u2193 ptr + 0x20 ... \\u2193 ptr + 0x40 ... |\\n // |-------------------|---------------------------------------------------------------------------|\\n // | bytecodeHash | CCCCCCCCCCCCC...CC |\\n // | salt | BBBBBBBBBBBBB...BB |\\n // | deployer | 000000...0000AAAAAAAAAAAAAAAAAAA...AA |\\n // | 0xFF | FF |\\n // |-------------------|---------------------------------------------------------------------------|\\n // | memory | 000000...00FFAAAAAAAAAAAAAAAAAAA...AABBBBBBBBBBBBB...BBCCCCCCCCCCCCC...CC |\\n // | keccak(start, 85) | \\u2191\\u2191\\u2191\\u2191\\u2191\\u2191\\u2191\\u2191\\u2191\\u2191\\u2191\\u2191\\u2191\\u2191\\u2191\\u2191\\u2191\\u2191\\u2191\\u2191\\u2191\\u2191\\u2191\\u2191\\u2191\\u2191\\u2191\\u2191\\u2191\\u2191\\u2191\\u2191\\u2191\\u2191\\u2191\\u2191\\u2191\\u2191\\u2191\\u2191\\u2191\\u2191\\u2191\\u2191\\u2191\\u2191\\u2191\\u2191\\u2191\\u2191\\u2191\\u2191\\u2191\\u2191\\u2191\\u2191\\u2191\\u2191\\u2191\\u2191\\u2191\\u2191 |\\n\\n mstore(add(ptr, 0x40), bytecodeHash)\\n mstore(add(ptr, 0x20), salt)\\n mstore(ptr, deployer) // Right-aligned with 12 preceding garbage bytes\\n let start := add(ptr, 0x0b) // The hashed data starts at the final garbage byte which we will set to 0xff\\n mstore8(start, 0xff)\\n addr := and(keccak256(start, 85), 0xffffffffffffffffffffffffffffffffffffffff)\\n }\\n }\\n}\\n\",\"keccak256\":\"0xbb7e8401583d26268ea9103013bcdcd90866a7718bd91105ebd21c9bf11f4f06\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Errors.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.1.0) (utils/Errors.sol)\\n\\npragma solidity ^0.8.20;\\n\\n/**\\n * @dev Collection of common custom errors used in multiple contracts\\n *\\n * IMPORTANT: Backwards compatibility is not guaranteed in future versions of the library.\\n * It is recommended to avoid relying on the error API for critical functionality.\\n *\\n * _Available since v5.1._\\n */\\nlibrary Errors {\\n /**\\n * @dev The ETH balance of the account is not enough to perform the operation.\\n */\\n error InsufficientBalance(uint256 balance, uint256 needed);\\n\\n /**\\n * @dev A call to an address target failed. The target may have reverted.\\n */\\n error FailedCall();\\n\\n /**\\n * @dev The deployment failed.\\n */\\n error FailedDeployment();\\n\\n /**\\n * @dev A necessary precompile is missing.\\n */\\n error MissingPrecompile(address);\\n}\\n\",\"keccak256\":\"0x6afa713bfd42cf0f7656efa91201007ac465e42049d7de1d50753a373648c123\",\"license\":\"MIT\"},\"@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\",\"keccak256\":\"0xf7fe324703a64fc51702311dc51562d5cb1497734f074e4f483bfb6717572d7a\",\"license\":\"MIT\"},\"@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\",\"keccak256\":\"0xcf74f855663ce2ae00ed8352666b7935f6cddea2932fdf2c3ecd30a9b1cd0e97\",\"license\":\"MIT\"},\"@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\",\"keccak256\":\"0x725209b582291bb83058e3078624b53d15a133f7401c30295e7f3704181d2aed\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/cryptography/ECDSA.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.1.0) (utils/cryptography/ECDSA.sol)\\n\\npragma solidity ^0.8.20;\\n\\n/**\\n * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations.\\n *\\n * These functions can be used to verify that a message was signed by the holder\\n * of the private keys of a given address.\\n */\\nlibrary ECDSA {\\n enum RecoverError {\\n NoError,\\n InvalidSignature,\\n InvalidSignatureLength,\\n InvalidSignatureS\\n }\\n\\n /**\\n * @dev The signature derives the `address(0)`.\\n */\\n error ECDSAInvalidSignature();\\n\\n /**\\n * @dev The signature has an invalid length.\\n */\\n error ECDSAInvalidSignatureLength(uint256 length);\\n\\n /**\\n * @dev The signature has an S value that is in the upper half order.\\n */\\n error ECDSAInvalidSignatureS(bytes32 s);\\n\\n /**\\n * @dev Returns the address that signed a hashed message (`hash`) with `signature` or an error. This will not\\n * return address(0) without also returning an error description. Errors are documented using an enum (error type)\\n * and a bytes32 providing additional information about the error.\\n *\\n * If no error is returned, then the address can be used for verification purposes.\\n *\\n * The `ecrecover` EVM precompile allows for malleable (non-unique) signatures:\\n * this function rejects them by requiring the `s` value to be in the lower\\n * half order, and the `v` value to be either 27 or 28.\\n *\\n * IMPORTANT: `hash` _must_ be the result of a hash operation for the\\n * verification to be secure: it is possible to craft signatures that\\n * recover to arbitrary addresses for non-hashed data. A safe way to ensure\\n * this is by receiving a hash of the original message (which may otherwise\\n * be too long), and then calling {MessageHashUtils-toEthSignedMessageHash} on it.\\n *\\n * Documentation for signature generation:\\n * - with https://web3js.readthedocs.io/en/v1.3.4/web3-eth-accounts.html#sign[Web3.js]\\n * - with https://docs.ethers.io/v5/api/signer/#Signer-signMessage[ethers]\\n */\\n function tryRecover(\\n bytes32 hash,\\n bytes memory signature\\n ) internal pure returns (address recovered, RecoverError err, bytes32 errArg) {\\n if (signature.length == 65) {\\n bytes32 r;\\n bytes32 s;\\n uint8 v;\\n // ecrecover takes the signature parameters, and the only way to get them\\n // currently is to use assembly.\\n assembly (\\\"memory-safe\\\") {\\n r := mload(add(signature, 0x20))\\n s := mload(add(signature, 0x40))\\n v := byte(0, mload(add(signature, 0x60)))\\n }\\n return tryRecover(hash, v, r, s);\\n } else {\\n return (address(0), RecoverError.InvalidSignatureLength, bytes32(signature.length));\\n }\\n }\\n\\n /**\\n * @dev Returns the address that signed a hashed message (`hash`) with\\n * `signature`. This address can then be used for verification purposes.\\n *\\n * The `ecrecover` EVM precompile allows for malleable (non-unique) signatures:\\n * this function rejects them by requiring the `s` value to be in the lower\\n * half order, and the `v` value to be either 27 or 28.\\n *\\n * IMPORTANT: `hash` _must_ be the result of a hash operation for the\\n * verification to be secure: it is possible to craft signatures that\\n * recover to arbitrary addresses for non-hashed data. A safe way to ensure\\n * this is by receiving a hash of the original message (which may otherwise\\n * be too long), and then calling {MessageHashUtils-toEthSignedMessageHash} on it.\\n */\\n function recover(bytes32 hash, bytes memory signature) internal pure returns (address) {\\n (address recovered, RecoverError error, bytes32 errorArg) = tryRecover(hash, signature);\\n _throwError(error, errorArg);\\n return recovered;\\n }\\n\\n /**\\n * @dev Overload of {ECDSA-tryRecover} that receives the `r` and `vs` short-signature fields separately.\\n *\\n * See https://eips.ethereum.org/EIPS/eip-2098[ERC-2098 short signatures]\\n */\\n function tryRecover(\\n bytes32 hash,\\n bytes32 r,\\n bytes32 vs\\n ) internal pure returns (address recovered, RecoverError err, bytes32 errArg) {\\n unchecked {\\n bytes32 s = vs & bytes32(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff);\\n // We do not check for an overflow here since the shift operation results in 0 or 1.\\n uint8 v = uint8((uint256(vs) >> 255) + 27);\\n return tryRecover(hash, v, r, s);\\n }\\n }\\n\\n /**\\n * @dev Overload of {ECDSA-recover} that receives the `r and `vs` short-signature fields separately.\\n */\\n function recover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address) {\\n (address recovered, RecoverError error, bytes32 errorArg) = tryRecover(hash, r, vs);\\n _throwError(error, errorArg);\\n return recovered;\\n }\\n\\n /**\\n * @dev Overload of {ECDSA-tryRecover} that receives the `v`,\\n * `r` and `s` signature fields separately.\\n */\\n function tryRecover(\\n bytes32 hash,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) internal pure returns (address recovered, RecoverError err, bytes32 errArg) {\\n // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature\\n // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines\\n // the valid range for s in (301): 0 < s < secp256k1n \\u00f7 2 + 1, and for v in (302): v \\u2208 {27, 28}. Most\\n // signatures from current libraries generate a unique signature with an s-value in the lower half order.\\n //\\n // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value\\n // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or\\n // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept\\n // these malleable signatures as well.\\n if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) {\\n return (address(0), RecoverError.InvalidSignatureS, s);\\n }\\n\\n // If the signature is valid (and not malleable), return the signer address\\n address signer = ecrecover(hash, v, r, s);\\n if (signer == address(0)) {\\n return (address(0), RecoverError.InvalidSignature, bytes32(0));\\n }\\n\\n return (signer, RecoverError.NoError, bytes32(0));\\n }\\n\\n /**\\n * @dev Overload of {ECDSA-recover} that receives the `v`,\\n * `r` and `s` signature fields separately.\\n */\\n function recover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address) {\\n (address recovered, RecoverError error, bytes32 errorArg) = tryRecover(hash, v, r, s);\\n _throwError(error, errorArg);\\n return recovered;\\n }\\n\\n /**\\n * @dev Optionally reverts with the corresponding custom error according to the `error` argument provided.\\n */\\n function _throwError(RecoverError error, bytes32 errorArg) private pure {\\n if (error == RecoverError.NoError) {\\n return; // no error: do nothing\\n } else if (error == RecoverError.InvalidSignature) {\\n revert ECDSAInvalidSignature();\\n } else if (error == RecoverError.InvalidSignatureLength) {\\n revert ECDSAInvalidSignatureLength(uint256(errorArg));\\n } else if (error == RecoverError.InvalidSignatureS) {\\n revert ECDSAInvalidSignatureS(errorArg);\\n }\\n }\\n}\\n\",\"keccak256\":\"0x69f54c02b7d81d505910ec198c11ed4c6a728418a868b906b4a0cf29946fda84\",\"license\":\"MIT\"},\"@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\",\"keccak256\":\"0x4515543bc4c78561f6bea83ecfdfc3dead55bd59858287d682045b11de1ae575\",\"license\":\"MIT\"},\"@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\",\"keccak256\":\"0x79796192ec90263f21b464d5bc90b777a525971d3de8232be80d9c4f9fb353b8\",\"license\":\"MIT\"},\"@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\\u00b2\\u2075\\u2076 and mod 2\\u00b2\\u2075\\u2076 - 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\\u00b2\\u2075\\u2076 + 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\\u00b2\\u2075\\u2076. 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\\u00b2\\u2075\\u2076 / 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\\u00b2\\u2075\\u2076. Now that denominator is an odd number, it has an inverse modulo 2\\u00b2\\u2075\\u2076 such\\n // that denominator * inv \\u2261 1 mod 2\\u00b2\\u2075\\u2076. Compute the inverse by starting with a seed that is correct for\\n // four bits. That is, denominator * inv \\u2261 1 mod 2\\u2074.\\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\\u2078\\n inverse *= 2 - denominator * inverse; // inverse mod 2\\u00b9\\u2076\\n inverse *= 2 - denominator * inverse; // inverse mod 2\\u00b3\\u00b2\\n inverse *= 2 - denominator * inverse; // inverse mod 2\\u2076\\u2074\\n inverse *= 2 - denominator * inverse; // inverse mod 2\\u00b9\\u00b2\\u2078\\n inverse *= 2 - denominator * inverse; // inverse mod 2\\u00b2\\u2075\\u2076\\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\\u00b2\\u2075\\u2076. Since the preconditions guarantee that the outcome is\\n // less than 2\\u00b2\\u2075\\u2076, 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 \\u2261 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) \\u2261 1 mod p`. As a consequence, we have `a * a**(p-2) \\u2261 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\\u00b2 - 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 `\\u03b5_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) \\u2264 sqrt(a) < 2**e`). We know that `e \\u2264 128` because `(2\\u00b9\\u00b2\\u2078)\\u00b2 = 2\\u00b2\\u2075\\u2076` is\\n // bigger than any uint256.\\n //\\n // By noticing that\\n // `2**(e-1) \\u2264 sqrt(a) < 2**e \\u2192 (2**(e-1))\\u00b2 \\u2264 a < (2**e)\\u00b2 \\u2192 2**(2*e-2) \\u2264 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) \\u2264 sqrt(a) < 2**e = 2 * x_n`. This implies \\u03b5_n \\u2264 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 \\u03b5_n \\u2264 2**(e-2).\\n // This is going to be our x_0 (and \\u03b5_0)\\n xn = (3 * xn) >> 1; // \\u03b5_0 := | x_0 - sqrt(a) | \\u2264 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}\\u00b2 - a = ((x_n + a / x_n) / 2)\\u00b2 - a\\n // = ((x_n\\u00b2 + a) / (2 * x_n))\\u00b2 - a\\n // = (x_n\\u2074 + 2 * a * x_n\\u00b2 + a\\u00b2) / (4 * x_n\\u00b2) - a\\n // = (x_n\\u2074 + 2 * a * x_n\\u00b2 + a\\u00b2 - 4 * a * x_n\\u00b2) / (4 * x_n\\u00b2)\\n // = (x_n\\u2074 - 2 * a * x_n\\u00b2 + a\\u00b2) / (4 * x_n\\u00b2)\\n // = (x_n\\u00b2 - a)\\u00b2 / (2 * x_n)\\u00b2\\n // = ((x_n\\u00b2 - a) / (2 * x_n))\\u00b2\\n // \\u2265 0\\n // Which proves that for all n \\u2265 1, sqrt(a) \\u2264 x_n\\n //\\n // This gives us the proof of quadratic convergence of the sequence:\\n // \\u03b5_{n+1} = | x_{n+1} - sqrt(a) |\\n // = | (x_n + a / x_n) / 2 - sqrt(a) |\\n // = | (x_n\\u00b2 + a - 2*x_n*sqrt(a)) / (2 * x_n) |\\n // = | (x_n - sqrt(a))\\u00b2 / (2 * x_n) |\\n // = | \\u03b5_n\\u00b2 / (2 * x_n) |\\n // = \\u03b5_n\\u00b2 / | (2 * x_n) |\\n //\\n // For the first iteration, we have a special case where x_0 is known:\\n // \\u03b5_1 = \\u03b5_0\\u00b2 / | (2 * x_0) |\\n // \\u2264 (2**(e-2))\\u00b2 / (2 * (2**(e-1) + 2**(e-2)))\\n // \\u2264 2**(2*e-4) / (3 * 2**(e-1))\\n // \\u2264 2**(e-3) / 3\\n // \\u2264 2**(e-3-log2(3))\\n // \\u2264 2**(e-4.5)\\n //\\n // For the following iterations, we use the fact that, 2**(e-1) \\u2264 sqrt(a) \\u2264 x_n:\\n // \\u03b5_{n+1} = \\u03b5_n\\u00b2 / | (2 * x_n) |\\n // \\u2264 (2**(e-k))\\u00b2 / (2 * 2**(e-1))\\n // \\u2264 2**(2*e-2*k) / 2**e\\n // \\u2264 2**(e-2*k)\\n xn = (xn + a / xn) >> 1; // \\u03b5_1 := | x_1 - sqrt(a) | \\u2264 2**(e-4.5) -- special case, see above\\n xn = (xn + a / xn) >> 1; // \\u03b5_2 := | x_2 - sqrt(a) | \\u2264 2**(e-9) -- general case with k = 4.5\\n xn = (xn + a / xn) >> 1; // \\u03b5_3 := | x_3 - sqrt(a) | \\u2264 2**(e-18) -- general case with k = 9\\n xn = (xn + a / xn) >> 1; // \\u03b5_4 := | x_4 - sqrt(a) | \\u2264 2**(e-36) -- general case with k = 18\\n xn = (xn + a / xn) >> 1; // \\u03b5_5 := | x_5 - sqrt(a) | \\u2264 2**(e-72) -- general case with k = 36\\n xn = (xn + a / xn) >> 1; // \\u03b5_6 := | x_6 - sqrt(a) | \\u2264 2**(e-144) -- general case with k = 72\\n\\n // Because e \\u2264 128 (as discussed during the first estimation phase), we know have reached a precision\\n // \\u03b5_6 \\u2264 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\",\"keccak256\":\"0xa00be322d7db5786750ce0ac7e2f5b633ac30a5ed5fa1ced1e74acfc19acecea\",\"license\":\"MIT\"},\"@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\",\"keccak256\":\"0x195533c86d0ef72bcc06456a4f66a9b941f38eb403739b00f21fd7c1abd1ae54\",\"license\":\"MIT\"},\"@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\",\"keccak256\":\"0xb1970fac7b64e6c09611e6691791e848d5e3fe410fa5899e7df2e0afd77a99e3\",\"license\":\"MIT\"},\"contracts/accounts/SimpleAccount.sol\":{\"content\":\"// 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 \\\"@openzeppelin/contracts/utils/cryptography/ECDSA.sol\\\";\\nimport \\\"@openzeppelin/contracts/utils/cryptography/MessageHashUtils.sol\\\";\\nimport \\\"@openzeppelin/contracts/proxy/utils/Initializable.sol\\\";\\nimport \\\"@openzeppelin/contracts/proxy/utils/UUPSUpgradeable.sol\\\";\\nimport \\\"../core/BaseAccount.sol\\\";\\nimport \\\"../core/Helpers.sol\\\";\\nimport \\\"./callback/TokenCallbackHandler.sol\\\";\\n\\n/**\\n * minimal account.\\n * this is sample minimal account.\\n * has execute, eth handling methods\\n * has a single signer that can send requests through the entryPoint.\\n */\\ncontract SimpleAccount is BaseAccount, TokenCallbackHandler, UUPSUpgradeable, Initializable {\\n address public owner;\\n\\n IEntryPoint private immutable _entryPoint;\\n\\n event SimpleAccountInitialized(IEntryPoint indexed entryPoint, address indexed owner);\\n\\n modifier onlyOwner() {\\n _onlyOwner();\\n _;\\n }\\n\\n /// @inheritdoc BaseAccount\\n function entryPoint() public view virtual override returns (IEntryPoint) {\\n return _entryPoint;\\n }\\n\\n // solhint-disable-next-line no-empty-blocks\\n receive() external payable {}\\n\\n constructor(IEntryPoint anEntryPoint) {\\n _entryPoint = anEntryPoint;\\n _disableInitializers();\\n }\\n\\n function _onlyOwner() internal view {\\n // Directly from EOA owner, or through the account itself (which gets redirected through execute())\\n require(msg.sender == owner || msg.sender == address(this), \\\"only owner\\\");\\n }\\n\\n /**\\n * @dev The _entryPoint member is immutable, to reduce gas consumption. To upgrade EntryPoint,\\n * a new implementation of SimpleAccount must be deployed with the new EntryPoint address, then upgrading\\n * the implementation by calling `upgradeTo()`\\n * @param anOwner the owner (signer) of this account\\n */\\n function initialize(address anOwner) public virtual initializer {\\n _initialize(anOwner);\\n }\\n\\n function _initialize(address anOwner) internal virtual {\\n owner = anOwner;\\n emit SimpleAccountInitialized(_entryPoint, owner);\\n }\\n\\n // Require the function call went through EntryPoint or owner\\n function _requireForExecute() internal view override virtual {\\n require(msg.sender == address(entryPoint()) || msg.sender == owner, \\\"account: not Owner or EntryPoint\\\");\\n }\\n\\n /// implement template method of BaseAccount\\n function _validateSignature(PackedUserOperation calldata userOp, bytes32 userOpHash)\\n internal override virtual returns (uint256 validationData) {\\n\\n // UserOpHash can be generated using eth_signTypedData_v4\\n if (owner != ECDSA.recover(userOpHash, userOp.signature))\\n return SIG_VALIDATION_FAILED;\\n return SIG_VALIDATION_SUCCESS;\\n }\\n\\n /**\\n * check current account deposit in the entryPoint\\n */\\n function getDeposit() public view returns (uint256) {\\n return entryPoint().balanceOf(address(this));\\n }\\n\\n /**\\n * deposit more funds for this account in the entryPoint\\n */\\n function addDeposit() public payable {\\n entryPoint().depositTo{value: msg.value}(address(this));\\n }\\n\\n /**\\n * withdraw value from the account's deposit\\n * @param withdrawAddress target to send to\\n * @param amount to withdraw\\n */\\n function withdrawDepositTo(address payable withdrawAddress, uint256 amount) public onlyOwner {\\n entryPoint().withdrawTo(withdrawAddress, amount);\\n }\\n\\n function _authorizeUpgrade(address newImplementation) internal view override {\\n (newImplementation);\\n _onlyOwner();\\n }\\n}\\n\\n\",\"keccak256\":\"0xfecdf35a9bb625b8d7b694238ee8aba566ff74c06cdb0e73b783165b035f46a5\",\"license\":\"MIT\"},\"contracts/accounts/SimpleAccountFactory.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.28;\\n\\nimport \\\"@openzeppelin/contracts/utils/Create2.sol\\\";\\nimport \\\"@openzeppelin/contracts/proxy/ERC1967/ERC1967Proxy.sol\\\";\\n\\nimport \\\"../interfaces/ISenderCreator.sol\\\";\\nimport \\\"./SimpleAccount.sol\\\";\\n\\n/**\\n * A sample factory contract for SimpleAccount\\n * A UserOperations \\\"initCode\\\" holds the address of the factory, and a method call (to createAccount, in this sample factory).\\n * The factory's createAccount returns the target account address even if it is already installed.\\n * This way, the entryPoint.getSenderAddress() can be called either before or after the account is created.\\n */\\ncontract SimpleAccountFactory {\\n SimpleAccount public immutable accountImplementation;\\n ISenderCreator public immutable senderCreator;\\n\\n constructor(IEntryPoint _entryPoint) {\\n accountImplementation = new SimpleAccount(_entryPoint);\\n senderCreator = _entryPoint.senderCreator();\\n }\\n\\n /**\\n * create an account, and return its address.\\n * returns the address even if the account is already deployed.\\n * Note that during UserOperation execution, this method is called only if the account is not deployed.\\n * This method returns an existing account address so that entryPoint.getSenderAddress() would work even after account creation\\n */\\n function createAccount(address owner,uint256 salt) public returns (SimpleAccount ret) {\\n require(msg.sender == address(senderCreator), \\\"only callable from SenderCreator\\\");\\n address addr = getAddress(owner, salt);\\n uint256 codeSize = addr.code.length;\\n if (codeSize > 0) {\\n return SimpleAccount(payable(addr));\\n }\\n ret = SimpleAccount(payable(new ERC1967Proxy{salt : bytes32(salt)}(\\n address(accountImplementation),\\n abi.encodeCall(SimpleAccount.initialize, (owner))\\n )));\\n }\\n\\n /**\\n * calculate the counterfactual address of this account as it would be returned by createAccount()\\n */\\n function getAddress(address owner,uint256 salt) public view returns (address) {\\n return Create2.computeAddress(bytes32(salt), keccak256(abi.encodePacked(\\n type(ERC1967Proxy).creationCode,\\n abi.encode(\\n address(accountImplementation),\\n abi.encodeCall(SimpleAccount.initialize, (owner))\\n )\\n )));\\n }\\n}\\n\",\"keccak256\":\"0x212dd1f9a7ec056dbee76f1a35bd0cdf6b0afe83bda2adcc9502c853dc2f2d9f\",\"license\":\"MIT\"},\"contracts/accounts/callback/TokenCallbackHandler.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.28;\\n\\n/* solhint-disable no-empty-blocks */\\n\\nimport \\\"@openzeppelin/contracts/utils/introspection/IERC165.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC1155/IERC1155Receiver.sol\\\";\\n\\n/**\\n * Token callback handler.\\n * Handles supported tokens' callbacks, allowing account receiving these tokens.\\n */\\nabstract contract TokenCallbackHandler is IERC721Receiver, IERC1155Receiver {\\n\\n function onERC721Received(\\n address,\\n address,\\n uint256,\\n bytes calldata\\n ) external pure override returns (bytes4) {\\n return IERC721Receiver.onERC721Received.selector;\\n }\\n\\n function onERC1155Received(\\n address,\\n address,\\n uint256,\\n uint256,\\n bytes calldata\\n ) external pure override returns (bytes4) {\\n return IERC1155Receiver.onERC1155Received.selector;\\n }\\n\\n function onERC1155BatchReceived(\\n address,\\n address,\\n uint256[] calldata,\\n uint256[] calldata,\\n bytes calldata\\n ) external pure override returns (bytes4) {\\n return IERC1155Receiver.onERC1155BatchReceived.selector;\\n }\\n\\n function supportsInterface(bytes4 interfaceId) external view virtual override returns (bool) {\\n return\\n interfaceId == type(IERC721Receiver).interfaceId ||\\n interfaceId == type(IERC1155Receiver).interfaceId ||\\n interfaceId == type(IERC165).interfaceId;\\n }\\n}\\n\",\"keccak256\":\"0xd91a14caef87567866880b0f01955dfa50b4bc593dcecfcb38be41d98e6b9662\",\"license\":\"MIT\"},\"contracts/core/BaseAccount.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.28;\\n\\n/* solhint-disable avoid-low-level-calls */\\n/* solhint-disable no-empty-blocks */\\n/* solhint-disable no-inline-assembly */\\n\\nimport \\\"../interfaces/IAccount.sol\\\";\\nimport \\\"../interfaces/IEntryPoint.sol\\\";\\nimport \\\"../utils/Exec.sol\\\";\\nimport \\\"./UserOperationLib.sol\\\";\\n\\n/**\\n * Basic account implementation.\\n * This contract provides the basic logic for implementing the IAccount interface - validateUserOp\\n * Specific account implementation should inherit it and provide the account-specific logic.\\n */\\nabstract contract BaseAccount is IAccount {\\n using UserOperationLib for PackedUserOperation;\\n\\n struct Call {\\n address target;\\n uint256 value;\\n bytes data;\\n }\\n\\n error ExecuteError(uint256 index, bytes error);\\n\\n /**\\n * Return the account nonce.\\n * This method returns the next sequential nonce.\\n * For a nonce of a specific key, use `entrypoint.getNonce(account, key)`\\n */\\n function getNonce() public view virtual returns (uint256) {\\n return entryPoint().getNonce(address(this), 0);\\n }\\n\\n /**\\n * Return the entryPoint used by this account.\\n * Subclass should return the current entryPoint used by this account.\\n */\\n function entryPoint() public view virtual returns (IEntryPoint);\\n\\n /**\\n * execute a single call from the account.\\n */\\n function execute(address target, uint256 value, bytes calldata data) virtual external {\\n _requireForExecute();\\n\\n bool ok = Exec.call(target, value, data, gasleft());\\n if (!ok) {\\n Exec.revertWithReturnData();\\n }\\n }\\n\\n /**\\n * execute a batch of calls.\\n * revert on the first call that fails.\\n * If the batch reverts, and it contains more than a single call, then wrap the revert with ExecuteError,\\n * to mark the failing call index.\\n */\\n function executeBatch(Call[] calldata calls) virtual external {\\n _requireForExecute();\\n\\n uint256 callsLength = calls.length;\\n for (uint256 i = 0; i < callsLength; i++) {\\n Call calldata call = calls[i];\\n bool ok = Exec.call(call.target, call.value, call.data, gasleft());\\n if (!ok) {\\n if (callsLength == 1) {\\n Exec.revertWithReturnData();\\n } else {\\n revert ExecuteError(i, Exec.getReturnData(0));\\n }\\n }\\n }\\n }\\n\\n /// @inheritdoc IAccount\\n function validateUserOp(\\n PackedUserOperation calldata userOp,\\n bytes32 userOpHash,\\n uint256 missingAccountFunds\\n ) external virtual override returns (uint256 validationData) {\\n _requireFromEntryPoint();\\n validationData = _validateSignature(userOp, userOpHash);\\n _validateNonce(userOp.nonce);\\n _payPrefund(missingAccountFunds);\\n }\\n\\n /**\\n * Ensure the request comes from the known entrypoint.\\n */\\n function _requireFromEntryPoint() internal view virtual {\\n require(\\n msg.sender == address(entryPoint()),\\n \\\"account: not from EntryPoint\\\"\\n );\\n }\\n\\n function _requireForExecute() internal view virtual {\\n _requireFromEntryPoint();\\n }\\n\\n /**\\n * Validate the signature is valid for this message.\\n * @param userOp - Validate the userOp.signature field.\\n * @param userOpHash - Convenient field: the hash of the request, to check the signature against.\\n * (also hashes the entrypoint and chain id)\\n * @return validationData - Signature and time-range of this operation.\\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 the account doesn't use time-range, it is enough to return\\n * 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 _validateSignature(\\n PackedUserOperation calldata userOp,\\n bytes32 userOpHash\\n ) internal virtual returns (uint256 validationData);\\n\\n /**\\n * Validate the nonce of the UserOperation.\\n * This method may validate the nonce requirement of this account.\\n * e.g.\\n * To limit the nonce to use sequenced UserOps only (no \\\"out of order\\\" UserOps):\\n * `require(nonce < type(uint64).max)`\\n * For a hypothetical account that *requires* the nonce to be out-of-order:\\n * `require(nonce & type(uint64).max == 0)`\\n *\\n * The actual nonce uniqueness is managed by the EntryPoint, and thus no other\\n * action is needed by the account itself.\\n *\\n * @param nonce to validate\\n *\\n * solhint-disable-next-line no-empty-blocks\\n */\\n function _validateNonce(uint256 nonce) internal view virtual {\\n }\\n\\n /**\\n * Sends to the entrypoint (msg.sender) the missing funds for this transaction.\\n * SubClass MAY override this method for better funds management\\n * (e.g. send to the entryPoint more than the minimum required, so that in future transactions\\n * it will not be required to send again).\\n * @param missingAccountFunds - The minimum value this method should send the entrypoint.\\n * This value MAY be zero, in case there is enough deposit,\\n * or the userOp has a paymaster.\\n */\\n function _payPrefund(uint256 missingAccountFunds) internal virtual {\\n if (missingAccountFunds != 0) {\\n (bool success,) = payable(msg.sender).call{\\n value: missingAccountFunds\\n }(\\\"\\\");\\n (success);\\n // Ignore failure (its EntryPoint's job to verify, not account.)\\n }\\n }\\n}\\n\",\"keccak256\":\"0x071e38cf697bedbfe021955879277620ff763ecca1a1143ce14792e8c86c6d94\",\"license\":\"MIT\"},\"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\",\"keccak256\":\"0x42b948af5fa14a96149611595df1186800c7558b2de8762e4b45a7c45c16f65e\",\"license\":\"MIT\"},\"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\",\"keccak256\":\"0x2d3450fa3906422b6fdbbe7f2a2a9e36d6f3751bfa9cd80af88befd6a5be78c1\",\"license\":\"MIT\"},\"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\",\"keccak256\":\"0x1030b464b49ce80da46b5b6c9af357c2d526f308de61391db6a4ec767d33b864\",\"license\":\"MIT\"},\"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\",\"keccak256\":\"0xdf580eafa015b81bde436d6a5468cc92b531ada84007cef885e923f6dfc5e8bf\",\"license\":\"MIT\"},\"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\",\"keccak256\":\"0x3b0423737e810dd886183ed32cfed9b45edd315f5fb3e1076fc19f86791adc64\",\"license\":\"MIT\"},\"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\",\"keccak256\":\"0xee493ae200b8c675bdc0da66f7ac6bb883ecea33672d7d0a95526b9eecdedf87\",\"license\":\"MIT\"},\"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\",\"keccak256\":\"0x677f651d733162b80d1af7901e4f36469e362737a8353d1d0cc7bb94489e4ba4\",\"license\":\"MIT\"},\"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\",\"keccak256\":\"0xe48e904fcac02295aad07fbfa1c1d449a74bf44c04e432afef6f34d1ef726ae0\",\"license\":\"MIT\"},\"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\",\"keccak256\":\"0xb15188e25e45fe73097e279675b6c0beccbd4133ead2260f8f0c4ba840046800\",\"license\":\"MIT\"},\"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\",\"keccak256\":\"0x9c724ee22011193ea7f92d3c3c467ee6aa27139d3ddc225c7f1254d241e6ccdd\",\"license\":\"MIT\"}},\"version\":1}", + "bytecode": "0x60c0806040523461010d57602081612433803803809161001f8285610138565b83398101031261010d57516001600160a01b0381169081900361010d57604051611a5a808201906001600160401b038211838310176101245760209183916109d983398481520301905ff08015610119576080526040516213997160e71b815290602090829060049082905afa908115610119575f916100d3575b5060a05260405161087d908161015c823960805181818160e60152818161037d01526104df015260a05181818161015201526102b20152f35b90506020813d602011610111575b816100ee60209383610138565b8101031261010d57516001600160a01b038116810361010d575f61009a565b5f80fd5b3d91506100e1565b6040513d5f823e3d90fd5b634e487b7160e01b5f52604160045260245ffd5b601f909101601f19168101906001600160401b038211908210176101245760405256fe6080806040526004361015610012575f80fd5b5f3560e01c90816309ccb8801461010a5750806311464fbe1461009c5780635fbfb9cf1461008357638cb84e1814610048575f80fd5b3461007f57602061006161005b36610176565b9061044b565b73ffffffffffffffffffffffffffffffffffffffff60405191168152f35b5f80fd5b3461007f57602061006161009636610176565b9061029b565b3461007f575f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261007f57602060405173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000168152f35b3461007f575f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261007f5760209073ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000168152f35b7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc604091011261007f5760043573ffffffffffffffffffffffffffffffffffffffff8116810361007f579060243590565b90601f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0910116810190811067ffffffffffffffff82111761020857604052565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b90601f602060609473ffffffffffffffffffffffffffffffffffffffff7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0941685526040828601528051918291826040880152018686015e5f8582860101520116010190565b73ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001633036103ed576102e2828261044b565b803b6103d1575073ffffffffffffffffffffffffffffffffffffffff604051917fc4d66de80000000000000000000000000000000000000000000000000000000060208401521660248201526024815261033d6044826101c7565b604051906102a88083019183831067ffffffffffffffff8411176102085783926103a3926105a0853973ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001690610235565b03905ff580156103c65773ffffffffffffffffffffffffffffffffffffffff1690565b6040513d5f823e3d90fd5b73ffffffffffffffffffffffffffffffffffffffff1692915050565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602060248201527f6f6e6c792063616c6c61626c652066726f6d2053656e64657243726561746f726044820152fd5b600b73ffffffffffffffffffffffffffffffffffffffff926055926102a8906105806040519261047e60208201856101c7565b80845260208401906105a0823987604051937fc4d66de8000000000000000000000000000000000000000000000000000000006020860152166024840152602483526104cb6044846101c7565b60206040519361053185610505848201938d7f00000000000000000000000000000000000000000000000000000000000000001685610235565b037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081018752866101c7565b60405194859383850197518091895e840190838201905f8252519283915e01015f8152037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081018352826101c7565b5190209060405191604083015260208201523081520160ff815320169056fe60806040526102a88038038061001481610168565b92833981016040828203126101645781516001600160a01b03811692909190838303610164576020810151906001600160401b03821161016457019281601f8501121561016457835161006e610069826101a1565b610168565b9481865260208601936020838301011161016457815f926020809301865e86010152823b15610152577f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc80546001600160a01b031916821790557fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b5f80a282511561013a575f8091610122945190845af43d15610132573d91610113610069846101a1565b9283523d5f602085013e6101bc565b505b604051608d908161021b8239f35b6060916101bc565b50505034156101245763b398979f60e01b5f5260045ffd5b634c9c8ce360e01b5f5260045260245ffd5b5f80fd5b6040519190601f01601f191682016001600160401b0381118382101761018d57604052565b634e487b7160e01b5f52604160045260245ffd5b6001600160401b03811161018d57601f01601f191660200190565b906101e057508051156101d157805190602001fd5b63d6bda27560e01b5f5260045ffd5b81511580610211575b6101f1575090565b639996b31560e01b5f9081526001600160a01b0391909116600452602490fd5b50803b156101e956fe60806040525f8073ffffffffffffffffffffffffffffffffffffffff7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5416368280378136915af43d5f803e156053573d5ff35b3d5ffdfea264697066735822122012ef914fc5c0fe0eff95047a7f10780a737a1ca4f30269b985bcf38a18e4d23464736f6c634300081c0033a264697066735822122066c9a94ba9d56842fb888dc2cf77cab726a70ab7553a9d08125d4ea7c35a9fd064736f6c634300081c003360c03461014757601f611a5a38819003918201601f19168301916001600160401b0383118484101761014b5780849260209460405283398101031261014757516001600160a01b0381168103610147573060805260a0525f516020611a3a5f395f51905f525460ff8160401c16610138576002600160401b03196001600160401b038216016100e2575b6040516118da908161016082396080518181816108c401526109b8015260a0518181816101f0015281816103a7015281816105960152818161078601528181610cf501528181610dca0152818161102601526115130152f35b6001600160401b0319166001600160401b039081175f516020611a3a5f395f51905f52556040519081527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d290602090a15f610089565b63f92ee8a960e01b5f5260045ffd5b5f80fd5b634e487b7160e01b5f52604160045260245ffdfe608080604052600436101561001c575b50361561001a575f80fd5b005b5f905f3560e01c90816301ffc9a71461117157508063150b7a02146110e457806319822f7c14610f9e57806334fcd5be14610e4e5780634a58db1914610d895780634d44560d14610c845780634f1ef2861461093c57806352d1902d1461087e5780638da5cb5b1461082d578063ad3cb1cc146107aa578063b0d691fe1461073b578063b61d27f6146106a1578063bc197c81146105cf578063c399ec881461051d578063c4d66de81461026d578063d087d288146101715763f23a6e610361000f573461016e5760a07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261016e5761011661125e565b5061011f611281565b5060843567ffffffffffffffff811161016c576101409036906004016112a4565b505060206040517ff23a6e61000000000000000000000000000000000000000000000000000000008152f35b505b80fd5b503461016e57807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261016e57604051907f35567e1a00000000000000000000000000000000000000000000000000000000825230600483015280602483015260208260448173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000165afa908115610261579061022a575b602090604051908152f35b506020813d602011610259575b8161024460209383611303565b81010312610255576020905161021f565b5f80fd5b3d9150610237565b604051903d90823e3d90fd5b503461016e5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261016e576102a561125e565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00549060ff8260401c16159167ffffffffffffffff811680159081610515575b600114908161050b575b159081610502575b506104da5790818360017fffffffffffffffffffffffffffffffffffffffffffffffff000000000000000073ffffffffffffffffffffffffffffffffffffffff9516177ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a0055610485575b501690817fffffffffffffffffffffffff00000000000000000000000000000000000000008454161783556040519173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000167f47e55c76e7a6f1fd8996a1da8008c1ea29699cca35e7bcd057f2dec313b6e5de8580a36103f3575080f35b60207fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d2917fffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffff7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a0054167ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a005560018152a180f35b7fffffffffffffffffffffffffffffffffffffffffffffff0000000000000000001668010000000000000001177ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00555f610361565b6004847ff92ee8a9000000000000000000000000000000000000000000000000000000008152fd5b9050155f6102f7565b303b1591506102ef565b8491506102e5565b503461016e57807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261016e57604051907f70a0823100000000000000000000000000000000000000000000000000000000825230600483015260208260248173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000165afa908115610261579061022a57602090604051908152f35b503461016e5760a07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261016e5761060761125e565b50610610611281565b5060443567ffffffffffffffff811161016c576106319036906004016112d2565b505060643567ffffffffffffffff811161016c576106539036906004016112d2565b505060843567ffffffffffffffff811161016c576106759036906004016112a4565b505060206040517fbc197c81000000000000000000000000000000000000000000000000000000008152f35b503461016e5760607ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261016e57806106da61125e565b60443567ffffffffffffffff81116107375782916106ff6107129236906004016112a4565b92906107096114fc565b5a9336916113ab565b916020835193019160243591f1156107275780f35b61072f6115c1565b602081519101fd5b5050fd5b503461016e57807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261016e57602060405173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000168152f35b503461016e57807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261016e57506108296040516107eb604082611303565b600581527f352e302e3000000000000000000000000000000000000000000000000000000060208201526040519182916020835260208301906113e1565b0390f35b503461016e57807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261016e5773ffffffffffffffffffffffffffffffffffffffff6020915416604051908152f35b503461016e57807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261016e5773ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001630036109145760206040517f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc8152f35b807fe07c8dba0000000000000000000000000000000000000000000000000000000060049252fd5b5060407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261016e5761096f61125e565b9060243567ffffffffffffffff811161016c573660238201121561016c576109a19036906024816004013591016113ab565b73ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016803014908115610c42575b50610c1a576109f06115db565b73ffffffffffffffffffffffffffffffffffffffff831690604051937f52d1902d000000000000000000000000000000000000000000000000000000008552602085600481865afa80958596610be2575b50610a7257602484847f4c9c8ce3000000000000000000000000000000000000000000000000000000008252600452fd5b9091847f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc8103610bb75750813b15610b8c57807fffffffffffffffffffffffff00000000000000000000000000000000000000007f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5416177f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc557fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b8480a28151839015610b595780836020610b5595519101845af4610b4f6114cd565b9161180b565b5080f35b50505034610b645780f35b807fb398979f0000000000000000000000000000000000000000000000000000000060049252fd5b7f4c9c8ce3000000000000000000000000000000000000000000000000000000008452600452602483fd5b7faa1d49a4000000000000000000000000000000000000000000000000000000008552600452602484fd5b9095506020813d602011610c12575b81610bfe60209383611303565b81010312610c0e5751945f610a41565b8480fd5b3d9150610bf1565b6004827fe07c8dba000000000000000000000000000000000000000000000000000000008152fd5b905073ffffffffffffffffffffffffffffffffffffffff7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc541614155f6109e3565b503461016e5760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261016e578060043573ffffffffffffffffffffffffffffffffffffffff8116809103610d8657610cde6115db565b73ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001690813b156107375782916044839260405194859384927f205c2878000000000000000000000000000000000000000000000000000000008452600484015260243560248401525af18015610d7b57610d6a5750f35b81610d7491611303565b61016e5780f35b6040513d84823e3d90fd5b50fd5b505f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126102555773ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016803b15610255575f602491604051928380927fb760faf900000000000000000000000000000000000000000000000000000000825230600483015234905af18015610e4357610e37575080f35b61001a91505f90611303565b6040513d5f823e3d90fd5b346102555760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126102555760043567ffffffffffffffff811161025557610e9d9036906004016112d2565b610ea56114fc565b5f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa183360301905b8281101561001a578060051b8401358281121561025557840180359073ffffffffffffffffffffffffffffffffffffffff82168203610255575f9181610f25610f1a604086950183611424565b91905a9236916113ab565b926020808551950193013591f115610f3f57600101610ecd565b60018303610f4f5761072f6115c1565b610f576115c1565b90610f9a6040519283927f5a15467500000000000000000000000000000000000000000000000000000000845260048401526040602484015260448301906113e1565b0390fd5b346102555760607ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126102555760043567ffffffffffffffff8111610255576101207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc82360301126102555760443573ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001633036110865761105e60209260243590600401611475565b908061106e575b50604051908152f35b5f80808093335af15061107f6114cd565b5082611065565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601c60248201527f6163636f756e743a206e6f742066726f6d20456e747279506f696e74000000006044820152fd5b346102555760807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126102555761111b61125e565b50611124611281565b5060643567ffffffffffffffff8111610255576111459036906004016112a4565b505060206040517f150b7a02000000000000000000000000000000000000000000000000000000008152f35b346102555760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261025557600435907fffffffff00000000000000000000000000000000000000000000000000000000821680920361025557817f150b7a020000000000000000000000000000000000000000000000000000000060209314908115611234575b811561120a575b5015158152f35b7f01ffc9a70000000000000000000000000000000000000000000000000000000091501483611203565b7f4e2312e000000000000000000000000000000000000000000000000000000000811491506111fc565b6004359073ffffffffffffffffffffffffffffffffffffffff8216820361025557565b6024359073ffffffffffffffffffffffffffffffffffffffff8216820361025557565b9181601f840112156102555782359167ffffffffffffffff8311610255576020838186019501011161025557565b9181601f840112156102555782359167ffffffffffffffff8311610255576020808501948460051b01011161025557565b90601f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0910116810190811067ffffffffffffffff82111761134457604052565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b67ffffffffffffffff811161134457601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200190565b9291926113b782611371565b916113c56040519384611303565b829481845281830111610255578281602093845f960137010152565b907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f602080948051918291828752018686015e5f8582860101520116010190565b9035907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe181360301821215610255570180359067ffffffffffffffff82116102555760200191813603831361025557565b906114be6114b573ffffffffffffffffffffffffffffffffffffffff926114af6114a8855f541696610100810190611424565b36916113ab565b9061166a565b909291926116a4565b16036114c8575f90565b600190565b3d156114f7573d906114de82611371565b916114ec6040519384611303565b82523d5f602084013e565b606090565b73ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016331480156115a1575b1561154357565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602060248201527f6163636f756e743a206e6f74204f776e6572206f7220456e747279506f696e746044820152fd5b5073ffffffffffffffffffffffffffffffffffffffff5f5416331461153c565b3d604051906020818301016040528082525f602083013e90565b73ffffffffffffffffffffffffffffffffffffffff5f541633148015611661575b1561160357565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600a60248201527f6f6e6c79206f776e6572000000000000000000000000000000000000000000006044820152fd5b503033146115fc565b815191906041830361169a576116939250602082015190606060408401519301515f1a9061177c565b9192909190565b50505f9160029190565b600481101561174f57806116b6575050565b600181036116e6577ff645eedf000000000000000000000000000000000000000000000000000000005f5260045ffd5b6002810361171a57507ffce698f7000000000000000000000000000000000000000000000000000000005f5260045260245ffd5b6003146117245750565b7fd78bce0c000000000000000000000000000000000000000000000000000000005f5260045260245ffd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602160045260245ffd5b91907f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a08411611800579160209360809260ff5f9560405194855216868401526040830152606082015282805260015afa15610e43575f5173ffffffffffffffffffffffffffffffffffffffff8116156117f657905f905f90565b505f906001905f90565b5050505f9160039190565b90611848575080511561182057805190602001fd5b7fd6bda275000000000000000000000000000000000000000000000000000000005f5260045ffd5b8151158061189b575b611859575090565b73ffffffffffffffffffffffffffffffffffffffff907f9996b315000000000000000000000000000000000000000000000000000000005f521660045260245ffd5b50803b1561185156fea2646970667358221220d37aff8d76de5b79d9a6144dc38b8c5efe3e2f3cf6c07850979839cabc14388d64736f6c634300081c0033f0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00", + "deployedBytecode": "0x6080806040526004361015610012575f80fd5b5f3560e01c90816309ccb8801461010a5750806311464fbe1461009c5780635fbfb9cf1461008357638cb84e1814610048575f80fd5b3461007f57602061006161005b36610176565b9061044b565b73ffffffffffffffffffffffffffffffffffffffff60405191168152f35b5f80fd5b3461007f57602061006161009636610176565b9061029b565b3461007f575f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261007f57602060405173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000168152f35b3461007f575f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261007f5760209073ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000168152f35b7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc604091011261007f5760043573ffffffffffffffffffffffffffffffffffffffff8116810361007f579060243590565b90601f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0910116810190811067ffffffffffffffff82111761020857604052565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b90601f602060609473ffffffffffffffffffffffffffffffffffffffff7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0941685526040828601528051918291826040880152018686015e5f8582860101520116010190565b73ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001633036103ed576102e2828261044b565b803b6103d1575073ffffffffffffffffffffffffffffffffffffffff604051917fc4d66de80000000000000000000000000000000000000000000000000000000060208401521660248201526024815261033d6044826101c7565b604051906102a88083019183831067ffffffffffffffff8411176102085783926103a3926105a0853973ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001690610235565b03905ff580156103c65773ffffffffffffffffffffffffffffffffffffffff1690565b6040513d5f823e3d90fd5b73ffffffffffffffffffffffffffffffffffffffff1692915050565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602060248201527f6f6e6c792063616c6c61626c652066726f6d2053656e64657243726561746f726044820152fd5b600b73ffffffffffffffffffffffffffffffffffffffff926055926102a8906105806040519261047e60208201856101c7565b80845260208401906105a0823987604051937fc4d66de8000000000000000000000000000000000000000000000000000000006020860152166024840152602483526104cb6044846101c7565b60206040519361053185610505848201938d7f00000000000000000000000000000000000000000000000000000000000000001685610235565b037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081018752866101c7565b60405194859383850197518091895e840190838201905f8252519283915e01015f8152037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081018352826101c7565b5190209060405191604083015260208201523081520160ff815320169056fe60806040526102a88038038061001481610168565b92833981016040828203126101645781516001600160a01b03811692909190838303610164576020810151906001600160401b03821161016457019281601f8501121561016457835161006e610069826101a1565b610168565b9481865260208601936020838301011161016457815f926020809301865e86010152823b15610152577f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc80546001600160a01b031916821790557fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b5f80a282511561013a575f8091610122945190845af43d15610132573d91610113610069846101a1565b9283523d5f602085013e6101bc565b505b604051608d908161021b8239f35b6060916101bc565b50505034156101245763b398979f60e01b5f5260045ffd5b634c9c8ce360e01b5f5260045260245ffd5b5f80fd5b6040519190601f01601f191682016001600160401b0381118382101761018d57604052565b634e487b7160e01b5f52604160045260245ffd5b6001600160401b03811161018d57601f01601f191660200190565b906101e057508051156101d157805190602001fd5b63d6bda27560e01b5f5260045ffd5b81511580610211575b6101f1575090565b639996b31560e01b5f9081526001600160a01b0391909116600452602490fd5b50803b156101e956fe60806040525f8073ffffffffffffffffffffffffffffffffffffffff7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5416368280378136915af43d5f803e156053573d5ff35b3d5ffdfea264697066735822122012ef914fc5c0fe0eff95047a7f10780a737a1ca4f30269b985bcf38a18e4d23464736f6c634300081c0033a264697066735822122066c9a94ba9d56842fb888dc2cf77cab726a70ab7553a9d08125d4ea7c35a9fd064736f6c634300081c0033", + "devdoc": { + "kind": "dev", + "methods": {}, + "version": 1 + }, + "userdoc": { + "kind": "user", + "methods": { + "createAccount(address,uint256)": { + "notice": "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" + }, + "getAddress(address,uint256)": { + "notice": "calculate the counterfactual address of this account as it would be returned by createAccount()" + } + }, + "notice": "A sample factory contract for SimpleAccount A UserOperations \"initCode\" holds the address of the factory, and a method call (to createAccount, in this sample factory). The factory's createAccount returns the target account address even if it is already installed. This way, the entryPoint.getSenderAddress() can be called either before or after the account is created.", + "version": 1 + }, + "storageLayout": { + "storage": [], + "types": null + } +} \ No newline at end of file diff --git a/dependencies/eth-infinitism-account-abstraction-0.9.0/deployments/ethereum/proxy/.chainId b/dependencies/eth-infinitism-account-abstraction-0.9.0/deployments/ethereum/proxy/.chainId new file mode 100644 index 0000000..56a6051 --- /dev/null +++ b/dependencies/eth-infinitism-account-abstraction-0.9.0/deployments/ethereum/proxy/.chainId @@ -0,0 +1 @@ +1 \ No newline at end of file diff --git a/dependencies/eth-infinitism-account-abstraction-0.8.0/deployments/ethereum/solcInputs/594e0595d5f1f4861d3b32a5f38cc32f.json b/dependencies/eth-infinitism-account-abstraction-0.9.0/deployments/ethereum/solcInputs/3affd247c847bf3b9442c478ca38a4a0.json similarity index 58% rename from dependencies/eth-infinitism-account-abstraction-0.8.0/deployments/ethereum/solcInputs/594e0595d5f1f4861d3b32a5f38cc32f.json rename to dependencies/eth-infinitism-account-abstraction-0.9.0/deployments/ethereum/solcInputs/3affd247c847bf3b9442c478ca38a4a0.json index fb28d1a..dbb3647 100644 --- a/dependencies/eth-infinitism-account-abstraction-0.8.0/deployments/ethereum/solcInputs/594e0595d5f1f4861d3b32a5f38cc32f.json +++ b/dependencies/eth-infinitism-account-abstraction-0.9.0/deployments/ethereum/solcInputs/3affd247c847bf3b9442c478ca38a4a0.json @@ -28,9 +28,6 @@ "@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" }, @@ -40,29 +37,26 @@ "@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" + "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 error Eip7702SenderWithoutCode(address sender);\n error Eip7702SenderNotDelegate(address sender);\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, Eip7702SenderWithoutCode(sender));\n revert Eip7702SenderNotDelegate(sender);\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" + "content": "// SPDX-License-Identifier: GPL-3.0\npragma solidity ^0.8.28;\n\n/* solhint-disable avoid-low-level-calls */\n/* solhint-disable gas-calldata-parameters */\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/introspection/ERC165.sol\";\nimport \"@openzeppelin/contracts/utils/cryptography/EIP712.sol\";\n\n/**\n * Account-Abstraction (EIP-4337) singleton EntryPoint v0.9 implementation.\n * Only one instance required on each chain.\n * @custom:security-contact https://bounty.ethereum.org\n */\ncontract EntryPoint is IEntryPoint, StakeManager, NonceManager, ERC165, EIP712 {\n\n using UserOperationLib for PackedUserOperation;\n using Eip7702Support for address;\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 uint48 private constant VALIDITY_BLOCK_RANGE_FLAG = 0x800000000000;\n uint48 private constant VALIDITY_BLOCK_RANGE_MASK = 0x7fffffffffff;\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 bytes32 transient private currentUserOpHash;\n\n error Reentrancy();\n\n constructor() EIP712(DOMAIN_NAME, DOMAIN_VERSION) {\n }\n\n modifier nonReentrant() {\n require(\n // solhint-disable avoid-tx-origin\n tx.origin == msg.sender && msg.sender.code.length == 0,\n Reentrancy()\n );\n _;\n }\n\n /// @inheritdoc IEntryPoint\n function handleOps(\n PackedUserOperation[] calldata ops,\n address payable beneficiary\n ) external virtual 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 virtual 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 /// @inheritdoc IEntryPoint\n function getCurrentUserOpHash(\n ) public view returns (bytes32) {\n return currentUserOpHash;\n }\n\n /// @inheritdoc IEntryPoint\n function getSenderAddress(bytes calldata initCode) external virtual {\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 virtual {\n (bool success, bytes memory ret) = target.delegatecall(data);\n revert DelegateAndRevert(success, ret);\n }\n\n function getPackedUserOpTypeHash() external virtual 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), InvalidBeneficiary(beneficiary));\n (bool success, bytes memory ret) = beneficiary.call{value: amount}(\"\");\n require(success, FailedSendToBeneficiary(beneficiary, amount, ret));\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 currentUserOpHash = opInfo.userOpHash;\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 virtual 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 virtual returns (uint256 actualGasCost) {\n uint256 preGas = gasleft();\n require(msg.sender == address(this), InternalFunction());\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 InvalidPaymasterData(paymasterAndData.length)\n );\n address paymaster;\n (paymaster, mUserOp.paymasterVerificationGasLimit, mUserOp.paymasterPostOpGasLimit) = UserOperationLib.unpackPaymasterStaticFields(paymasterAndData);\n require(paymaster != address(0), InvalidPaymaster(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 address delegate = sender._getEip7702Delegate();\n emit EIP7702AccountInitialized(opInfo.userOpHash, sender, delegate);\n }\n return;\n }\n if (initCode.length < 20) {\n revert FailedOp(opIndex, \"AA99 initCode too small\");\n }\n address factory = address(bytes20(initCode[0 : 20]));\n if (sender.code.length != 0) {\n // ignoring the initcode for an existing 'sender' contract\n emit IgnoredInitCode(\n opInfo.userOpHash,\n sender,\n factory\n );\n return;\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 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 pmVerificationGasLimit\");\n }\n }\n }\n\n function _callValidatePaymasterUserOp(\n uint256 opIndex,\n PackedUserOperation calldata op,\n UserOpInfo memory opInfo\n ) internal virtual 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 outOfValidityRange, bool isBlockRange) = _getValidationData(\n validationData\n );\n if (expectedAggregator != aggregator) {\n revert FailedOp(opIndex, \"AA24 signature error\");\n }\n if (outOfValidityRange) {\n if (isBlockRange) {\n revert FailedOp(opIndex, \"AA27 outside valid block range\");\n }\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, outOfValidityRange, isBlockRange) = _getValidationData(\n paymasterValidationData\n );\n if (pmAggregator != address(0)) {\n revert FailedOp(opIndex, \"AA34 signature error\");\n }\n if (outOfValidityRange) {\n if (isBlockRange) {\n revert FailedOp(opIndex, \"AA37 paymaster inval block range\");\n }\n // solhint-disable-next-line gas-small-strings\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 outOfValidityRange 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 outOfValidityRange, bool isBlockRange) {\n if (validationData == 0) {\n return (address(0), false, false);\n }\n ValidationData memory data = _parseValidationData(validationData);\n // using top bit of 'validAfter' and 'validUntil' to indicate block-range instead of time-range\n if (data.validAfter > VALIDITY_BLOCK_RANGE_FLAG && data.validUntil > VALIDITY_BLOCK_RANGE_FLAG) {\n uint48 validAfterBlock = data.validAfter & VALIDITY_BLOCK_RANGE_MASK;\n uint48 validUntilBlock = data.validUntil & VALIDITY_BLOCK_RANGE_MASK;\n outOfValidityRange = block.number > validUntilBlock || block.number <= validAfterBlock;\n isBlockRange = true;\n } else {\n // solhint-disable-next-line not-rely-on-time\n outOfValidityRange = block.timestamp > data.validUntil || block.timestamp <= data.validAfter;\n isBlockRange = false;\n }\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 virtual 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 virtual 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" + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.28;\nimport \"./UserOperationLib.sol\";\n\n/* solhint-disable no-inline-assembly */\n\nusing UserOperationLib for bytes;\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 */\nfunction 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 * @notice Computes the Keccak-256 hash of a slice of calldata, followed by an 8-byte suffix.\n * This function copies the first `len` bytes from the given calldata array `data` into memory.\n * The assembly code is equivalent to:\n * keccak256(abi.encodePacked(data[0:len], suffix))\n * But more efficient, and doesn't leave the copied data in memory.\n *\n * @param data Calldata byte array to read from.\n * @param len Number of bytes to copy from `data` starting at its offset.\n * @param suffix 8-byte value appended to the data bytes before hashing.\n *\n * @return ret The hash of (data[0:len] || suffix).\n */\nfunction calldataKeccakWithSuffix(bytes calldata data, uint256 len, bytes8 suffix) pure returns (bytes32 ret) {\n assembly (\"memory-safe\") {\n let mem := mload(0x40)\n calldatacopy(mem, data.offset, len)\n mstore(add(mem, len), suffix)\n len := add(len, 8)\n ret := keccak256(mem, len)\n }\n}\n\n/**\n * Keccak function over paymaster data.\n * If data ends with `PAYMASTER_SIG_MAGIC`, then\n * read the previous 2 bytes as pmSignatureLength,\n * and ignore this suffix from the hash.\n * This means that the trailing pmSignatureLength+10 bytes are not covered by the UserOpHash, and thus are not signed.\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 */\nfunction paymasterDataKeccak(bytes calldata data) pure returns (bytes32 ret) {\n uint256 pmSignatureLength = data.getPaymasterSignatureLength();\n if (pmSignatureLength > 0) {\n unchecked {\n //keccak everything up to the paymasterSignature, but still append the sig magic.\n return calldataKeccakWithSuffix(data, data.length - (pmSignatureLength + UserOperationLib.PAYMASTER_SUFFIX_LEN), UserOperationLib.PAYMASTER_SIG_MAGIC);\n }\n }\n return calldataKeccak(data);\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" + "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 virtual 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 virtual 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" + "content": "// SPDX-License-Identifier: GPL-3.0\npragma solidity ^0.8.28;\n\n/* solhint-disable avoid-low-level-calls */\n/* solhint-disable gas-calldata-parameters */\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 error NotFromEntryPoint(address msgSender, address entity, address entryPoint);\n\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, NotFromEntryPoint(msg.sender, address(this), 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, NotFromEntryPoint(msg.sender, address(this), 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" + "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 virtual 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 virtual 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 virtual view returns (uint256) {\n return deposits[account].deposit;\n }\n\n receive() external payable {\n depositTo(msg.sender);\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 virtual 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 virtual 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 virtual payable {\n DepositInfo storage info = deposits[msg.sender];\n require(unstakeDelaySec > 0, InvalidUnstakeDelay(unstakeDelaySec, info.unstakeDelaySec));\n require(\n unstakeDelaySec >= info.unstakeDelaySec,\n InvalidUnstakeDelay(unstakeDelaySec, info.unstakeDelaySec)\n );\n uint256 stake = info.stake + msg.value;\n require(stake > 0, InvalidStake(msg.value, info.stake));\n require(stake <= type(uint112).max, InvalidStake(msg.value, info.stake));\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 virtual {\n DepositInfo storage info = deposits[msg.sender];\n require(info.unstakeDelaySec != 0, NotStaked(info.stake, info.unstakeDelaySec, info.staked));\n require(info.staked, NotStaked(info.stake, info.unstakeDelaySec, info.staked));\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 virtual {\n DepositInfo storage info = deposits[msg.sender];\n uint256 stake = info.stake;\n require(stake > 0, NotStaked(info.stake, info.unstakeDelaySec, info.staked));\n require(info.withdrawTime > 0, StakeNotUnlocked(info.withdrawTime, block.timestamp));\n require(\n info.withdrawTime <= block.timestamp,\n WithdrawalNotDue(info.withdrawTime, block.timestamp)\n );\n info.unstakeDelaySec = 0;\n info.withdrawTime = 0;\n info.stake = 0;\n emit StakeWithdrawn(msg.sender, withdrawAddress, stake);\n (bool success, bytes memory ret) = withdrawAddress.call{value: stake}(\"\");\n require(success, StakeWithdrawalFailed(msg.sender, withdrawAddress, stake, ret));\n }\n\n /// @inheritdoc IStakeManager\n function withdrawTo(\n address payable withdrawAddress,\n uint256 withdrawAmount\n ) external virtual {\n DepositInfo storage info = deposits[msg.sender];\n uint256 currentDeposit = info.deposit;\n require(withdrawAmount <= currentDeposit, InsufficientDeposit(currentDeposit, withdrawAmount));\n info.deposit = currentDeposit - withdrawAmount;\n emit Withdrawn(msg.sender, withdrawAddress, withdrawAmount);\n (bool success, bytes memory ret) = withdrawAddress.call{value: withdrawAmount}(\"\");\n require(success, DepositWithdrawalFailed(msg.sender, withdrawAddress, withdrawAmount, ret));\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" + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.28;\n\n/* solhint-disable no-inline-assembly */\n\nimport \"../interfaces/PackedUserOperation.sol\";\nimport \"./Helpers.sol\";\n\n/**\n * Utility functions helpful when working with UserOperation structs.\n */\nlibrary UserOperationLib {\n\n error InvalidPaymasterSignatureLength(uint256 dataLength, uint256 pmSignatureLength);\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 uint256 constant internal PAYMASTER_SIG_MAGIC_LEN = 8;\n uint256 constant internal PAYMASTER_SUFFIX_LEN = PAYMASTER_SIG_MAGIC_LEN + 2; // suffix length (signature length + magic)\n bytes8 constant internal PAYMASTER_SIG_MAGIC = 0x22e325a297439656; // keccak(\"PaymasterSignature\")[:8]\n uint256 constant internal MIN_PAYMASTER_DATA_WITH_SUFFIX_LEN = PAYMASTER_DATA_OFFSET + PAYMASTER_SUFFIX_LEN; // minimum length of paymasterData that can contain a paymaster signature.\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 // solhint-disable-next-line gas-small-strings\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 = paymasterDataKeccak(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 * return the length of the paymaster signature appended in paymasterAndData.\n * return 0 if no signature.\n * note that this signature is not part of the userOpHash, and thus not signed by the user.\n */\n function getPaymasterSignatureLength(\n bytes calldata paymasterAndData\n ) internal pure returns (uint256 paymasterSignatureLength) {\n unchecked {\n uint256 dataLength = paymasterAndData.length;\n if (dataLength < MIN_PAYMASTER_DATA_WITH_SUFFIX_LEN) {\n return 0;\n }\n bytes8 suffix8 = bytes8(paymasterAndData[dataLength - PAYMASTER_SIG_MAGIC_LEN : dataLength]);\n if (suffix8 != PAYMASTER_SIG_MAGIC) {\n return 0;\n }\n uint256 pmSignatureLength = uint16(bytes2(paymasterAndData[dataLength - PAYMASTER_SUFFIX_LEN :]));\n\n if (pmSignatureLength > dataLength - MIN_PAYMASTER_DATA_WITH_SUFFIX_LEN) {\n // paymasterSignature cannot extend before the paymasterData\n revert InvalidPaymasterSignatureLength(dataLength, pmSignatureLength);\n }\n return pmSignatureLength;\n }\n }\n\n /**\n * return the paymasterData that is signed by the user's signature\n * this data excludes the paymaster signature appended at the end of paymasterAndData\n */\n function getSignedPaymasterData(\n bytes calldata paymasterAndData\n ) internal pure returns (bytes calldata signedPaymasterData) {\n uint256 sigLen = getPaymasterSignatureLength(paymasterAndData);\n uint256 paymasterDataLen = paymasterAndData.length;\n if (sigLen != 0) {\n paymasterDataLen -= (sigLen + PAYMASTER_SUFFIX_LEN);\n }\n return paymasterAndData[PAYMASTER_DATA_OFFSET : paymasterDataLen];\n }\n\n /**\n * decodes dynamic signature appended to paymasterAndData\n * note that this signature is not part of the userOpHash, and thus not signed by the user.\n * @param paymasterAndData - The paymasterAndData field of the user operation\n * @return pmSig the paymaster-specific signature (may be empty)\n */\n function getPaymasterSignature(bytes calldata paymasterAndData\n ) internal pure returns (bytes calldata pmSig) {\n uint256 len = getPaymasterSignatureLength(paymasterAndData);\n return getPaymasterSignatureWithLength(paymasterAndData, len);\n }\n\n /**\n * decodes dynamic signature appended to paymasterAndData\n * Assumes the length field is valid, and was obtained from getPaymasterSignatureLength\n * @param paymasterAndData - The paymasterAndData field of the user operation\n * @param paymasterSignatureLength - length of the signature (as returned by getPaymasterSignatureLength)\n * @return pmSig the paymaster-specific signature (may be empty)\n */\n function getPaymasterSignatureWithLength(\n bytes calldata paymasterAndData, uint256 paymasterSignatureLength\n ) internal pure returns (bytes calldata pmSig) {\n if (paymasterSignatureLength == 0) {\n return paymasterAndData[0 : 0];\n }\n uint256 dataLen = paymasterAndData.length;\n unchecked {\n uint256 pmSigEnd = dataLen - PAYMASTER_SUFFIX_LEN;\n uint256 pmSigBegin = pmSigEnd - paymasterSignatureLength;\n return paymasterAndData[pmSigBegin : pmSigEnd];\n }\n }\n\n /**\n * encode the paymaster signature as suffix to append to paymasterAndData\n * This method is a reference for off-chain encoding of paymaster signature.\n */\n function encodePaymasterSignature(bytes calldata paymasterSignature) internal pure returns (bytes memory) {\n uint256 len = paymasterSignature.length;\n if (len == 0) {\n return \"\";\n }\n\n return abi.encodePacked(\n paymasterSignature,\n uint16(len),\n PAYMASTER_SIG_MAGIC\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" @@ -74,7 +68,7 @@ "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" + "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 * Account \"sender\" already exists and the 'initCode' was ignored.\n * @param userOpHash - The current userOp. UserOperationEvent will follow.\n * @param sender - The account that was supposed to be deployed.\n * @param unusedFactory - The factory contract that was not used but was specified in the 'initCode'.\n */\n event IgnoredInitCode(\n bytes32 indexed userOpHash,\n address indexed sender,\n address unusedFactory\n );\n\n /**\n * Account \"sender\" is an EIP-7702 account that was initialized during this UserOperation.\n * @param userOpHash - The current userOp. UserOperationEvent will follow.\n * @param sender - The account that was supposed to be deployed.\n */\n event EIP7702AccountInitialized(\n bytes32 indexed userOpHash,\n address indexed sender,\n address indexed delegate\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 error InvalidBeneficiary(address beneficiary);\n error FailedSendToBeneficiary(address beneficiary, uint256 amount, bytes revertData);\n error InternalFunction();\n error InvalidPaymasterData(uint256 paymasterAndDataLength);\n error InvalidPaymaster(address paymaster);\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 * Allows the AA-aware contracts to query the hash of the currently running UserOperation.\n * @return hash - the hash of the currently running UserOperation, or 0 if none.\n */\n function getCurrentUserOpHash() 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" @@ -86,10 +80,10 @@ "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" + "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 error InvalidUnstakeDelay(uint256 newUnstakeDelaySec, uint256 currentUnstakeDelaySec);\n error InvalidStake(uint256 msgValue, uint256 currentStake);\n error NotStaked(uint256 currentStake, uint256 unstakeDelaySec, bool staked);\n error InsufficientDeposit(uint256 currentDeposit, uint256 withdrawAmount);\n error StakeNotUnlocked(uint256 withdrawTime, uint256 blockTimestamp);\n error WithdrawalNotDue(uint256 withdrawTime, uint256 blockTimestamp);\n error StakeWithdrawalFailed(address account, address withdrawAddress, uint256 amount, bytes revertReason);\n error DepositWithdrawalFailed(address account, address withdrawAddress, uint256 amount, bytes revertReason);\n\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" + "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 *\n *\n * Field layout (enforced on-chain by EntryPoint):\n * - sender: must already be deployed, or be the address that `initCode` will deploy; for EIP-7702 onboarding, `initCode = 0x7702 || optionalPayload`\n * and `sender.code` must begin `0xef0100 || delegate`.\n * - nonce = uint192(key) || uint64(sequence); EntryPoint tracks sequential values of `sequence` separately for each `key` value.\n * - initCode:\n * * non-7702: `initCode = factory(20) || factoryCalldata`; the factory must return `sender` and deploy code.\n * * 7702: `0x7702` (magic prefix), optionally padded to 20 bytes and followed by `initizlizationCode`. This optional payload is executed on `sender` to finalise delegate setup.\n * - callData: executed verbatim; if it starts with `IAccountExecute.executeUserOp.selector` (0x8dd7712f), EntryPoint wraps and forwards `(userOp, userOpHash)`.\n * - accountGasLimits =`uint128(verificationGasLimit) || uint128(callGasLimit)`\n * - gasFees = `uint128(maxPriorityFeePerGas) || uint128(maxFeePerGas)`\n * - paymasterAndData (if non-empty) = `paymaster(20) || verificationGasLimit(16) || postOpGasLimit(16) || paymasterData`\n * * an optional paymasterSignature may be added by appending:\n * `paymasterSignature || uint16(paymasterSignature.length) || PAYMASTER_SIG_MAGIC (0x22e325a297439656)`\n * - signature: Used by the account to validate the UserOperation against the `userOpHash`.\n * The hash covers all UserOperation fields, except `signature` and `paymasterSignature`\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" diff --git a/dependencies/eth-infinitism-account-abstraction-0.9.0/deployments/ethereum/solcInputs/e0f62075d3b5c33c869a8675a95268ec.json b/dependencies/eth-infinitism-account-abstraction-0.9.0/deployments/ethereum/solcInputs/e0f62075d3b5c33c869a8675a95268ec.json new file mode 100644 index 0000000..4312373 --- /dev/null +++ b/dependencies/eth-infinitism-account-abstraction-0.9.0/deployments/ethereum/solcInputs/e0f62075d3b5c33c869a8675a95268ec.json @@ -0,0 +1,319 @@ +{ + "language": "Solidity", + "sources": { + "@openzeppelin/contracts/access/Ownable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.0.0) (access/Ownable.sol)\n\npragma solidity ^0.8.20;\n\nimport {Context} from \"../utils/Context.sol\";\n\n/**\n * @dev Contract module which provides a basic access control mechanism, where\n * there is an account (an owner) that can be granted exclusive access to\n * specific functions.\n *\n * The initial owner is set to the address provided by the deployer. This can\n * later be changed with {transferOwnership}.\n *\n * This module is used through inheritance. It will make available the modifier\n * `onlyOwner`, which can be applied to your functions to restrict their use to\n * the owner.\n */\nabstract contract Ownable is Context {\n address private _owner;\n\n /**\n * @dev The caller account is not authorized to perform an operation.\n */\n error OwnableUnauthorizedAccount(address account);\n\n /**\n * @dev The owner is not a valid owner account. (eg. `address(0)`)\n */\n error OwnableInvalidOwner(address owner);\n\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\n\n /**\n * @dev Initializes the contract setting the address provided by the deployer as the initial owner.\n */\n constructor(address initialOwner) {\n if (initialOwner == address(0)) {\n revert OwnableInvalidOwner(address(0));\n }\n _transferOwnership(initialOwner);\n }\n\n /**\n * @dev Throws if called by any account other than the owner.\n */\n modifier onlyOwner() {\n _checkOwner();\n _;\n }\n\n /**\n * @dev Returns the address of the current owner.\n */\n function owner() public view virtual returns (address) {\n return _owner;\n }\n\n /**\n * @dev Throws if the sender is not the owner.\n */\n function _checkOwner() internal view virtual {\n if (owner() != _msgSender()) {\n revert OwnableUnauthorizedAccount(_msgSender());\n }\n }\n\n /**\n * @dev Leaves the contract without owner. It will not be possible to call\n * `onlyOwner` functions. Can only be called by the current owner.\n *\n * NOTE: Renouncing ownership will leave the contract without an owner,\n * thereby disabling any functionality that is only available to the owner.\n */\n function renounceOwnership() public virtual onlyOwner {\n _transferOwnership(address(0));\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Can only be called by the current owner.\n */\n function transferOwnership(address newOwner) public virtual onlyOwner {\n if (newOwner == address(0)) {\n revert OwnableInvalidOwner(address(0));\n }\n _transferOwnership(newOwner);\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Internal function without access restriction.\n */\n function _transferOwnership(address newOwner) internal virtual {\n address oldOwner = _owner;\n _owner = newOwner;\n emit OwnershipTransferred(oldOwner, newOwner);\n }\n}\n" + }, + "@openzeppelin/contracts/access/Ownable2Step.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.1.0) (access/Ownable2Step.sol)\n\npragma solidity ^0.8.20;\n\nimport {Ownable} from \"./Ownable.sol\";\n\n/**\n * @dev Contract module which provides access control mechanism, where\n * there is an account (an owner) that can be granted exclusive access to\n * specific functions.\n *\n * This extension of the {Ownable} contract includes a two-step mechanism to transfer\n * ownership, where the new owner must call {acceptOwnership} in order to replace the\n * old one. This can help prevent common mistakes, such as transfers of ownership to\n * incorrect accounts, or to contracts that are unable to interact with the\n * permission system.\n *\n * The initial owner is specified at deployment time in the constructor for `Ownable`. This\n * can later be changed with {transferOwnership} and {acceptOwnership}.\n *\n * This module is used through inheritance. It will make available all functions\n * from parent (Ownable).\n */\nabstract contract Ownable2Step is Ownable {\n address private _pendingOwner;\n\n event OwnershipTransferStarted(address indexed previousOwner, address indexed newOwner);\n\n /**\n * @dev Returns the address of the pending owner.\n */\n function pendingOwner() public view virtual returns (address) {\n return _pendingOwner;\n }\n\n /**\n * @dev Starts the ownership transfer of the contract to a new account. Replaces the pending transfer if there is one.\n * Can only be called by the current owner.\n *\n * Setting `newOwner` to the zero address is allowed; this can be used to cancel an initiated ownership transfer.\n */\n function transferOwnership(address newOwner) public virtual override onlyOwner {\n _pendingOwner = newOwner;\n emit OwnershipTransferStarted(owner(), newOwner);\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`) and deletes any pending owner.\n * Internal function without access restriction.\n */\n function _transferOwnership(address newOwner) internal virtual override {\n delete _pendingOwner;\n super._transferOwnership(newOwner);\n }\n\n /**\n * @dev The new owner accepts the ownership transfer.\n */\n function acceptOwnership() public virtual {\n address sender = _msgSender();\n if (pendingOwner() != sender) {\n revert OwnableUnauthorizedAccount(sender);\n }\n _transferOwnership(sender);\n }\n}\n" + }, + "@openzeppelin/contracts/interfaces/draft-IERC1822.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.1.0) (interfaces/draft-IERC1822.sol)\n\npragma solidity ^0.8.20;\n\n/**\n * @dev ERC-1822: Universal Upgradeable Proxy Standard (UUPS) documents a method for upgradeability through a simplified\n * proxy whose upgrades are fully controlled by the current implementation.\n */\ninterface IERC1822Proxiable {\n /**\n * @dev Returns the storage slot that the proxiable contract assumes is being used to store the implementation\n * address.\n *\n * IMPORTANT: A proxy pointing at a proxiable contract should not be considered proxiable itself, because this risks\n * bricking a proxy that upgrades to it, by delegating to itself until out of gas. Thus it is critical that this\n * function revert if invoked through a proxy.\n */\n function proxiableUUID() external view returns (bytes32);\n}\n" + }, + "@openzeppelin/contracts/interfaces/draft-IERC6093.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.1.0) (interfaces/draft-IERC6093.sol)\npragma solidity ^0.8.20;\n\n/**\n * @dev Standard ERC-20 Errors\n * Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC-20 tokens.\n */\ninterface IERC20Errors {\n /**\n * @dev Indicates an error related to the current `balance` of a `sender`. Used in transfers.\n * @param sender Address whose tokens are being transferred.\n * @param balance Current balance for the interacting account.\n * @param needed Minimum amount required to perform a transfer.\n */\n error ERC20InsufficientBalance(address sender, uint256 balance, uint256 needed);\n\n /**\n * @dev Indicates a failure with the token `sender`. Used in transfers.\n * @param sender Address whose tokens are being transferred.\n */\n error ERC20InvalidSender(address sender);\n\n /**\n * @dev Indicates a failure with the token `receiver`. Used in transfers.\n * @param receiver Address to which tokens are being transferred.\n */\n error ERC20InvalidReceiver(address receiver);\n\n /**\n * @dev Indicates a failure with the `spender`’s `allowance`. Used in transfers.\n * @param spender Address that may be allowed to operate on tokens without being their owner.\n * @param allowance Amount of tokens a `spender` is allowed to operate with.\n * @param needed Minimum amount required to perform a transfer.\n */\n error ERC20InsufficientAllowance(address spender, uint256 allowance, uint256 needed);\n\n /**\n * @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals.\n * @param approver Address initiating an approval operation.\n */\n error ERC20InvalidApprover(address approver);\n\n /**\n * @dev Indicates a failure with the `spender` to be approved. Used in approvals.\n * @param spender Address that may be allowed to operate on tokens without being their owner.\n */\n error ERC20InvalidSpender(address spender);\n}\n\n/**\n * @dev Standard ERC-721 Errors\n * Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC-721 tokens.\n */\ninterface IERC721Errors {\n /**\n * @dev Indicates that an address can't be an owner. For example, `address(0)` is a forbidden owner in ERC-20.\n * Used in balance queries.\n * @param owner Address of the current owner of a token.\n */\n error ERC721InvalidOwner(address owner);\n\n /**\n * @dev Indicates a `tokenId` whose `owner` is the zero address.\n * @param tokenId Identifier number of a token.\n */\n error ERC721NonexistentToken(uint256 tokenId);\n\n /**\n * @dev Indicates an error related to the ownership over a particular token. Used in transfers.\n * @param sender Address whose tokens are being transferred.\n * @param tokenId Identifier number of a token.\n * @param owner Address of the current owner of a token.\n */\n error ERC721IncorrectOwner(address sender, uint256 tokenId, address owner);\n\n /**\n * @dev Indicates a failure with the token `sender`. Used in transfers.\n * @param sender Address whose tokens are being transferred.\n */\n error ERC721InvalidSender(address sender);\n\n /**\n * @dev Indicates a failure with the token `receiver`. Used in transfers.\n * @param receiver Address to which tokens are being transferred.\n */\n error ERC721InvalidReceiver(address receiver);\n\n /**\n * @dev Indicates a failure with the `operator`’s approval. Used in transfers.\n * @param operator Address that may be allowed to operate on tokens without being their owner.\n * @param tokenId Identifier number of a token.\n */\n error ERC721InsufficientApproval(address operator, uint256 tokenId);\n\n /**\n * @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals.\n * @param approver Address initiating an approval operation.\n */\n error ERC721InvalidApprover(address approver);\n\n /**\n * @dev Indicates a failure with the `operator` to be approved. Used in approvals.\n * @param operator Address that may be allowed to operate on tokens without being their owner.\n */\n error ERC721InvalidOperator(address operator);\n}\n\n/**\n * @dev Standard ERC-1155 Errors\n * Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC-1155 tokens.\n */\ninterface IERC1155Errors {\n /**\n * @dev Indicates an error related to the current `balance` of a `sender`. Used in transfers.\n * @param sender Address whose tokens are being transferred.\n * @param balance Current balance for the interacting account.\n * @param needed Minimum amount required to perform a transfer.\n * @param tokenId Identifier number of a token.\n */\n error ERC1155InsufficientBalance(address sender, uint256 balance, uint256 needed, uint256 tokenId);\n\n /**\n * @dev Indicates a failure with the token `sender`. Used in transfers.\n * @param sender Address whose tokens are being transferred.\n */\n error ERC1155InvalidSender(address sender);\n\n /**\n * @dev Indicates a failure with the token `receiver`. Used in transfers.\n * @param receiver Address to which tokens are being transferred.\n */\n error ERC1155InvalidReceiver(address receiver);\n\n /**\n * @dev Indicates a failure with the `operator`’s approval. Used in transfers.\n * @param operator Address that may be allowed to operate on tokens without being their owner.\n * @param owner Address of the current owner of a token.\n */\n error ERC1155MissingApprovalForAll(address operator, address owner);\n\n /**\n * @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals.\n * @param approver Address initiating an approval operation.\n */\n error ERC1155InvalidApprover(address approver);\n\n /**\n * @dev Indicates a failure with the `operator` to be approved. Used in approvals.\n * @param operator Address that may be allowed to operate on tokens without being their owner.\n */\n error ERC1155InvalidOperator(address operator);\n\n /**\n * @dev Indicates an array length mismatch between ids and values in a safeBatchTransferFrom operation.\n * Used in batch transfers.\n * @param idsLength Length of the array of token identifiers\n * @param valuesLength Length of the array of token amounts\n */\n error ERC1155InvalidArrayLength(uint256 idsLength, uint256 valuesLength);\n}\n" + }, + "@openzeppelin/contracts/interfaces/IERC1271.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.1.0) (interfaces/IERC1271.sol)\n\npragma solidity ^0.8.20;\n\n/**\n * @dev Interface of the ERC-1271 standard signature validation method for\n * contracts as defined in https://eips.ethereum.org/EIPS/eip-1271[ERC-1271].\n */\ninterface IERC1271 {\n /**\n * @dev Should return whether the signature provided is valid for the provided data\n * @param hash Hash of the data to be signed\n * @param signature Signature byte array associated with _data\n */\n function isValidSignature(bytes32 hash, bytes memory signature) external view returns (bytes4 magicValue);\n}\n" + }, + "@openzeppelin/contracts/interfaces/IERC1967.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.0.0) (interfaces/IERC1967.sol)\n\npragma solidity ^0.8.20;\n\n/**\n * @dev ERC-1967: Proxy Storage Slots. This interface contains the events defined in the ERC.\n */\ninterface IERC1967 {\n /**\n * @dev Emitted when the implementation is upgraded.\n */\n event Upgraded(address indexed implementation);\n\n /**\n * @dev Emitted when the admin account has changed.\n */\n event AdminChanged(address previousAdmin, address newAdmin);\n\n /**\n * @dev Emitted when the beacon is changed.\n */\n event BeaconUpgraded(address indexed beacon);\n}\n" + }, + "@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/proxy/beacon/IBeacon.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.0.0) (proxy/beacon/IBeacon.sol)\n\npragma solidity ^0.8.20;\n\n/**\n * @dev This is the interface that {BeaconProxy} expects of its beacon.\n */\ninterface IBeacon {\n /**\n * @dev Must return an address that can be used as a delegate call target.\n *\n * {UpgradeableBeacon} will check that this address is a contract.\n */\n function implementation() external view returns (address);\n}\n" + }, + "@openzeppelin/contracts/proxy/ERC1967/ERC1967Proxy.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.1.0) (proxy/ERC1967/ERC1967Proxy.sol)\n\npragma solidity ^0.8.20;\n\nimport {Proxy} from \"../Proxy.sol\";\nimport {ERC1967Utils} from \"./ERC1967Utils.sol\";\n\n/**\n * @dev This contract implements an upgradeable proxy. It is upgradeable because calls are delegated to an\n * implementation address that can be changed. This address is stored in storage in the location specified by\n * https://eips.ethereum.org/EIPS/eip-1967[ERC-1967], so that it doesn't conflict with the storage layout of the\n * implementation behind the proxy.\n */\ncontract ERC1967Proxy is Proxy {\n /**\n * @dev Initializes the upgradeable proxy with an initial implementation specified by `implementation`.\n *\n * If `_data` is nonempty, it's used as data in a delegate call to `implementation`. This will typically be an\n * encoded function call, and allows initializing the storage of the proxy like a Solidity constructor.\n *\n * Requirements:\n *\n * - If `data` is empty, `msg.value` must be zero.\n */\n constructor(address implementation, bytes memory _data) payable {\n ERC1967Utils.upgradeToAndCall(implementation, _data);\n }\n\n /**\n * @dev Returns the current implementation address.\n *\n * TIP: To get this value clients can read directly from the storage slot shown below (specified by ERC-1967) using\n * the https://eth.wiki/json-rpc/API#eth_getstorageat[`eth_getStorageAt`] RPC call.\n * `0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc`\n */\n function _implementation() internal view virtual override returns (address) {\n return ERC1967Utils.getImplementation();\n }\n}\n" + }, + "@openzeppelin/contracts/proxy/ERC1967/ERC1967Utils.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.1.0) (proxy/ERC1967/ERC1967Utils.sol)\n\npragma solidity ^0.8.21;\n\nimport {IBeacon} from \"../beacon/IBeacon.sol\";\nimport {IERC1967} from \"../../interfaces/IERC1967.sol\";\nimport {Address} from \"../../utils/Address.sol\";\nimport {StorageSlot} from \"../../utils/StorageSlot.sol\";\n\n/**\n * @dev This library provides getters and event emitting update functions for\n * https://eips.ethereum.org/EIPS/eip-1967[ERC-1967] slots.\n */\nlibrary ERC1967Utils {\n /**\n * @dev Storage slot with the address of the current implementation.\n * This is the keccak-256 hash of \"eip1967.proxy.implementation\" subtracted by 1.\n */\n // solhint-disable-next-line private-vars-leading-underscore\n bytes32 internal constant IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;\n\n /**\n * @dev The `implementation` of the proxy is invalid.\n */\n error ERC1967InvalidImplementation(address implementation);\n\n /**\n * @dev The `admin` of the proxy is invalid.\n */\n error ERC1967InvalidAdmin(address admin);\n\n /**\n * @dev The `beacon` of the proxy is invalid.\n */\n error ERC1967InvalidBeacon(address beacon);\n\n /**\n * @dev An upgrade function sees `msg.value > 0` that may be lost.\n */\n error ERC1967NonPayable();\n\n /**\n * @dev Returns the current implementation address.\n */\n function getImplementation() internal view returns (address) {\n return StorageSlot.getAddressSlot(IMPLEMENTATION_SLOT).value;\n }\n\n /**\n * @dev Stores a new address in the ERC-1967 implementation slot.\n */\n function _setImplementation(address newImplementation) private {\n if (newImplementation.code.length == 0) {\n revert ERC1967InvalidImplementation(newImplementation);\n }\n StorageSlot.getAddressSlot(IMPLEMENTATION_SLOT).value = newImplementation;\n }\n\n /**\n * @dev Performs implementation upgrade with additional setup call if data is nonempty.\n * This function is payable only if the setup call is performed, otherwise `msg.value` is rejected\n * to avoid stuck value in the contract.\n *\n * Emits an {IERC1967-Upgraded} event.\n */\n function upgradeToAndCall(address newImplementation, bytes memory data) internal {\n _setImplementation(newImplementation);\n emit IERC1967.Upgraded(newImplementation);\n\n if (data.length > 0) {\n Address.functionDelegateCall(newImplementation, data);\n } else {\n _checkNonPayable();\n }\n }\n\n /**\n * @dev Storage slot with the admin of the contract.\n * This is the keccak-256 hash of \"eip1967.proxy.admin\" subtracted by 1.\n */\n // solhint-disable-next-line private-vars-leading-underscore\n bytes32 internal constant ADMIN_SLOT = 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103;\n\n /**\n * @dev Returns the current admin.\n *\n * TIP: To get this value clients can read directly from the storage slot shown below (specified by ERC-1967) using\n * the https://eth.wiki/json-rpc/API#eth_getstorageat[`eth_getStorageAt`] RPC call.\n * `0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103`\n */\n function getAdmin() internal view returns (address) {\n return StorageSlot.getAddressSlot(ADMIN_SLOT).value;\n }\n\n /**\n * @dev Stores a new address in the ERC-1967 admin slot.\n */\n function _setAdmin(address newAdmin) private {\n if (newAdmin == address(0)) {\n revert ERC1967InvalidAdmin(address(0));\n }\n StorageSlot.getAddressSlot(ADMIN_SLOT).value = newAdmin;\n }\n\n /**\n * @dev Changes the admin of the proxy.\n *\n * Emits an {IERC1967-AdminChanged} event.\n */\n function changeAdmin(address newAdmin) internal {\n emit IERC1967.AdminChanged(getAdmin(), newAdmin);\n _setAdmin(newAdmin);\n }\n\n /**\n * @dev The storage slot of the UpgradeableBeacon contract which defines the implementation for this proxy.\n * This is the keccak-256 hash of \"eip1967.proxy.beacon\" subtracted by 1.\n */\n // solhint-disable-next-line private-vars-leading-underscore\n bytes32 internal constant BEACON_SLOT = 0xa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d50;\n\n /**\n * @dev Returns the current beacon.\n */\n function getBeacon() internal view returns (address) {\n return StorageSlot.getAddressSlot(BEACON_SLOT).value;\n }\n\n /**\n * @dev Stores a new beacon in the ERC-1967 beacon slot.\n */\n function _setBeacon(address newBeacon) private {\n if (newBeacon.code.length == 0) {\n revert ERC1967InvalidBeacon(newBeacon);\n }\n\n StorageSlot.getAddressSlot(BEACON_SLOT).value = newBeacon;\n\n address beaconImplementation = IBeacon(newBeacon).implementation();\n if (beaconImplementation.code.length == 0) {\n revert ERC1967InvalidImplementation(beaconImplementation);\n }\n }\n\n /**\n * @dev Change the beacon and trigger a setup call if data is nonempty.\n * This function is payable only if the setup call is performed, otherwise `msg.value` is rejected\n * to avoid stuck value in the contract.\n *\n * Emits an {IERC1967-BeaconUpgraded} event.\n *\n * CAUTION: Invoking this function has no effect on an instance of {BeaconProxy} since v5, since\n * it uses an immutable beacon without looking at the value of the ERC-1967 beacon slot for\n * efficiency.\n */\n function upgradeBeaconToAndCall(address newBeacon, bytes memory data) internal {\n _setBeacon(newBeacon);\n emit IERC1967.BeaconUpgraded(newBeacon);\n\n if (data.length > 0) {\n Address.functionDelegateCall(IBeacon(newBeacon).implementation(), data);\n } else {\n _checkNonPayable();\n }\n }\n\n /**\n * @dev Reverts if `msg.value` is not zero. It can be used to avoid `msg.value` stuck in the contract\n * if an upgrade doesn't perform an initialization call.\n */\n function _checkNonPayable() private {\n if (msg.value > 0) {\n revert ERC1967NonPayable();\n }\n }\n}\n" + }, + "@openzeppelin/contracts/proxy/Proxy.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.0.0) (proxy/Proxy.sol)\n\npragma solidity ^0.8.20;\n\n/**\n * @dev This abstract contract provides a fallback function that delegates all calls to another contract using the EVM\n * instruction `delegatecall`. We refer to the second contract as the _implementation_ behind the proxy, and it has to\n * be specified by overriding the virtual {_implementation} function.\n *\n * Additionally, delegation to the implementation can be triggered manually through the {_fallback} function, or to a\n * different contract through the {_delegate} function.\n *\n * The success and return data of the delegated call will be returned back to the caller of the proxy.\n */\nabstract contract Proxy {\n /**\n * @dev Delegates the current call to `implementation`.\n *\n * This function does not return to its internal call site, it will return directly to the external caller.\n */\n function _delegate(address implementation) internal virtual {\n assembly {\n // Copy msg.data. We take full control of memory in this inline assembly\n // block because it will not return to Solidity code. We overwrite the\n // Solidity scratch pad at memory position 0.\n calldatacopy(0, 0, calldatasize())\n\n // Call the implementation.\n // out and outsize are 0 because we don't know the size yet.\n let result := delegatecall(gas(), implementation, 0, calldatasize(), 0, 0)\n\n // Copy the returned data.\n returndatacopy(0, 0, returndatasize())\n\n switch result\n // delegatecall returns 0 on error.\n case 0 {\n revert(0, returndatasize())\n }\n default {\n return(0, returndatasize())\n }\n }\n }\n\n /**\n * @dev This is a virtual function that should be overridden so it returns the address to which the fallback\n * function and {_fallback} should delegate.\n */\n function _implementation() internal view virtual returns (address);\n\n /**\n * @dev Delegates the current call to the address returned by `_implementation()`.\n *\n * This function does not return to its internal call site, it will return directly to the external caller.\n */\n function _fallback() internal virtual {\n _delegate(_implementation());\n }\n\n /**\n * @dev Fallback function that delegates calls to the address returned by `_implementation()`. Will run if no other\n * function in the contract matches the call data.\n */\n fallback() external payable virtual {\n _fallback();\n }\n}\n" + }, + "@openzeppelin/contracts/proxy/utils/Initializable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.0.0) (proxy/utils/Initializable.sol)\n\npragma solidity ^0.8.20;\n\n/**\n * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed\n * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an\n * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer\n * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.\n *\n * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be\n * reused. This mechanism prevents re-execution of each \"step\" but allows the creation of new initialization steps in\n * case an upgrade adds a module that needs to be initialized.\n *\n * For example:\n *\n * [.hljs-theme-light.nopadding]\n * ```solidity\n * contract MyToken is ERC20Upgradeable {\n * function initialize() initializer public {\n * __ERC20_init(\"MyToken\", \"MTK\");\n * }\n * }\n *\n * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable {\n * function initializeV2() reinitializer(2) public {\n * __ERC20Permit_init(\"MyToken\");\n * }\n * }\n * ```\n *\n * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as\n * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}.\n *\n * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure\n * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.\n *\n * [CAUTION]\n * ====\n * Avoid leaving a contract uninitialized.\n *\n * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation\n * contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke\n * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed:\n *\n * [.hljs-theme-light.nopadding]\n * ```\n * /// @custom:oz-upgrades-unsafe-allow constructor\n * constructor() {\n * _disableInitializers();\n * }\n * ```\n * ====\n */\nabstract contract Initializable {\n /**\n * @dev Storage of the initializable contract.\n *\n * It's implemented on a custom ERC-7201 namespace to reduce the risk of storage collisions\n * when using with upgradeable contracts.\n *\n * @custom:storage-location erc7201:openzeppelin.storage.Initializable\n */\n struct InitializableStorage {\n /**\n * @dev Indicates that the contract has been initialized.\n */\n uint64 _initialized;\n /**\n * @dev Indicates that the contract is in the process of being initialized.\n */\n bool _initializing;\n }\n\n // keccak256(abi.encode(uint256(keccak256(\"openzeppelin.storage.Initializable\")) - 1)) & ~bytes32(uint256(0xff))\n bytes32 private constant INITIALIZABLE_STORAGE = 0xf0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00;\n\n /**\n * @dev The contract is already initialized.\n */\n error InvalidInitialization();\n\n /**\n * @dev The contract is not initializing.\n */\n error NotInitializing();\n\n /**\n * @dev Triggered when the contract has been initialized or reinitialized.\n */\n event Initialized(uint64 version);\n\n /**\n * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope,\n * `onlyInitializing` functions can be used to initialize parent contracts.\n *\n * Similar to `reinitializer(1)`, except that in the context of a constructor an `initializer` may be invoked any\n * number of times. This behavior in the constructor can be useful during testing and is not expected to be used in\n * production.\n *\n * Emits an {Initialized} event.\n */\n modifier initializer() {\n // solhint-disable-next-line var-name-mixedcase\n InitializableStorage storage $ = _getInitializableStorage();\n\n // Cache values to avoid duplicated sloads\n bool isTopLevelCall = !$._initializing;\n uint64 initialized = $._initialized;\n\n // Allowed calls:\n // - initialSetup: the contract is not in the initializing state and no previous version was\n // initialized\n // - construction: the contract is initialized at version 1 (no reininitialization) and the\n // current contract is just being deployed\n bool initialSetup = initialized == 0 && isTopLevelCall;\n bool construction = initialized == 1 && address(this).code.length == 0;\n\n if (!initialSetup && !construction) {\n revert InvalidInitialization();\n }\n $._initialized = 1;\n if (isTopLevelCall) {\n $._initializing = true;\n }\n _;\n if (isTopLevelCall) {\n $._initializing = false;\n emit Initialized(1);\n }\n }\n\n /**\n * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the\n * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be\n * used to initialize parent contracts.\n *\n * A reinitializer may be used after the original initialization step. This is essential to configure modules that\n * are added through upgrades and that require initialization.\n *\n * When `version` is 1, this modifier is similar to `initializer`, except that functions marked with `reinitializer`\n * cannot be nested. If one is invoked in the context of another, execution will revert.\n *\n * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in\n * a contract, executing them in the right order is up to the developer or operator.\n *\n * WARNING: Setting the version to 2**64 - 1 will prevent any future reinitialization.\n *\n * Emits an {Initialized} event.\n */\n modifier reinitializer(uint64 version) {\n // solhint-disable-next-line var-name-mixedcase\n InitializableStorage storage $ = _getInitializableStorage();\n\n if ($._initializing || $._initialized >= version) {\n revert InvalidInitialization();\n }\n $._initialized = version;\n $._initializing = true;\n _;\n $._initializing = false;\n emit Initialized(version);\n }\n\n /**\n * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the\n * {initializer} and {reinitializer} modifiers, directly or indirectly.\n */\n modifier onlyInitializing() {\n _checkInitializing();\n _;\n }\n\n /**\n * @dev Reverts if the contract is not in an initializing state. See {onlyInitializing}.\n */\n function _checkInitializing() internal view virtual {\n if (!_isInitializing()) {\n revert NotInitializing();\n }\n }\n\n /**\n * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call.\n * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized\n * to any version. It is recommended to use this to lock implementation contracts that are designed to be called\n * through proxies.\n *\n * Emits an {Initialized} event the first time it is successfully executed.\n */\n function _disableInitializers() internal virtual {\n // solhint-disable-next-line var-name-mixedcase\n InitializableStorage storage $ = _getInitializableStorage();\n\n if ($._initializing) {\n revert InvalidInitialization();\n }\n if ($._initialized != type(uint64).max) {\n $._initialized = type(uint64).max;\n emit Initialized(type(uint64).max);\n }\n }\n\n /**\n * @dev Returns the highest version that has been initialized. See {reinitializer}.\n */\n function _getInitializedVersion() internal view returns (uint64) {\n return _getInitializableStorage()._initialized;\n }\n\n /**\n * @dev Returns `true` if the contract is currently initializing. See {onlyInitializing}.\n */\n function _isInitializing() internal view returns (bool) {\n return _getInitializableStorage()._initializing;\n }\n\n /**\n * @dev Returns a pointer to the storage namespace.\n */\n // solhint-disable-next-line var-name-mixedcase\n function _getInitializableStorage() private pure returns (InitializableStorage storage $) {\n assembly {\n $.slot := INITIALIZABLE_STORAGE\n }\n }\n}\n" + }, + "@openzeppelin/contracts/proxy/utils/UUPSUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.1.0) (proxy/utils/UUPSUpgradeable.sol)\n\npragma solidity ^0.8.20;\n\nimport {IERC1822Proxiable} from \"../../interfaces/draft-IERC1822.sol\";\nimport {ERC1967Utils} from \"../ERC1967/ERC1967Utils.sol\";\n\n/**\n * @dev An upgradeability mechanism designed for UUPS proxies. The functions included here can perform an upgrade of an\n * {ERC1967Proxy}, when this contract is set as the implementation behind such a proxy.\n *\n * A security mechanism ensures that an upgrade does not turn off upgradeability accidentally, although this risk is\n * reinstated if the upgrade retains upgradeability but removes the security mechanism, e.g. by replacing\n * `UUPSUpgradeable` with a custom implementation of upgrades.\n *\n * The {_authorizeUpgrade} function must be overridden to include access restriction to the upgrade mechanism.\n */\nabstract contract UUPSUpgradeable is IERC1822Proxiable {\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\n address private immutable __self = address(this);\n\n /**\n * @dev The version of the upgrade interface of the contract. If this getter is missing, both `upgradeTo(address)`\n * and `upgradeToAndCall(address,bytes)` are present, and `upgradeTo` must be used if no function should be called,\n * while `upgradeToAndCall` will invoke the `receive` function if the second argument is the empty byte string.\n * If the getter returns `\"5.0.0\"`, only `upgradeToAndCall(address,bytes)` is present, and the second argument must\n * be the empty byte string if no function should be called, making it impossible to invoke the `receive` function\n * during an upgrade.\n */\n string public constant UPGRADE_INTERFACE_VERSION = \"5.0.0\";\n\n /**\n * @dev The call is from an unauthorized context.\n */\n error UUPSUnauthorizedCallContext();\n\n /**\n * @dev The storage `slot` is unsupported as a UUID.\n */\n error UUPSUnsupportedProxiableUUID(bytes32 slot);\n\n /**\n * @dev Check that the execution is being performed through a delegatecall call and that the execution context is\n * a proxy contract with an implementation (as defined in ERC-1967) pointing to self. This should only be the case\n * for UUPS and transparent proxies that are using the current contract as their implementation. Execution of a\n * function through ERC-1167 minimal proxies (clones) would not normally pass this test, but is not guaranteed to\n * fail.\n */\n modifier onlyProxy() {\n _checkProxy();\n _;\n }\n\n /**\n * @dev Check that the execution is not being performed through a delegate call. This allows a function to be\n * callable on the implementing contract but not through proxies.\n */\n modifier notDelegated() {\n _checkNotDelegated();\n _;\n }\n\n /**\n * @dev Implementation of the ERC-1822 {proxiableUUID} function. This returns the storage slot used by the\n * implementation. It is used to validate the implementation's compatibility when performing an upgrade.\n *\n * IMPORTANT: A proxy pointing at a proxiable contract should not be considered proxiable itself, because this risks\n * bricking a proxy that upgrades to it, by delegating to itself until out of gas. Thus it is critical that this\n * function revert if invoked through a proxy. This is guaranteed by the `notDelegated` modifier.\n */\n function proxiableUUID() external view virtual notDelegated returns (bytes32) {\n return ERC1967Utils.IMPLEMENTATION_SLOT;\n }\n\n /**\n * @dev Upgrade the implementation of the proxy to `newImplementation`, and subsequently execute the function call\n * encoded in `data`.\n *\n * Calls {_authorizeUpgrade}.\n *\n * Emits an {Upgraded} event.\n *\n * @custom:oz-upgrades-unsafe-allow-reachable delegatecall\n */\n function upgradeToAndCall(address newImplementation, bytes memory data) public payable virtual onlyProxy {\n _authorizeUpgrade(newImplementation);\n _upgradeToAndCallUUPS(newImplementation, data);\n }\n\n /**\n * @dev Reverts if the execution is not performed via delegatecall or the execution\n * context is not of a proxy with an ERC-1967 compliant implementation pointing to self.\n * See {_onlyProxy}.\n */\n function _checkProxy() internal view virtual {\n if (\n address(this) == __self || // Must be called through delegatecall\n ERC1967Utils.getImplementation() != __self // Must be called through an active proxy\n ) {\n revert UUPSUnauthorizedCallContext();\n }\n }\n\n /**\n * @dev Reverts if the execution is performed via delegatecall.\n * See {notDelegated}.\n */\n function _checkNotDelegated() internal view virtual {\n if (address(this) != __self) {\n // Must not be called through delegatecall\n revert UUPSUnauthorizedCallContext();\n }\n }\n\n /**\n * @dev Function that should revert when `msg.sender` is not authorized to upgrade the contract. Called by\n * {upgradeToAndCall}.\n *\n * Normally, this function will use an xref:access.adoc[access control] modifier such as {Ownable-onlyOwner}.\n *\n * ```solidity\n * function _authorizeUpgrade(address) internal onlyOwner {}\n * ```\n */\n function _authorizeUpgrade(address newImplementation) internal virtual;\n\n /**\n * @dev Performs an implementation upgrade with a security check for UUPS proxies, and additional setup call.\n *\n * As a security check, {proxiableUUID} is invoked in the new implementation, and the return value\n * is expected to be the implementation slot in ERC-1967.\n *\n * Emits an {IERC1967-Upgraded} event.\n */\n function _upgradeToAndCallUUPS(address newImplementation, bytes memory data) private {\n try IERC1822Proxiable(newImplementation).proxiableUUID() returns (bytes32 slot) {\n if (slot != ERC1967Utils.IMPLEMENTATION_SLOT) {\n revert UUPSUnsupportedProxiableUUID(slot);\n }\n ERC1967Utils.upgradeToAndCall(newImplementation, data);\n } catch {\n // The implementation is not UUPS\n revert ERC1967Utils.ERC1967InvalidImplementation(newImplementation);\n }\n }\n}\n" + }, + "@openzeppelin/contracts/token/ERC1155/IERC1155Receiver.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.1.0) (token/ERC1155/IERC1155Receiver.sol)\n\npragma solidity ^0.8.20;\n\nimport {IERC165} from \"../../utils/introspection/IERC165.sol\";\n\n/**\n * @dev Interface that must be implemented by smart contracts in order to receive\n * ERC-1155 token transfers.\n */\ninterface IERC1155Receiver is IERC165 {\n /**\n * @dev Handles the receipt of a single ERC-1155 token type. This function is\n * called at the end of a `safeTransferFrom` after the balance has been updated.\n *\n * NOTE: To accept the transfer, this must return\n * `bytes4(keccak256(\"onERC1155Received(address,address,uint256,uint256,bytes)\"))`\n * (i.e. 0xf23a6e61, or its own function selector).\n *\n * @param operator The address which initiated the transfer (i.e. msg.sender)\n * @param from The address which previously owned the token\n * @param id The ID of the token being transferred\n * @param value The amount of tokens being transferred\n * @param data Additional data with no specified format\n * @return `bytes4(keccak256(\"onERC1155Received(address,address,uint256,uint256,bytes)\"))` if transfer is allowed\n */\n function onERC1155Received(\n address operator,\n address from,\n uint256 id,\n uint256 value,\n bytes calldata data\n ) external returns (bytes4);\n\n /**\n * @dev Handles the receipt of a multiple ERC-1155 token types. This function\n * is called at the end of a `safeBatchTransferFrom` after the balances have\n * been updated.\n *\n * NOTE: To accept the transfer(s), this must return\n * `bytes4(keccak256(\"onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)\"))`\n * (i.e. 0xbc197c81, or its own function selector).\n *\n * @param operator The address which initiated the batch transfer (i.e. msg.sender)\n * @param from The address which previously owned the token\n * @param ids An array containing ids of each token being transferred (order and length must match values array)\n * @param values An array containing amounts of each token being transferred (order and length must match ids array)\n * @param data Additional data with no specified format\n * @return `bytes4(keccak256(\"onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)\"))` if transfer is allowed\n */\n function onERC1155BatchReceived(\n address operator,\n address from,\n uint256[] calldata ids,\n uint256[] calldata values,\n bytes calldata data\n ) external returns (bytes4);\n}\n" + }, + "@openzeppelin/contracts/token/ERC1155/utils/ERC1155Holder.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.1.0) (token/ERC1155/utils/ERC1155Holder.sol)\n\npragma solidity ^0.8.20;\n\nimport {IERC165, ERC165} from \"../../../utils/introspection/ERC165.sol\";\nimport {IERC1155Receiver} from \"../IERC1155Receiver.sol\";\n\n/**\n * @dev Simple implementation of `IERC1155Receiver` that will allow a contract to hold ERC-1155 tokens.\n *\n * IMPORTANT: When inheriting this contract, you must include a way to use the received tokens, otherwise they will be\n * stuck.\n */\nabstract contract ERC1155Holder is ERC165, IERC1155Receiver {\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual override(ERC165, IERC165) returns (bool) {\n return interfaceId == type(IERC1155Receiver).interfaceId || super.supportsInterface(interfaceId);\n }\n\n function onERC1155Received(\n address,\n address,\n uint256,\n uint256,\n bytes memory\n ) public virtual override returns (bytes4) {\n return this.onERC1155Received.selector;\n }\n\n function onERC1155BatchReceived(\n address,\n address,\n uint256[] memory,\n uint256[] memory,\n bytes memory\n ) public virtual override returns (bytes4) {\n return this.onERC1155BatchReceived.selector;\n }\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/ERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.1.0) (token/ERC20/ERC20.sol)\n\npragma solidity ^0.8.20;\n\nimport {IERC20} from \"./IERC20.sol\";\nimport {IERC20Metadata} from \"./extensions/IERC20Metadata.sol\";\nimport {Context} from \"../../utils/Context.sol\";\nimport {IERC20Errors} from \"../../interfaces/draft-IERC6093.sol\";\n\n/**\n * @dev Implementation of the {IERC20} interface.\n *\n * This implementation is agnostic to the way tokens are created. This means\n * that a supply mechanism has to be added in a derived contract using {_mint}.\n *\n * TIP: For a detailed writeup see our guide\n * https://forum.openzeppelin.com/t/how-to-implement-erc20-supply-mechanisms/226[How\n * to implement supply mechanisms].\n *\n * The default value of {decimals} is 18. To change this, you should override\n * this function so it returns a different value.\n *\n * We have followed general OpenZeppelin Contracts guidelines: functions revert\n * instead returning `false` on failure. This behavior is nonetheless\n * conventional and does not conflict with the expectations of ERC-20\n * applications.\n */\nabstract contract ERC20 is Context, IERC20, IERC20Metadata, IERC20Errors {\n mapping(address account => uint256) private _balances;\n\n mapping(address account => mapping(address spender => uint256)) private _allowances;\n\n uint256 private _totalSupply;\n\n string private _name;\n string private _symbol;\n\n /**\n * @dev Sets the values for {name} and {symbol}.\n *\n * All two of these values are immutable: they can only be set once during\n * construction.\n */\n constructor(string memory name_, string memory symbol_) {\n _name = name_;\n _symbol = symbol_;\n }\n\n /**\n * @dev Returns the name of the token.\n */\n function name() public view virtual returns (string memory) {\n return _name;\n }\n\n /**\n * @dev Returns the symbol of the token, usually a shorter version of the\n * name.\n */\n function symbol() public view virtual returns (string memory) {\n return _symbol;\n }\n\n /**\n * @dev Returns the number of decimals used to get its user representation.\n * For example, if `decimals` equals `2`, a balance of `505` tokens should\n * be displayed to a user as `5.05` (`505 / 10 ** 2`).\n *\n * Tokens usually opt for a value of 18, imitating the relationship between\n * Ether and Wei. This is the default value returned by this function, unless\n * it's overridden.\n *\n * NOTE: This information is only used for _display_ purposes: it in\n * no way affects any of the arithmetic of the contract, including\n * {IERC20-balanceOf} and {IERC20-transfer}.\n */\n function decimals() public view virtual returns (uint8) {\n return 18;\n }\n\n /**\n * @dev See {IERC20-totalSupply}.\n */\n function totalSupply() public view virtual returns (uint256) {\n return _totalSupply;\n }\n\n /**\n * @dev See {IERC20-balanceOf}.\n */\n function balanceOf(address account) public view virtual returns (uint256) {\n return _balances[account];\n }\n\n /**\n * @dev See {IERC20-transfer}.\n *\n * Requirements:\n *\n * - `to` cannot be the zero address.\n * - the caller must have a balance of at least `value`.\n */\n function transfer(address to, uint256 value) public virtual returns (bool) {\n address owner = _msgSender();\n _transfer(owner, to, value);\n return true;\n }\n\n /**\n * @dev See {IERC20-allowance}.\n */\n function allowance(address owner, address spender) public view virtual returns (uint256) {\n return _allowances[owner][spender];\n }\n\n /**\n * @dev See {IERC20-approve}.\n *\n * NOTE: If `value` is the maximum `uint256`, the allowance is not updated on\n * `transferFrom`. This is semantically equivalent to an infinite approval.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n */\n function approve(address spender, uint256 value) public virtual returns (bool) {\n address owner = _msgSender();\n _approve(owner, spender, value);\n return true;\n }\n\n /**\n * @dev See {IERC20-transferFrom}.\n *\n * Skips emitting an {Approval} event indicating an allowance update. This is not\n * required by the ERC. See {xref-ERC20-_approve-address-address-uint256-bool-}[_approve].\n *\n * NOTE: Does not update the allowance if the current allowance\n * is the maximum `uint256`.\n *\n * Requirements:\n *\n * - `from` and `to` cannot be the zero address.\n * - `from` must have a balance of at least `value`.\n * - the caller must have allowance for ``from``'s tokens of at least\n * `value`.\n */\n function transferFrom(address from, address to, uint256 value) public virtual returns (bool) {\n address spender = _msgSender();\n _spendAllowance(from, spender, value);\n _transfer(from, to, value);\n return true;\n }\n\n /**\n * @dev Moves a `value` amount of tokens from `from` to `to`.\n *\n * This internal function is equivalent to {transfer}, and can be used to\n * e.g. implement automatic token fees, slashing mechanisms, etc.\n *\n * Emits a {Transfer} event.\n *\n * NOTE: This function is not virtual, {_update} should be overridden instead.\n */\n function _transfer(address from, address to, uint256 value) internal {\n if (from == address(0)) {\n revert ERC20InvalidSender(address(0));\n }\n if (to == address(0)) {\n revert ERC20InvalidReceiver(address(0));\n }\n _update(from, to, value);\n }\n\n /**\n * @dev Transfers a `value` amount of tokens from `from` to `to`, or alternatively mints (or burns) if `from`\n * (or `to`) is the zero address. All customizations to transfers, mints, and burns should be done by overriding\n * this function.\n *\n * Emits a {Transfer} event.\n */\n function _update(address from, address to, uint256 value) internal virtual {\n if (from == address(0)) {\n // Overflow check required: The rest of the code assumes that totalSupply never overflows\n _totalSupply += value;\n } else {\n uint256 fromBalance = _balances[from];\n if (fromBalance < value) {\n revert ERC20InsufficientBalance(from, fromBalance, value);\n }\n unchecked {\n // Overflow not possible: value <= fromBalance <= totalSupply.\n _balances[from] = fromBalance - value;\n }\n }\n\n if (to == address(0)) {\n unchecked {\n // Overflow not possible: value <= totalSupply or value <= fromBalance <= totalSupply.\n _totalSupply -= value;\n }\n } else {\n unchecked {\n // Overflow not possible: balance + value is at most totalSupply, which we know fits into a uint256.\n _balances[to] += value;\n }\n }\n\n emit Transfer(from, to, value);\n }\n\n /**\n * @dev Creates a `value` amount of tokens and assigns them to `account`, by transferring it from address(0).\n * Relies on the `_update` mechanism\n *\n * Emits a {Transfer} event with `from` set to the zero address.\n *\n * NOTE: This function is not virtual, {_update} should be overridden instead.\n */\n function _mint(address account, uint256 value) internal {\n if (account == address(0)) {\n revert ERC20InvalidReceiver(address(0));\n }\n _update(address(0), account, value);\n }\n\n /**\n * @dev Destroys a `value` amount of tokens from `account`, lowering the total supply.\n * Relies on the `_update` mechanism.\n *\n * Emits a {Transfer} event with `to` set to the zero address.\n *\n * NOTE: This function is not virtual, {_update} should be overridden instead\n */\n function _burn(address account, uint256 value) internal {\n if (account == address(0)) {\n revert ERC20InvalidSender(address(0));\n }\n _update(account, address(0), value);\n }\n\n /**\n * @dev Sets `value` as the allowance of `spender` over the `owner` s tokens.\n *\n * This internal function is equivalent to `approve`, and can be used to\n * e.g. set automatic allowances for certain subsystems, etc.\n *\n * Emits an {Approval} event.\n *\n * Requirements:\n *\n * - `owner` cannot be the zero address.\n * - `spender` cannot be the zero address.\n *\n * Overrides to this logic should be done to the variant with an additional `bool emitEvent` argument.\n */\n function _approve(address owner, address spender, uint256 value) internal {\n _approve(owner, spender, value, true);\n }\n\n /**\n * @dev Variant of {_approve} with an optional flag to enable or disable the {Approval} event.\n *\n * By default (when calling {_approve}) the flag is set to true. On the other hand, approval changes made by\n * `_spendAllowance` during the `transferFrom` operation set the flag to false. This saves gas by not emitting any\n * `Approval` event during `transferFrom` operations.\n *\n * Anyone who wishes to continue emitting `Approval` events on the`transferFrom` operation can force the flag to\n * true using the following override:\n *\n * ```solidity\n * function _approve(address owner, address spender, uint256 value, bool) internal virtual override {\n * super._approve(owner, spender, value, true);\n * }\n * ```\n *\n * Requirements are the same as {_approve}.\n */\n function _approve(address owner, address spender, uint256 value, bool emitEvent) internal virtual {\n if (owner == address(0)) {\n revert ERC20InvalidApprover(address(0));\n }\n if (spender == address(0)) {\n revert ERC20InvalidSpender(address(0));\n }\n _allowances[owner][spender] = value;\n if (emitEvent) {\n emit Approval(owner, spender, value);\n }\n }\n\n /**\n * @dev Updates `owner` s allowance for `spender` based on spent `value`.\n *\n * Does not update the allowance value in case of infinite allowance.\n * Revert if not enough allowance is available.\n *\n * Does not emit an {Approval} event.\n */\n function _spendAllowance(address owner, address spender, uint256 value) internal virtual {\n uint256 currentAllowance = allowance(owner, spender);\n if (currentAllowance != type(uint256).max) {\n if (currentAllowance < value) {\n revert ERC20InsufficientAllowance(spender, currentAllowance, value);\n }\n unchecked {\n _approve(owner, spender, currentAllowance - value, false);\n }\n }\n }\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.1.0) (token/ERC20/extensions/IERC20Metadata.sol)\n\npragma solidity ^0.8.20;\n\nimport {IERC20} from \"../IERC20.sol\";\n\n/**\n * @dev Interface for the optional metadata functions from the ERC-20 standard.\n */\ninterface IERC20Metadata is IERC20 {\n /**\n * @dev Returns the name of the token.\n */\n function name() external view returns (string memory);\n\n /**\n * @dev Returns the symbol of the token.\n */\n function symbol() external view returns (string memory);\n\n /**\n * @dev Returns the decimals places of the token.\n */\n function decimals() external view returns (uint8);\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/IERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.1.0) (token/ERC20/IERC20.sol)\n\npragma solidity ^0.8.20;\n\n/**\n * @dev Interface of the ERC-20 standard as defined in the ERC.\n */\ninterface IERC20 {\n /**\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\n * another (`to`).\n *\n * Note that `value` may be zero.\n */\n event Transfer(address indexed from, address indexed to, uint256 value);\n\n /**\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\n * a call to {approve}. `value` is the new allowance.\n */\n event Approval(address indexed owner, address indexed spender, uint256 value);\n\n /**\n * @dev Returns the value of tokens in existence.\n */\n function totalSupply() external view returns (uint256);\n\n /**\n * @dev Returns the value of tokens owned by `account`.\n */\n function balanceOf(address account) external view returns (uint256);\n\n /**\n * @dev Moves a `value` amount of tokens from the caller's account to `to`.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transfer(address to, uint256 value) external returns (bool);\n\n /**\n * @dev Returns the remaining number of tokens that `spender` will be\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\n * zero by default.\n *\n * This value changes when {approve} or {transferFrom} are called.\n */\n function allowance(address owner, address spender) external view returns (uint256);\n\n /**\n * @dev Sets a `value` amount of tokens as the allowance of `spender` over the\n * caller's tokens.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\n * that someone may use both the old and the new allowance by unfortunate\n * transaction ordering. One possible solution to mitigate this race\n * condition is to first reduce the spender's allowance to 0 and set the\n * desired value afterwards:\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\n *\n * Emits an {Approval} event.\n */\n function approve(address spender, uint256 value) external returns (bool);\n\n /**\n * @dev Moves a `value` amount of tokens from `from` to `to` using the\n * allowance mechanism. `value` is then deducted from the caller's\n * allowance.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transferFrom(address from, address to, uint256 value) external returns (bool);\n}\n" + }, + "@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.1.0) (token/ERC721/IERC721Receiver.sol)\n\npragma solidity ^0.8.20;\n\n/**\n * @title ERC-721 token receiver interface\n * @dev Interface for any contract that wants to support safeTransfers\n * from ERC-721 asset contracts.\n */\ninterface IERC721Receiver {\n /**\n * @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom}\n * by `operator` from `from`, this function is called.\n *\n * It must return its Solidity selector to confirm the token transfer.\n * If any other value is returned or the interface is not implemented by the recipient, the transfer will be\n * reverted.\n *\n * The selector can be obtained in Solidity with `IERC721Receiver.onERC721Received.selector`.\n */\n function onERC721Received(\n address operator,\n address from,\n uint256 tokenId,\n bytes calldata data\n ) external returns (bytes4);\n}\n" + }, + "@openzeppelin/contracts/token/ERC721/utils/ERC721Holder.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC721/utils/ERC721Holder.sol)\n\npragma solidity ^0.8.20;\n\nimport {IERC721Receiver} from \"../IERC721Receiver.sol\";\n\n/**\n * @dev Implementation of the {IERC721Receiver} interface.\n *\n * Accepts all token transfers.\n * Make sure the contract is able to use its token with {IERC721-safeTransferFrom}, {IERC721-approve} or\n * {IERC721-setApprovalForAll}.\n */\nabstract contract ERC721Holder is IERC721Receiver {\n /**\n * @dev See {IERC721Receiver-onERC721Received}.\n *\n * Always returns `IERC721Receiver.onERC721Received.selector`.\n */\n function onERC721Received(address, address, uint256, bytes memory) public virtual returns (bytes4) {\n return this.onERC721Received.selector;\n }\n}\n" + }, + "@openzeppelin/contracts/utils/Address.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.1.0) (utils/Address.sol)\n\npragma solidity ^0.8.20;\n\nimport {Errors} from \"./Errors.sol\";\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary Address {\n /**\n * @dev There's no code at `target` (it is not a contract).\n */\n error AddressEmptyCode(address target);\n\n /**\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n * `recipient`, forwarding all available gas and reverting on errors.\n *\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\n * imposed by `transfer`, making them unable to receive funds via\n * `transfer`. {sendValue} removes this limitation.\n *\n * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n *\n * IMPORTANT: because control is transferred to `recipient`, care must be\n * taken to not create reentrancy vulnerabilities. Consider using\n * {ReentrancyGuard} or the\n * https://solidity.readthedocs.io/en/v0.8.20/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n */\n function sendValue(address payable recipient, uint256 amount) internal {\n if (address(this).balance < amount) {\n revert Errors.InsufficientBalance(address(this).balance, amount);\n }\n\n (bool success, ) = recipient.call{value: amount}(\"\");\n if (!success) {\n revert Errors.FailedCall();\n }\n }\n\n /**\n * @dev Performs a Solidity function call using a low level `call`. A\n * plain `call` is an unsafe replacement for a function call: use this\n * function instead.\n *\n * If `target` reverts with a revert reason or custom error, it is bubbled\n * up by this function (like regular Solidity function calls). However, if\n * the call reverted with no returned reason, this function reverts with a\n * {Errors.FailedCall} error.\n *\n * Returns the raw returned data. To convert to the expected return value,\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n *\n * Requirements:\n *\n * - `target` must be a contract.\n * - calling `target` with `data` must not revert.\n */\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but also transferring `value` wei to `target`.\n *\n * Requirements:\n *\n * - the calling contract must have an ETH balance of at least `value`.\n * - the called Solidity function must be `payable`.\n */\n function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\n if (address(this).balance < value) {\n revert Errors.InsufficientBalance(address(this).balance, value);\n }\n (bool success, bytes memory returndata) = target.call{value: value}(data);\n return verifyCallResultFromTarget(target, success, returndata);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a static call.\n */\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n (bool success, bytes memory returndata) = target.staticcall(data);\n return verifyCallResultFromTarget(target, success, returndata);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a delegate call.\n */\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\n (bool success, bytes memory returndata) = target.delegatecall(data);\n return verifyCallResultFromTarget(target, success, returndata);\n }\n\n /**\n * @dev Tool to verify that a low level call to smart-contract was successful, and reverts if the target\n * was not a contract or bubbling up the revert reason (falling back to {Errors.FailedCall}) in case\n * of an unsuccessful call.\n */\n function verifyCallResultFromTarget(\n address target,\n bool success,\n bytes memory returndata\n ) internal view returns (bytes memory) {\n if (!success) {\n _revert(returndata);\n } else {\n // only check if target is a contract if the call was successful and the return data is empty\n // otherwise we already know that it was a contract\n if (returndata.length == 0 && target.code.length == 0) {\n revert AddressEmptyCode(target);\n }\n return returndata;\n }\n }\n\n /**\n * @dev Tool to verify that a low level call was successful, and reverts if it wasn't, either by bubbling the\n * revert reason or with a default {Errors.FailedCall} error.\n */\n function verifyCallResult(bool success, bytes memory returndata) internal pure returns (bytes memory) {\n if (!success) {\n _revert(returndata);\n } else {\n return returndata;\n }\n }\n\n /**\n * @dev Reverts with returndata if present. Otherwise reverts with {Errors.FailedCall}.\n */\n function _revert(bytes memory returndata) private pure {\n // Look for revert reason and bubble it up if present\n if (returndata.length > 0) {\n // The easiest way to bubble the revert reason is using memory via assembly\n assembly (\"memory-safe\") {\n let returndata_size := mload(returndata)\n revert(add(32, returndata), returndata_size)\n }\n } else {\n revert Errors.FailedCall();\n }\n }\n}\n" + }, + "@openzeppelin/contracts/utils/Context.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol)\n\npragma solidity ^0.8.20;\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract Context {\n function _msgSender() internal view virtual returns (address) {\n return msg.sender;\n }\n\n function _msgData() internal view virtual returns (bytes calldata) {\n return msg.data;\n }\n\n function _contextSuffixLength() internal view virtual returns (uint256) {\n return 0;\n }\n}\n" + }, + "@openzeppelin/contracts/utils/Create2.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.1.0) (utils/Create2.sol)\n\npragma solidity ^0.8.20;\n\nimport {Errors} from \"./Errors.sol\";\n\n/**\n * @dev Helper to make usage of the `CREATE2` EVM opcode easier and safer.\n * `CREATE2` can be used to compute in advance the address where a smart\n * contract will be deployed, which allows for interesting new mechanisms known\n * as 'counterfactual interactions'.\n *\n * See the https://eips.ethereum.org/EIPS/eip-1014#motivation[EIP] for more\n * information.\n */\nlibrary Create2 {\n /**\n * @dev There's no code to deploy.\n */\n error Create2EmptyBytecode();\n\n /**\n * @dev Deploys a contract using `CREATE2`. The address where the contract\n * will be deployed can be known in advance via {computeAddress}.\n *\n * The bytecode for a contract can be obtained from Solidity with\n * `type(contractName).creationCode`.\n *\n * Requirements:\n *\n * - `bytecode` must not be empty.\n * - `salt` must have not been used for `bytecode` already.\n * - the factory must have a balance of at least `amount`.\n * - if `amount` is non-zero, `bytecode` must have a `payable` constructor.\n */\n function deploy(uint256 amount, bytes32 salt, bytes memory bytecode) internal returns (address addr) {\n if (address(this).balance < amount) {\n revert Errors.InsufficientBalance(address(this).balance, amount);\n }\n if (bytecode.length == 0) {\n revert Create2EmptyBytecode();\n }\n assembly (\"memory-safe\") {\n addr := create2(amount, add(bytecode, 0x20), mload(bytecode), salt)\n // if no address was created, and returndata is not empty, bubble revert\n if and(iszero(addr), not(iszero(returndatasize()))) {\n let p := mload(0x40)\n returndatacopy(p, 0, returndatasize())\n revert(p, returndatasize())\n }\n }\n if (addr == address(0)) {\n revert Errors.FailedDeployment();\n }\n }\n\n /**\n * @dev Returns the address where a contract will be stored if deployed via {deploy}. Any change in the\n * `bytecodeHash` or `salt` will result in a new destination address.\n */\n function computeAddress(bytes32 salt, bytes32 bytecodeHash) internal view returns (address) {\n return computeAddress(salt, bytecodeHash, address(this));\n }\n\n /**\n * @dev Returns the address where a contract will be stored if deployed via {deploy} from a contract located at\n * `deployer`. If `deployer` is this contract's address, returns the same value as {computeAddress}.\n */\n function computeAddress(bytes32 salt, bytes32 bytecodeHash, address deployer) internal pure returns (address addr) {\n assembly (\"memory-safe\") {\n let ptr := mload(0x40) // Get free memory pointer\n\n // | | ↓ ptr ... ↓ ptr + 0x0B (start) ... ↓ ptr + 0x20 ... ↓ ptr + 0x40 ... |\n // |-------------------|---------------------------------------------------------------------------|\n // | bytecodeHash | CCCCCCCCCCCCC...CC |\n // | salt | BBBBBBBBBBBBB...BB |\n // | deployer | 000000...0000AAAAAAAAAAAAAAAAAAA...AA |\n // | 0xFF | FF |\n // |-------------------|---------------------------------------------------------------------------|\n // | memory | 000000...00FFAAAAAAAAAAAAAAAAAAA...AABBBBBBBBBBBBB...BBCCCCCCCCCCCCC...CC |\n // | keccak(start, 85) | ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑ |\n\n mstore(add(ptr, 0x40), bytecodeHash)\n mstore(add(ptr, 0x20), salt)\n mstore(ptr, deployer) // Right-aligned with 12 preceding garbage bytes\n let start := add(ptr, 0x0b) // The hashed data starts at the final garbage byte which we will set to 0xff\n mstore8(start, 0xff)\n addr := and(keccak256(start, 85), 0xffffffffffffffffffffffffffffffffffffffff)\n }\n }\n}\n" + }, + "@openzeppelin/contracts/utils/cryptography/ECDSA.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.1.0) (utils/cryptography/ECDSA.sol)\n\npragma solidity ^0.8.20;\n\n/**\n * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations.\n *\n * These functions can be used to verify that a message was signed by the holder\n * of the private keys of a given address.\n */\nlibrary ECDSA {\n enum RecoverError {\n NoError,\n InvalidSignature,\n InvalidSignatureLength,\n InvalidSignatureS\n }\n\n /**\n * @dev The signature derives the `address(0)`.\n */\n error ECDSAInvalidSignature();\n\n /**\n * @dev The signature has an invalid length.\n */\n error ECDSAInvalidSignatureLength(uint256 length);\n\n /**\n * @dev The signature has an S value that is in the upper half order.\n */\n error ECDSAInvalidSignatureS(bytes32 s);\n\n /**\n * @dev Returns the address that signed a hashed message (`hash`) with `signature` or an error. This will not\n * return address(0) without also returning an error description. Errors are documented using an enum (error type)\n * and a bytes32 providing additional information about the error.\n *\n * If no error is returned, then the address can be used for verification purposes.\n *\n * The `ecrecover` EVM precompile allows for malleable (non-unique) signatures:\n * this function rejects them by requiring the `s` value to be in the lower\n * half order, and the `v` value to be either 27 or 28.\n *\n * IMPORTANT: `hash` _must_ be the result of a hash operation for the\n * verification to be secure: it is possible to craft signatures that\n * recover to arbitrary addresses for non-hashed data. A safe way to ensure\n * this is by receiving a hash of the original message (which may otherwise\n * be too long), and then calling {MessageHashUtils-toEthSignedMessageHash} on it.\n *\n * Documentation for signature generation:\n * - with https://web3js.readthedocs.io/en/v1.3.4/web3-eth-accounts.html#sign[Web3.js]\n * - with https://docs.ethers.io/v5/api/signer/#Signer-signMessage[ethers]\n */\n function tryRecover(\n bytes32 hash,\n bytes memory signature\n ) internal pure returns (address recovered, RecoverError err, bytes32 errArg) {\n if (signature.length == 65) {\n bytes32 r;\n bytes32 s;\n uint8 v;\n // ecrecover takes the signature parameters, and the only way to get them\n // currently is to use assembly.\n assembly (\"memory-safe\") {\n r := mload(add(signature, 0x20))\n s := mload(add(signature, 0x40))\n v := byte(0, mload(add(signature, 0x60)))\n }\n return tryRecover(hash, v, r, s);\n } else {\n return (address(0), RecoverError.InvalidSignatureLength, bytes32(signature.length));\n }\n }\n\n /**\n * @dev Returns the address that signed a hashed message (`hash`) with\n * `signature`. This address can then be used for verification purposes.\n *\n * The `ecrecover` EVM precompile allows for malleable (non-unique) signatures:\n * this function rejects them by requiring the `s` value to be in the lower\n * half order, and the `v` value to be either 27 or 28.\n *\n * IMPORTANT: `hash` _must_ be the result of a hash operation for the\n * verification to be secure: it is possible to craft signatures that\n * recover to arbitrary addresses for non-hashed data. A safe way to ensure\n * this is by receiving a hash of the original message (which may otherwise\n * be too long), and then calling {MessageHashUtils-toEthSignedMessageHash} on it.\n */\n function recover(bytes32 hash, bytes memory signature) internal pure returns (address) {\n (address recovered, RecoverError error, bytes32 errorArg) = tryRecover(hash, signature);\n _throwError(error, errorArg);\n return recovered;\n }\n\n /**\n * @dev Overload of {ECDSA-tryRecover} that receives the `r` and `vs` short-signature fields separately.\n *\n * See https://eips.ethereum.org/EIPS/eip-2098[ERC-2098 short signatures]\n */\n function tryRecover(\n bytes32 hash,\n bytes32 r,\n bytes32 vs\n ) internal pure returns (address recovered, RecoverError err, bytes32 errArg) {\n unchecked {\n bytes32 s = vs & bytes32(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff);\n // We do not check for an overflow here since the shift operation results in 0 or 1.\n uint8 v = uint8((uint256(vs) >> 255) + 27);\n return tryRecover(hash, v, r, s);\n }\n }\n\n /**\n * @dev Overload of {ECDSA-recover} that receives the `r and `vs` short-signature fields separately.\n */\n function recover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address) {\n (address recovered, RecoverError error, bytes32 errorArg) = tryRecover(hash, r, vs);\n _throwError(error, errorArg);\n return recovered;\n }\n\n /**\n * @dev Overload of {ECDSA-tryRecover} that receives the `v`,\n * `r` and `s` signature fields separately.\n */\n function tryRecover(\n bytes32 hash,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) internal pure returns (address recovered, RecoverError err, bytes32 errArg) {\n // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature\n // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines\n // the valid range for s in (301): 0 < s < secp256k1n ÷ 2 + 1, and for v in (302): v ∈ {27, 28}. Most\n // signatures from current libraries generate a unique signature with an s-value in the lower half order.\n //\n // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value\n // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or\n // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept\n // these malleable signatures as well.\n if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) {\n return (address(0), RecoverError.InvalidSignatureS, s);\n }\n\n // If the signature is valid (and not malleable), return the signer address\n address signer = ecrecover(hash, v, r, s);\n if (signer == address(0)) {\n return (address(0), RecoverError.InvalidSignature, bytes32(0));\n }\n\n return (signer, RecoverError.NoError, bytes32(0));\n }\n\n /**\n * @dev Overload of {ECDSA-recover} that receives the `v`,\n * `r` and `s` signature fields separately.\n */\n function recover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address) {\n (address recovered, RecoverError error, bytes32 errorArg) = tryRecover(hash, v, r, s);\n _throwError(error, errorArg);\n return recovered;\n }\n\n /**\n * @dev Optionally reverts with the corresponding custom error according to the `error` argument provided.\n */\n function _throwError(RecoverError error, bytes32 errorArg) private pure {\n if (error == RecoverError.NoError) {\n return; // no error: do nothing\n } else if (error == RecoverError.InvalidSignature) {\n revert ECDSAInvalidSignature();\n } else if (error == RecoverError.InvalidSignatureLength) {\n revert ECDSAInvalidSignatureLength(uint256(errorArg));\n } else if (error == RecoverError.InvalidSignatureS) {\n revert ECDSAInvalidSignatureS(errorArg);\n }\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/Errors.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.1.0) (utils/Errors.sol)\n\npragma solidity ^0.8.20;\n\n/**\n * @dev Collection of common custom errors used in multiple contracts\n *\n * IMPORTANT: Backwards compatibility is not guaranteed in future versions of the library.\n * It is recommended to avoid relying on the error API for critical functionality.\n *\n * _Available since v5.1._\n */\nlibrary Errors {\n /**\n * @dev The ETH balance of the account is not enough to perform the operation.\n */\n error InsufficientBalance(uint256 balance, uint256 needed);\n\n /**\n * @dev A call to an address target failed. The target may have reverted.\n */\n error FailedCall();\n\n /**\n * @dev The deployment failed.\n */\n error FailedDeployment();\n\n /**\n * @dev A necessary precompile is missing.\n */\n error MissingPrecompile(address);\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/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" + }, + "@uniswap/v3-core/contracts/interfaces/callback/IUniswapV3SwapCallback.sol": { + "content": "// SPDX-License-Identifier: GPL-2.0-or-later\npragma solidity >=0.5.0;\n\n/// @title Callback for IUniswapV3PoolActions#swap\n/// @notice Any contract that calls IUniswapV3PoolActions#swap must implement this interface\ninterface IUniswapV3SwapCallback {\n /// @notice Called to `msg.sender` after executing a swap via IUniswapV3Pool#swap.\n /// @dev In the implementation you must pay the pool tokens owed for the swap.\n /// The caller of this method must be checked to be a UniswapV3Pool deployed by the canonical UniswapV3Factory.\n /// amount0Delta and amount1Delta can both be 0 if no tokens were swapped.\n /// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by\n /// the end of the swap. If positive, the callback must send that amount of token0 to the pool.\n /// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by\n /// the end of the swap. If positive, the callback must send that amount of token1 to the pool.\n /// @param data Any data passed through by the caller via the IUniswapV3PoolActions#swap call\n function uniswapV3SwapCallback(\n int256 amount0Delta,\n int256 amount1Delta,\n bytes calldata data\n ) external;\n}\n" + }, + "@uniswap/v3-periphery/contracts/interfaces/ISwapRouter.sol": { + "content": "// SPDX-License-Identifier: GPL-2.0-or-later\npragma solidity >=0.7.5;\npragma abicoder v2;\n\nimport '@uniswap/v3-core/contracts/interfaces/callback/IUniswapV3SwapCallback.sol';\n\n/// @title Router token swapping functionality\n/// @notice Functions for swapping tokens via Uniswap V3\ninterface ISwapRouter is IUniswapV3SwapCallback {\n struct ExactInputSingleParams {\n address tokenIn;\n address tokenOut;\n uint24 fee;\n address recipient;\n uint256 deadline;\n uint256 amountIn;\n uint256 amountOutMinimum;\n uint160 sqrtPriceLimitX96;\n }\n\n /// @notice Swaps `amountIn` of one token for as much as possible of another token\n /// @param params The parameters necessary for the swap, encoded as `ExactInputSingleParams` in calldata\n /// @return amountOut The amount of the received token\n function exactInputSingle(ExactInputSingleParams calldata params) external payable returns (uint256 amountOut);\n\n struct ExactInputParams {\n bytes path;\n address recipient;\n uint256 deadline;\n uint256 amountIn;\n uint256 amountOutMinimum;\n }\n\n /// @notice Swaps `amountIn` of one token for as much as possible of another along the specified path\n /// @param params The parameters necessary for the multi-hop swap, encoded as `ExactInputParams` in calldata\n /// @return amountOut The amount of the received token\n function exactInput(ExactInputParams calldata params) external payable returns (uint256 amountOut);\n\n struct ExactOutputSingleParams {\n address tokenIn;\n address tokenOut;\n uint24 fee;\n address recipient;\n uint256 deadline;\n uint256 amountOut;\n uint256 amountInMaximum;\n uint160 sqrtPriceLimitX96;\n }\n\n /// @notice Swaps as little as possible of one token for `amountOut` of another token\n /// @param params The parameters necessary for the swap, encoded as `ExactOutputSingleParams` in calldata\n /// @return amountIn The amount of the input token\n function exactOutputSingle(ExactOutputSingleParams calldata params) external payable returns (uint256 amountIn);\n\n struct ExactOutputParams {\n bytes path;\n address recipient;\n uint256 deadline;\n uint256 amountOut;\n uint256 amountInMaximum;\n }\n\n /// @notice Swaps as little as possible of one token for `amountOut` of another along the specified path (reversed)\n /// @param params The parameters necessary for the multi-hop swap, encoded as `ExactOutputParams` in calldata\n /// @return amountIn The amount of the input token\n function exactOutput(ExactOutputParams calldata params) external payable returns (uint256 amountIn);\n}\n" + }, + "contracts/accounts/callback/TokenCallbackHandler.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.28;\n\n/* solhint-disable no-empty-blocks */\n\nimport \"@openzeppelin/contracts/utils/introspection/IERC165.sol\";\nimport \"@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol\";\nimport \"@openzeppelin/contracts/token/ERC1155/IERC1155Receiver.sol\";\n\n/**\n * Token callback handler.\n * Handles supported tokens' callbacks, allowing account receiving these tokens.\n */\nabstract contract TokenCallbackHandler is IERC721Receiver, IERC1155Receiver {\n\n function onERC721Received(\n address,\n address,\n uint256,\n bytes calldata\n ) external pure override returns (bytes4) {\n return IERC721Receiver.onERC721Received.selector;\n }\n\n function onERC1155Received(\n address,\n address,\n uint256,\n uint256,\n bytes calldata\n ) external pure override returns (bytes4) {\n return IERC1155Receiver.onERC1155Received.selector;\n }\n\n function onERC1155BatchReceived(\n address,\n address,\n uint256[] calldata,\n uint256[] calldata,\n bytes calldata\n ) external pure override returns (bytes4) {\n return IERC1155Receiver.onERC1155BatchReceived.selector;\n }\n\n function supportsInterface(bytes4 interfaceId) external view virtual override returns (bool) {\n return\n interfaceId == type(IERC721Receiver).interfaceId ||\n interfaceId == type(IERC1155Receiver).interfaceId ||\n interfaceId == type(IERC165).interfaceId;\n }\n}\n" + }, + "contracts/accounts/Simple7702Account.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.28;\n\nimport \"@openzeppelin/contracts/utils/introspection/IERC165.sol\";\nimport \"@openzeppelin/contracts/interfaces/IERC1271.sol\";\nimport \"@openzeppelin/contracts/token/ERC1155/utils/ERC1155Holder.sol\";\nimport \"@openzeppelin/contracts/token/ERC721/utils/ERC721Holder.sol\";\nimport \"@openzeppelin/contracts/utils/cryptography/ECDSA.sol\";\nimport \"../core/Helpers.sol\";\nimport \"../core/BaseAccount.sol\";\n\n/**\n * Simple7702Account.sol\n * A minimal account to be used with EIP-7702 (for batching) and ERC-4337 (for gas sponsoring)\n */\ncontract Simple7702Account is BaseAccount, IERC165, IERC1271, ERC1155Holder, ERC721Holder {\n\n IEntryPoint private immutable _entryPoint;\n\n constructor(IEntryPoint anEntryPoint) {\n _entryPoint = anEntryPoint;\n }\n\n function entryPoint() public view override returns (IEntryPoint) {\n return _entryPoint;\n }\n\n /**\n * Make this account callable through ERC-4337 EntryPoint.\n * The UserOperation should be signed by this account's private key.\n */\n function _validateSignature(\n PackedUserOperation calldata userOp,\n bytes32 userOpHash\n ) internal virtual override returns (uint256 validationData) {\n\n return _checkSignature(userOpHash, userOp.signature) ? SIG_VALIDATION_SUCCESS : SIG_VALIDATION_FAILED;\n }\n\n function isValidSignature(bytes32 hash, bytes memory signature) public view returns (bytes4 magicValue) {\n return _checkSignature(hash, signature) ? this.isValidSignature.selector : bytes4(0xffffffff);\n }\n\n function _checkSignature(bytes32 hash, bytes memory signature) internal view returns (bool) {\n return ECDSA.recover(hash, signature) == address(this);\n }\n\n function _requireForExecute() internal view virtual override {\n require(\n msg.sender == address(this) ||\n msg.sender == address(entryPoint()),\n NotFromEntryPoint(\n msg.sender,\n address(this),\n address(entryPoint())\n )\n );\n }\n\n function supportsInterface(bytes4 id) public override(ERC1155Holder, IERC165) pure returns (bool) {\n return\n id == type(IERC165).interfaceId ||\n id == type(IAccount).interfaceId ||\n id == type(IERC1271).interfaceId ||\n id == type(IERC1155Receiver).interfaceId ||\n id == type(IERC721Receiver).interfaceId;\n }\n\n // accept incoming calls (with or without value), to mimic an EOA.\n fallback() external payable {\n }\n\n receive() external payable {\n }\n}\n" + }, + "contracts/accounts/SimpleAccount.sol": { + "content": "// 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 \"@openzeppelin/contracts/utils/cryptography/ECDSA.sol\";\nimport \"@openzeppelin/contracts/utils/cryptography/MessageHashUtils.sol\";\nimport \"@openzeppelin/contracts/proxy/utils/Initializable.sol\";\nimport \"@openzeppelin/contracts/proxy/utils/UUPSUpgradeable.sol\";\nimport \"../core/BaseAccount.sol\";\nimport \"../core/Helpers.sol\";\nimport \"./callback/TokenCallbackHandler.sol\";\n\n/**\n * minimal account.\n * this is sample minimal account.\n * has execute, eth handling methods\n * has a single signer that can send requests through the entryPoint.\n */\ncontract SimpleAccount is BaseAccount, TokenCallbackHandler, UUPSUpgradeable, Initializable {\n address public owner;\n\n IEntryPoint private immutable _entryPoint;\n\n event SimpleAccountInitialized(IEntryPoint indexed entryPoint, address indexed owner);\n\n modifier onlyOwner() {\n _onlyOwner();\n _;\n }\n\n error NotOwner(address msgSender, address entity, address owner );\n error NotOwnerOrEntryPoint(address msgSender, address entity, address entryPoint, address owner);\n\n /// @inheritdoc BaseAccount\n function entryPoint() public view virtual override returns (IEntryPoint) {\n return _entryPoint;\n }\n\n // solhint-disable-next-line no-empty-blocks\n receive() external payable {}\n\n constructor(IEntryPoint anEntryPoint) {\n _entryPoint = anEntryPoint;\n _disableInitializers();\n }\n\n function _onlyOwner() internal view {\n // Directly from EOA owner, or through the account itself (which gets redirected through execute())\n require(\n msg.sender == owner || msg.sender == address(this),\n NotOwner(\n msg.sender,\n address(this),\n owner\n )\n );\n }\n\n /**\n * @dev The _entryPoint member is immutable, to reduce gas consumption. To upgrade EntryPoint,\n * a new implementation of SimpleAccount must be deployed with the new EntryPoint address, then upgrading\n * the implementation by calling `upgradeTo()`\n * @param anOwner the owner (signer) of this account\n */\n function initialize(address anOwner) public virtual initializer {\n _initialize(anOwner);\n }\n\n function _initialize(address anOwner) internal virtual {\n owner = anOwner;\n emit SimpleAccountInitialized(_entryPoint, owner);\n }\n\n // Require the function call went through EntryPoint or owner\n function _requireForExecute() internal view override virtual {\n require(msg.sender == address(entryPoint()) || msg.sender == owner,\n NotOwnerOrEntryPoint(\n msg.sender,\n address(this),\n address(entryPoint()),\n owner\n )\n );\n }\n\n /// implement template method of BaseAccount\n function _validateSignature(PackedUserOperation calldata userOp, bytes32 userOpHash)\n internal override virtual returns (uint256 validationData) {\n\n // UserOpHash can be generated using eth_signTypedData_v4\n if (owner != ECDSA.recover(userOpHash, userOp.signature))\n return SIG_VALIDATION_FAILED;\n return SIG_VALIDATION_SUCCESS;\n }\n\n /**\n * check current account deposit in the entryPoint\n */\n function getDeposit() public view returns (uint256) {\n return entryPoint().balanceOf(address(this));\n }\n\n /**\n * deposit more funds for this account in the entryPoint\n */\n function addDeposit() public payable {\n entryPoint().depositTo{value: msg.value}(address(this));\n }\n\n /**\n * withdraw value from the account's deposit\n * @param withdrawAddress target to send to\n * @param amount to withdraw\n */\n function withdrawDepositTo(address payable withdrawAddress, uint256 amount) public onlyOwner {\n entryPoint().withdrawTo(withdrawAddress, amount);\n }\n\n function _authorizeUpgrade(address newImplementation) internal view override {\n (newImplementation);\n _onlyOwner();\n }\n}\n\n" + }, + "contracts/accounts/SimpleAccountFactory.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.28;\n\nimport \"@openzeppelin/contracts/utils/Create2.sol\";\nimport \"@openzeppelin/contracts/proxy/ERC1967/ERC1967Proxy.sol\";\n\nimport \"../interfaces/ISenderCreator.sol\";\nimport \"./SimpleAccount.sol\";\n\n/**\n * A sample factory contract for SimpleAccount\n * A UserOperations \"initCode\" holds the address of the factory, and a method call (to createAccount, in this sample factory).\n * The factory's createAccount returns the target account address even if it is already installed.\n * This way, the entryPoint.getSenderAddress() can be called either before or after the account is created.\n */\ncontract SimpleAccountFactory {\n SimpleAccount public immutable accountImplementation;\n ISenderCreator public immutable senderCreator;\n\n error NotSenderCreator(address msgSender, address entity, address senderCreator);\n\n constructor(IEntryPoint _entryPoint) {\n accountImplementation = new SimpleAccount(_entryPoint);\n senderCreator = _entryPoint.senderCreator();\n }\n\n /**\n * create an account, and return its address.\n * returns the address even if the account is already deployed.\n * Note that during UserOperation execution, this method is called only if the account is not deployed.\n * This method returns an existing account address so that entryPoint.getSenderAddress() would work even after account creation\n */\n function createAccount(address owner, uint256 salt) public returns (SimpleAccount ret) {\n require(msg.sender == address(senderCreator),\n NotSenderCreator(\n msg.sender,\n address(this),\n address(senderCreator)\n )\n );\n address addr = getAddress(owner, salt);\n uint256 codeSize = addr.code.length;\n if (codeSize > 0) {\n return SimpleAccount(payable(addr));\n }\n ret = SimpleAccount(payable(new ERC1967Proxy{salt : bytes32(salt)}(\n address(accountImplementation),\n abi.encodeCall(SimpleAccount.initialize, (owner))\n )));\n }\n\n /**\n * calculate the counterfactual address of this account as it would be returned by createAccount()\n */\n function getAddress(address owner,uint256 salt) public view returns (address) {\n return Create2.computeAddress(bytes32(salt), keccak256(abi.encodePacked(\n type(ERC1967Proxy).creationCode,\n abi.encode(\n address(accountImplementation),\n abi.encodeCall(SimpleAccount.initialize, (owner))\n )\n )));\n }\n}\n" + }, + "contracts/core/BaseAccount.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.28;\n\n/* solhint-disable avoid-low-level-calls */\n/* solhint-disable no-empty-blocks */\n/* solhint-disable no-inline-assembly */\n\nimport \"../interfaces/IAccount.sol\";\nimport \"../interfaces/IEntryPoint.sol\";\nimport \"../utils/Exec.sol\";\nimport \"./UserOperationLib.sol\";\n\n/**\n * Basic account implementation.\n * This contract provides the basic logic for implementing the IAccount interface - validateUserOp\n * Specific account implementation should inherit it and provide the account-specific logic.\n */\nabstract contract BaseAccount is IAccount {\n using UserOperationLib for PackedUserOperation;\n\n struct Call {\n address target;\n uint256 value;\n bytes data;\n }\n\n error ExecuteError(uint256 index, bytes error);\n error NotFromEntryPoint(address msgSender, address entity, address entryPoint);\n\n /**\n * Return the account nonce.\n * This method returns the next sequential nonce.\n * For a nonce of a specific key, use `entrypoint.getNonce(account, key)`\n */\n function getNonce() public view virtual returns (uint256) {\n return entryPoint().getNonce(address(this), 0);\n }\n\n /**\n * Return the entryPoint used by this account.\n * Subclass should return the current entryPoint used by this account.\n */\n function entryPoint() public view virtual returns (IEntryPoint);\n\n /**\n * execute a single call from the account.\n */\n function execute(address target, uint256 value, bytes calldata data) virtual external {\n _requireForExecute();\n\n bool ok = Exec.call(target, value, data, gasleft());\n if (!ok) {\n Exec.revertWithReturnData();\n }\n }\n\n /**\n * execute a batch of calls.\n * revert on the first call that fails.\n * If the batch reverts, and it contains more than a single call, then wrap the revert with ExecuteError,\n * to mark the failing call index.\n */\n function executeBatch(Call[] calldata calls) virtual external {\n _requireForExecute();\n\n uint256 callsLength = calls.length;\n for (uint256 i = 0; i < callsLength; i++) {\n Call calldata call = calls[i];\n bool ok = Exec.call(call.target, call.value, call.data, gasleft());\n if (!ok) {\n if (callsLength == 1) {\n Exec.revertWithReturnData();\n } else {\n revert ExecuteError(i, Exec.getReturnData(0));\n }\n }\n }\n }\n\n /// @inheritdoc IAccount\n function validateUserOp(\n PackedUserOperation calldata userOp,\n bytes32 userOpHash,\n uint256 missingAccountFunds\n ) external virtual override returns (uint256 validationData) {\n _requireFromEntryPoint();\n validationData = _validateSignature(userOp, userOpHash);\n _validateNonce(userOp.nonce);\n _payPrefund(missingAccountFunds);\n }\n\n /**\n * Ensure the request comes from the known entrypoint.\n */\n function _requireFromEntryPoint() internal view virtual {\n require(\n msg.sender == address(entryPoint()),\n NotFromEntryPoint(\n msg.sender,\n address(this),\n address(entryPoint())\n )\n );\n }\n\n function _requireForExecute() internal view virtual {\n _requireFromEntryPoint();\n }\n\n /**\n * Validate the signature is valid for this message.\n * @param userOp - Validate the userOp.signature field.\n * @param userOpHash - Convenient field: the hash of the request, to check the signature against.\n * (also hashes the entrypoint and chain id)\n * @return validationData - Signature and time-range of this operation.\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 the account doesn't use time-range, it is enough to return\n * 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 _validateSignature(\n PackedUserOperation calldata userOp,\n bytes32 userOpHash\n ) internal virtual returns (uint256 validationData);\n\n /**\n * Validate the nonce of the UserOperation.\n * This method may validate the nonce requirement of this account.\n * e.g.\n * To limit the nonce to use sequenced UserOps only (no \"out of order\" UserOps):\n * `require(nonce < type(uint64).max)`\n * For a hypothetical account that *requires* the nonce to be out-of-order:\n * `require(nonce & type(uint64).max == 0)`\n *\n * The actual nonce uniqueness is managed by the EntryPoint, and thus no other\n * action is needed by the account itself.\n *\n * @param nonce to validate\n *\n * solhint-disable-next-line no-empty-blocks\n */\n function _validateNonce(uint256 nonce) internal view virtual {\n }\n\n /**\n * Sends to the entrypoint (msg.sender) the missing funds for this transaction.\n * SubClass MAY override this method for better funds management\n * (e.g. send to the entryPoint more than the minimum required, so that in future transactions\n * it will not be required to send again).\n * @param missingAccountFunds - The minimum value this method should send the entrypoint.\n * This value MAY be zero, in case there is enough deposit,\n * or the userOp has a paymaster.\n */\n function _payPrefund(uint256 missingAccountFunds) internal virtual {\n if (missingAccountFunds != 0) {\n (bool success,) = payable(msg.sender).call{\n value: missingAccountFunds\n }(\"\");\n (success);\n // Ignore failure (its EntryPoint's job to verify, not account.)\n }\n }\n}\n" + }, + "contracts/core/BasePaymaster.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.28;\n\n/* solhint-disable reason-string */\n\nimport \"@openzeppelin/contracts/access/Ownable2Step.sol\";\nimport \"@openzeppelin/contracts/utils/introspection/IERC165.sol\";\nimport \"../interfaces/IPaymaster.sol\";\nimport \"../interfaces/IEntryPoint.sol\";\nimport \"./Stakeable.sol\";\nimport \"./UserOperationLib.sol\";\n/**\n * Helper class for creating a paymaster.\n * provides helper methods for staking.\n * Validates that the postOp is called only by the entryPoint.\n */\nabstract contract BasePaymaster is IPaymaster, Stakeable {\n IEntryPoint internal immutable _entryPoint;\n\n uint256 internal constant PAYMASTER_VALIDATION_GAS_OFFSET = UserOperationLib.PAYMASTER_VALIDATION_GAS_OFFSET;\n uint256 internal constant PAYMASTER_POSTOP_GAS_OFFSET = UserOperationLib.PAYMASTER_POSTOP_GAS_OFFSET;\n uint256 internal constant PAYMASTER_DATA_OFFSET = UserOperationLib.PAYMASTER_DATA_OFFSET;\n\n error NotFromEntryPoint(address msgSender, address entity,address entryPoint);\n error ERC165Error(address entryPoint, bytes4 interfaceId);\n error MustOverride();\n\n constructor(IEntryPoint __entryPoint) Ownable(msg.sender) {\n _validateEntryPointInterface(__entryPoint);\n _entryPoint = __entryPoint;\n }\n\n function entryPoint() public view override returns (IEntryPoint) {\n return _entryPoint;\n }\n\n // Sanity check: make sure this EntryPoint was compiled against the same\n // IEntryPoint of this paymaster\n function _validateEntryPointInterface(IEntryPoint __entryPoint) internal virtual {\n bytes4 epInterfaceId = type(IEntryPoint).interfaceId;\n require(\n IERC165(address(__entryPoint)).supportsInterface(epInterfaceId),\n ERC165Error(address(__entryPoint), epInterfaceId)\n );\n }\n\n /// @inheritdoc IPaymaster\n function validatePaymasterUserOp(\n PackedUserOperation calldata userOp,\n bytes32 userOpHash,\n uint256 maxCost\n ) external override returns (bytes memory context, uint256 validationData) {\n _requireFromEntryPoint();\n return _validatePaymasterUserOp(userOp, userOpHash, maxCost);\n }\n\n /**\n * Validate a user operation.\n * @param userOp - The user operation.\n * @param userOpHash - The hash of the user operation.\n * @param maxCost - The maximum cost of the user operation.\n */\n function _validatePaymasterUserOp(\n PackedUserOperation calldata userOp,\n bytes32 userOpHash,\n uint256 maxCost\n ) internal virtual returns (bytes memory context, uint256 validationData);\n\n /// @inheritdoc IPaymaster\n function postOp(\n PostOpMode mode,\n bytes calldata context,\n uint256 actualGasCost,\n uint256 actualUserOpFeePerGas\n ) external override {\n _requireFromEntryPoint();\n _postOp(mode, context, actualGasCost, actualUserOpFeePerGas);\n }\n\n /**\n * Post-operation handler.\n * (verified to be called only through the entryPoint)\n * @dev If subclass returns a non-empty context from validatePaymasterUserOp,\n * it must also implement this method.\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 ) internal virtual {\n (mode, context, actualGasCost, actualUserOpFeePerGas); // unused params\n // subclass must override this method if validatePaymasterUserOp returns a context\n revert MustOverride();\n }\n\n /**\n * Add a deposit for this paymaster, used for paying for transaction fees.\n */\n function deposit() public payable {\n _entryPoint.depositTo{value: msg.value}(address(this));\n }\n\n /**\n * Withdraw value from the deposit.\n * @param withdrawAddress - Target to send to.\n * @param amount - Amount to withdraw.\n */\n function withdrawTo(\n address payable withdrawAddress,\n uint256 amount\n ) public onlyOwner {\n _entryPoint.withdrawTo(withdrawAddress, amount);\n }\n\n /**\n * Return current paymaster's deposit on the entryPoint.\n */\n function getDeposit() public view returns (uint256) {\n return _entryPoint.balanceOf(address(this));\n }\n\n /**\n * Validate the call is made from a valid entrypoint\n */\n function _requireFromEntryPoint() internal virtual {\n require(msg.sender == address(_entryPoint),\n NotFromEntryPoint(\n msg.sender,\n address(this),\n address(entryPoint())\n )\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 error Eip7702SenderWithoutCode(address sender);\n error Eip7702SenderNotDelegate(address sender);\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, Eip7702SenderWithoutCode(sender));\n revert Eip7702SenderNotDelegate(sender);\n }\n return address(bytes20(senderCode << 24));\n }\n}\n" + }, + "contracts/core/Helpers.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.28;\nimport \"./UserOperationLib.sol\";\n\n/* solhint-disable no-inline-assembly */\n\nusing UserOperationLib for bytes;\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 */\nfunction 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 * @notice Computes the Keccak-256 hash of a slice of calldata, followed by an 8-byte suffix.\n * This function copies the first `len` bytes from the given calldata array `data` into memory.\n * The assembly code is equivalent to:\n * keccak256(abi.encodePacked(data[0:len], suffix))\n * But more efficient, and doesn't leave the copied data in memory.\n *\n * @param data Calldata byte array to read from.\n * @param len Number of bytes to copy from `data` starting at its offset.\n * @param suffix 8-byte value appended to the data bytes before hashing.\n *\n * @return ret The hash of (data[0:len] || suffix).\n */\nfunction calldataKeccakWithSuffix(bytes calldata data, uint256 len, bytes8 suffix) pure returns (bytes32 ret) {\n assembly (\"memory-safe\") {\n let mem := mload(0x40)\n calldatacopy(mem, data.offset, len)\n mstore(add(mem, len), suffix)\n len := add(len, 8)\n ret := keccak256(mem, len)\n }\n}\n\n/**\n * Keccak function over paymaster data.\n * If data ends with `PAYMASTER_SIG_MAGIC`, then\n * read the previous 2 bytes as pmSignatureLength,\n * and ignore this suffix from the hash.\n * This means that the trailing pmSignatureLength+10 bytes are not covered by the UserOpHash, and thus are not signed.\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 */\nfunction paymasterDataKeccak(bytes calldata data) pure returns (bytes32 ret) {\n uint256 pmSignatureLength = data.getPaymasterSignatureLength();\n if (pmSignatureLength > 0) {\n unchecked {\n //keccak everything up to the paymasterSignature, but still append the sig magic.\n return calldataKeccakWithSuffix(data, data.length - (pmSignatureLength + UserOperationLib.PAYMASTER_SUFFIX_LEN), UserOperationLib.PAYMASTER_SIG_MAGIC);\n }\n }\n return calldataKeccak(data);\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 virtual 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 virtual 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\n/* solhint-disable avoid-low-level-calls */\n/* solhint-disable gas-calldata-parameters */\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 error NotFromEntryPoint(address msgSender, address entity, address entryPoint);\n\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, NotFromEntryPoint(msg.sender, address(this), 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, NotFromEntryPoint(msg.sender, address(this), 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/Stakeable.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.28;\n\nimport \"../interfaces/IEntryPoint.sol\";\nimport \"@openzeppelin/contracts/access/Ownable2Step.sol\";\n\n/**\n * @title Stakeable\n * @notice Helper that lets a contract add stake on the configured EntryPoint\n * for itself. Intended for factories or paymasters so their owner can call\n * the contract directly instead of interacting with EntryPoint.\n */\nabstract contract Stakeable is Ownable2Step {\n /**\n * @dev Implementations must supply the EntryPoint instance that should receive the stake.\n */\n function entryPoint() public view virtual returns (IEntryPoint);\n\n /**\n * Add stake for this contract.\n * This method can also carry eth value to add to the current stake.\n * @param unstakeDelaySec - The unstake delay for this contract. Can only be increased.\n */\n function addStake(uint32 unstakeDelaySec) external payable onlyOwner {\n entryPoint().addStake{value: msg.value}(unstakeDelaySec);\n }\n\n /**\n * Unlock the stake, in order to withdraw it.\n * The contract can't serve requests once unlocked, until it calls addStake again\n */\n function unlockStake() external onlyOwner {\n entryPoint().unlockStake();\n }\n\n /**\n * Withdraw the entire contract's stake.\n * stake must be unlocked first (and then wait for the unstakeDelay to be over)\n * @param withdrawAddress - The address to send withdrawn value.\n */\n function withdrawStake(address payable withdrawAddress) external onlyOwner {\n entryPoint().withdrawStake(withdrawAddress);\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 virtual 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 virtual 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 virtual view returns (uint256) {\n return deposits[account].deposit;\n }\n\n receive() external payable {\n depositTo(msg.sender);\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 virtual 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 virtual 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 virtual payable {\n DepositInfo storage info = deposits[msg.sender];\n require(unstakeDelaySec > 0, InvalidUnstakeDelay(unstakeDelaySec, info.unstakeDelaySec));\n require(\n unstakeDelaySec >= info.unstakeDelaySec,\n InvalidUnstakeDelay(unstakeDelaySec, info.unstakeDelaySec)\n );\n uint256 stake = info.stake + msg.value;\n require(stake > 0, InvalidStake(msg.value, info.stake));\n require(stake <= type(uint112).max, InvalidStake(msg.value, info.stake));\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 virtual {\n DepositInfo storage info = deposits[msg.sender];\n require(info.unstakeDelaySec != 0, NotStaked(info.stake, info.unstakeDelaySec, info.staked));\n require(info.staked, NotStaked(info.stake, info.unstakeDelaySec, info.staked));\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 virtual {\n DepositInfo storage info = deposits[msg.sender];\n uint256 stake = info.stake;\n require(stake > 0, NotStaked(info.stake, info.unstakeDelaySec, info.staked));\n require(info.withdrawTime > 0, StakeNotUnlocked(info.withdrawTime, block.timestamp));\n require(\n info.withdrawTime <= block.timestamp,\n WithdrawalNotDue(info.withdrawTime, block.timestamp)\n );\n info.unstakeDelaySec = 0;\n info.withdrawTime = 0;\n info.stake = 0;\n emit StakeWithdrawn(msg.sender, withdrawAddress, stake);\n (bool success, bytes memory ret) = withdrawAddress.call{value: stake}(\"\");\n require(success, StakeWithdrawalFailed(msg.sender, withdrawAddress, stake, ret));\n }\n\n /// @inheritdoc IStakeManager\n function withdrawTo(\n address payable withdrawAddress,\n uint256 withdrawAmount\n ) external virtual {\n DepositInfo storage info = deposits[msg.sender];\n uint256 currentDeposit = info.deposit;\n require(withdrawAmount <= currentDeposit, InsufficientDeposit(currentDeposit, withdrawAmount));\n info.deposit = currentDeposit - withdrawAmount;\n emit Withdrawn(msg.sender, withdrawAddress, withdrawAmount);\n (bool success, bytes memory ret) = withdrawAddress.call{value: withdrawAmount}(\"\");\n require(success, DepositWithdrawalFailed(msg.sender, withdrawAddress, withdrawAmount, ret));\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 \"./Helpers.sol\";\n\n/**\n * Utility functions helpful when working with UserOperation structs.\n */\nlibrary UserOperationLib {\n\n error InvalidPaymasterSignatureLength(uint256 dataLength, uint256 pmSignatureLength);\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 uint256 constant internal PAYMASTER_SIG_MAGIC_LEN = 8;\n uint256 constant internal PAYMASTER_SUFFIX_LEN = PAYMASTER_SIG_MAGIC_LEN + 2; // suffix length (signature length + magic)\n bytes8 constant internal PAYMASTER_SIG_MAGIC = 0x22e325a297439656; // keccak(\"PaymasterSignature\")[:8]\n uint256 constant internal MIN_PAYMASTER_DATA_WITH_SUFFIX_LEN = PAYMASTER_DATA_OFFSET + PAYMASTER_SUFFIX_LEN; // minimum length of paymasterData that can contain a paymaster signature.\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 // solhint-disable-next-line gas-small-strings\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 = paymasterDataKeccak(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 * return the length of the paymaster signature appended in paymasterAndData.\n * return 0 if no signature.\n * note that this signature is not part of the userOpHash, and thus not signed by the user.\n */\n function getPaymasterSignatureLength(\n bytes calldata paymasterAndData\n ) internal pure returns (uint256 paymasterSignatureLength) {\n unchecked {\n uint256 dataLength = paymasterAndData.length;\n if (dataLength < MIN_PAYMASTER_DATA_WITH_SUFFIX_LEN) {\n return 0;\n }\n bytes8 suffix8 = bytes8(paymasterAndData[dataLength - PAYMASTER_SIG_MAGIC_LEN : dataLength]);\n if (suffix8 != PAYMASTER_SIG_MAGIC) {\n return 0;\n }\n uint256 pmSignatureLength = uint16(bytes2(paymasterAndData[dataLength - PAYMASTER_SUFFIX_LEN :]));\n\n if (pmSignatureLength > dataLength - MIN_PAYMASTER_DATA_WITH_SUFFIX_LEN) {\n // paymasterSignature cannot extend before the paymasterData\n revert InvalidPaymasterSignatureLength(dataLength, pmSignatureLength);\n }\n return pmSignatureLength;\n }\n }\n\n /**\n * return the paymasterData that is signed by the user's signature\n * this data excludes the paymaster signature appended at the end of paymasterAndData\n */\n function getSignedPaymasterData(\n bytes calldata paymasterAndData\n ) internal pure returns (bytes calldata signedPaymasterData) {\n uint256 sigLen = getPaymasterSignatureLength(paymasterAndData);\n uint256 paymasterDataLen = paymasterAndData.length;\n if (sigLen != 0) {\n paymasterDataLen -= (sigLen + PAYMASTER_SUFFIX_LEN);\n }\n return paymasterAndData[PAYMASTER_DATA_OFFSET : paymasterDataLen];\n }\n\n /**\n * decodes dynamic signature appended to paymasterAndData\n * note that this signature is not part of the userOpHash, and thus not signed by the user.\n * @param paymasterAndData - The paymasterAndData field of the user operation\n * @return pmSig the paymaster-specific signature (may be empty)\n */\n function getPaymasterSignature(bytes calldata paymasterAndData\n ) internal pure returns (bytes calldata pmSig) {\n uint256 len = getPaymasterSignatureLength(paymasterAndData);\n return getPaymasterSignatureWithLength(paymasterAndData, len);\n }\n\n /**\n * decodes dynamic signature appended to paymasterAndData\n * Assumes the length field is valid, and was obtained from getPaymasterSignatureLength\n * @param paymasterAndData - The paymasterAndData field of the user operation\n * @param paymasterSignatureLength - length of the signature (as returned by getPaymasterSignatureLength)\n * @return pmSig the paymaster-specific signature (may be empty)\n */\n function getPaymasterSignatureWithLength(\n bytes calldata paymasterAndData, uint256 paymasterSignatureLength\n ) internal pure returns (bytes calldata pmSig) {\n if (paymasterSignatureLength == 0) {\n return paymasterAndData[0 : 0];\n }\n uint256 dataLen = paymasterAndData.length;\n unchecked {\n uint256 pmSigEnd = dataLen - PAYMASTER_SUFFIX_LEN;\n uint256 pmSigBegin = pmSigEnd - paymasterSignatureLength;\n return paymasterAndData[pmSigBegin : pmSigEnd];\n }\n }\n\n /**\n * encode the paymaster signature as suffix to append to paymasterAndData\n * This method is a reference for off-chain encoding of paymaster signature.\n */\n function encodePaymasterSignature(bytes calldata paymasterSignature) internal pure returns (bytes memory) {\n uint256 len = paymasterSignature.length;\n if (len == 0) {\n return \"\";\n }\n\n return abi.encodePacked(\n paymasterSignature,\n uint16(len),\n PAYMASTER_SIG_MAGIC\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 * Account \"sender\" already exists and the 'initCode' was ignored.\n * @param userOpHash - The current userOp. UserOperationEvent will follow.\n * @param sender - The account that was supposed to be deployed.\n * @param unusedFactory - The factory contract that was not used but was specified in the 'initCode'.\n */\n event IgnoredInitCode(\n bytes32 indexed userOpHash,\n address indexed sender,\n address unusedFactory\n );\n\n /**\n * Account \"sender\" is an EIP-7702 account that was initialized during this UserOperation.\n * @param userOpHash - The current userOp. UserOperationEvent will follow.\n * @param sender - The account that was supposed to be deployed.\n */\n event EIP7702AccountInitialized(\n bytes32 indexed userOpHash,\n address indexed sender,\n address indexed delegate\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 error InvalidBeneficiary(address beneficiary);\n error FailedSendToBeneficiary(address beneficiary, uint256 amount, bytes revertData);\n error InternalFunction();\n error InvalidPaymasterData(uint256 paymasterAndDataLength);\n error InvalidPaymaster(address paymaster);\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 * Allows the AA-aware contracts to query the hash of the currently running UserOperation.\n * @return hash - the hash of the currently running UserOperation, or 0 if none.\n */\n function getCurrentUserOpHash() 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/IEntryPointSimulations.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.28;\n\nimport \"./PackedUserOperation.sol\";\nimport \"./IEntryPoint.sol\";\n\ninterface IEntryPointSimulations is IEntryPoint {\n // Return value of simulateHandleOp.\n struct ExecutionResult {\n uint256 preOpGas;\n uint256 paid;\n uint256 accountValidationData;\n uint256 paymasterValidationData;\n bool targetSuccess;\n bytes targetResult;\n }\n\n /**\n * Returned aggregated signature info:\n * The aggregator returned by the account, and its current stake.\n */\n struct AggregatorStakeInfo {\n address aggregator;\n StakeInfo stakeInfo;\n }\n\n /**\n * Successful result from simulateValidation.\n * If the account returns a signature aggregator the \"aggregatorInfo\" struct is filled in as well.\n * @param returnInfo Gas and time-range returned values\n * @param senderInfo Stake information about the sender\n * @param factoryInfo Stake information about the factory (if any)\n * @param paymasterInfo Stake information about the paymaster (if any)\n * @param aggregatorInfo Signature aggregation info (if the account requires signature aggregator)\n * Bundler MUST use it to verify the signature, or reject the UserOperation.\n */\n struct ValidationResult {\n ReturnInfo returnInfo;\n StakeInfo senderInfo;\n StakeInfo factoryInfo;\n StakeInfo paymasterInfo;\n AggregatorStakeInfo aggregatorInfo;\n }\n\n /**\n * Simulate a call to account.validateUserOp and paymaster.validatePaymasterUserOp.\n * @dev The node must also verify it doesn't use banned opcodes, and that it doesn't reference storage\n * outside the account's data.\n * @param userOp - The user operation to validate.\n * @return the validation result structure\n */\n function simulateValidation(\n PackedUserOperation calldata userOp\n )\n external\n returns (\n ValidationResult memory\n );\n\n /**\n * Simulate full execution of a UserOperation (including both validation and target execution)\n * It performs full validation of the UserOperation, but ignores signature error.\n * An optional target address is called after the userop succeeds,\n * and its value is returned (before the entire call is reverted).\n * Note that in order to collect the the success/failure of the target call, it must be executed\n * with trace enabled to track the emitted events.\n * @param op The UserOperation to simulate.\n * @param target - If nonzero, a target address to call after userop simulation. If called,\n * the targetSuccess and targetResult are set to the return from that call.\n * @param targetCallData - CallData to pass to target address.\n * @return the execution result structure\n */\n function simulateHandleOp(\n PackedUserOperation calldata op,\n address target,\n bytes calldata targetCallData\n )\n external\n returns (\n ExecutionResult memory\n );\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 error InvalidUnstakeDelay(uint256 newUnstakeDelaySec, uint256 currentUnstakeDelaySec);\n error InvalidStake(uint256 msgValue, uint256 currentStake);\n error NotStaked(uint256 currentStake, uint256 unstakeDelaySec, bool staked);\n error InsufficientDeposit(uint256 currentDeposit, uint256 withdrawAmount);\n error StakeNotUnlocked(uint256 withdrawTime, uint256 blockTimestamp);\n error WithdrawalNotDue(uint256 withdrawTime, uint256 blockTimestamp);\n error StakeWithdrawalFailed(address account, address withdrawAddress, uint256 amount, bytes revertReason);\n error DepositWithdrawalFailed(address account, address withdrawAddress, uint256 amount, bytes revertReason);\n\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 *\n *\n * Field layout (enforced on-chain by EntryPoint):\n * - sender: must already be deployed, or be the address that `initCode` will deploy; for EIP-7702 onboarding, `initCode = 0x7702 || optionalPayload`\n * and `sender.code` must begin `0xef0100 || delegate`.\n * - nonce = uint192(key) || uint64(sequence); EntryPoint tracks sequential values of `sequence` separately for each `key` value.\n * - initCode:\n * * non-7702: `initCode = factory(20) || factoryCalldata`; the factory must return `sender` and deploy code.\n * * 7702: `0x7702` (magic prefix), optionally padded to 20 bytes and followed by `initizlizationCode`. This optional payload is executed on `sender` to finalise delegate setup.\n * - callData: executed verbatim; if it starts with `IAccountExecute.executeUserOp.selector` (0x8dd7712f), EntryPoint wraps and forwards `(userOp, userOpHash)`.\n * - accountGasLimits =`uint128(verificationGasLimit) || uint128(callGasLimit)`\n * - gasFees = `uint128(maxPriorityFeePerGas) || uint128(maxFeePerGas)`\n * - paymasterAndData (if non-empty) = `paymaster(20) || verificationGasLimit(16) || postOpGasLimit(16) || paymasterData`\n * * an optional paymasterSignature may be added by appending:\n * `paymasterSignature || uint16(paymasterSignature.length) || PAYMASTER_SIG_MAGIC (0x22e325a297439656)`\n * - signature: Used by the account to validate the UserOperation against the `userOpHash`.\n * The hash covers all UserOperation fields, except `signature` and `paymasterSignature`\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/legacy/v06/IAccount06.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.28;\n\nimport \"./UserOperation06.sol\";\n\ninterface IAccount06 {\n\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 able to make the call.\n * The excess is left as a deposit in the entrypoint, for future calls.\n * can be withdrawn anytime using \"entryPoint.withdrawTo()\"\n * In case there is a paymaster in the request (or the current deposit is high enough), this value will be zero.\n * @return validationData packaged ValidationData structure. use `_packValidationData` and `_unpackValidationData` to encode and decode\n * <20-byte> sigAuthorizer - 0 for valid signature, 1 to mark signature failure,\n * otherwise, an address of an \"authorizer\" contract.\n * <6-byte> validUntil - last timestamp this operation is valid. 0 for \"indefinite\"\n * <6-byte> validAfter - first timestamp this operation is valid\n * If an account doesn't use time-range, it is enough to 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(UserOperation06 calldata userOp, bytes32 userOpHash, uint256 missingAccountFunds)\n external returns (uint256 validationData);\n}\n" + }, + "contracts/legacy/v06/IAggregator06.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.28;\n\nimport \"./UserOperation06.sol\";\n\n/**\n * Aggregated Signatures validator.\n */\ninterface IAggregator06 {\n\n /**\n * validate aggregated signature.\n * revert if the aggregated signature does not match the given list of operations.\n */\n function validateSignatures(UserOperation06[] calldata userOps, bytes calldata signature) external view;\n\n /**\n * validate signature of a single userOp\n * This method is should be called by bundler after EntryPoint.simulateValidation() returns (reverts) with ValidationResultWithAggregation\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(UserOperation06 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 perform this aggregation\n * @param userOps array of UserOperations to collect the signatures from.\n * @return aggregatedSignature the aggregated signature\n */\n function aggregateSignatures(UserOperation06[] calldata userOps) external view returns (bytes memory aggregatedSignature);\n}\n" + }, + "contracts/legacy/v06/IEntryPoint06.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 \"./UserOperation06.sol\";\nimport \"./IStakeManager06.sol\";\nimport \"./IAggregator06.sol\";\nimport \"./INonceManager06.sol\";\n\ninterface IEntryPoint is IStakeManager06, INonceManager06 {\n\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, validation and execution).\n */\n event UserOperationEvent(bytes32 indexed userOpHash, address indexed sender, address indexed paymaster, uint256 nonce, bool success, uint256 actualGasCost, uint256 actualGasUsed);\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(bytes32 indexed userOpHash, address indexed sender, address factory, address paymaster);\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) call to \"callData\".\n */\n event UserOperationRevertReason(bytes32 indexed userOpHash, address indexed sender, uint256 nonce, bytes revertReason);\n\n /**\n * an event emitted by handleOps(), 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 */\n event SignatureAggregatorChanged(address indexed aggregator);\n\n /**\n * a custom revert error of handleOps, to identify the offending op.\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\n * The string starts with a unique code \"AAmn\", 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 * Should be caught in off-chain handleOps simulation and not happen on-chain.\n * Useful for mitigating DoS attempts against batchers or for troubleshooting of factory/account/paymaster reverts.\n */\n error FailedOp(uint256 opIndex, string reason);\n\n /**\n * error case when a signature aggregator fails to verify the aggregated signature it had created.\n */\n error SignatureValidationFailed(address aggregator);\n\n /**\n * Successful result from simulateValidation.\n * @param returnInfo gas and time-range returned values\n * @param senderInfo stake information about the sender\n * @param factoryInfo stake information about the factory (if any)\n * @param paymasterInfo stake information about the paymaster (if any)\n */\n error ValidationResult(ReturnInfo returnInfo,\n StakeInfo senderInfo, StakeInfo factoryInfo, StakeInfo paymasterInfo);\n\n /**\n * Successful result from simulateValidation, if the account returns a signature aggregator\n * @param returnInfo gas and time-range returned values\n * @param senderInfo stake information about the sender\n * @param factoryInfo stake information about the factory (if any)\n * @param paymasterInfo stake information about the paymaster (if any)\n * @param aggregatorInfo signature aggregation info (if the account requires signature aggregator)\n * bundler MUST use it to verify the signature, or reject the UserOperation\n */\n error ValidationResultWithAggregation(ReturnInfo returnInfo,\n StakeInfo senderInfo, StakeInfo factoryInfo, StakeInfo paymasterInfo,\n AggregatorStakeInfo aggregatorInfo);\n\n /**\n * return value of getSenderAddress\n */\n error SenderAddressResult(address sender);\n\n /**\n * return value of simulateHandleOp\n */\n error ExecutionResult(uint256 preOpGas, uint256 paid, uint48 validAfter, uint48 validUntil, bool targetSuccess, bytes targetResult);\n\n // UserOps handled, per aggregator\n struct UserOpsPerAggregator {\n UserOperation06[] userOps;\n\n // aggregator address\n IAggregator06 aggregator;\n // aggregated signature\n bytes signature;\n }\n\n /**\n * Execute a batch of UserOperation.\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(UserOperation06[] calldata ops, address payable beneficiary) 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), the entrypoint and the chainid.\n */\n function getUserOpHash(UserOperation06 calldata userOp) external view returns (bytes32);\n\n /**\n * Simulate a call to account.validateUserOp and paymaster.validatePaymasterUserOp.\n * @dev this method always revert. Successful result is ValidationResult error. other errors are failures.\n * @dev The node must also verify it doesn't use banned opcodes, and that it doesn't reference storage outside the account's data.\n * @param userOp the user operation to validate.\n */\n function simulateValidation(UserOperation06 calldata userOp) external;\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 sigFailed validateUserOp's (or paymaster's) signature check failed\n * @param validAfter - first timestamp this UserOp is valid (merging account and paymaster time-range)\n * @param validUntil - last timestamp this UserOp is valid (merging account and paymaster time-range)\n * @param paymasterContext returned by validatePaymasterUserOp (to be passed into postOp)\n */\n struct ReturnInfo {\n uint256 preOpGas;\n uint256 prefund;\n bool sigFailed;\n uint48 validAfter;\n uint48 validUntil;\n bytes paymasterContext;\n }\n\n /**\n * returned aggregated signature info.\n * the aggregator returned by the account, and its current stake.\n */\n struct AggregatorStakeInfo {\n address aggregator;\n StakeInfo stakeInfo;\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 * @param initCode the constructor code to be passed into the UserOperation.\n */\n function getSenderAddress(bytes memory initCode) external;\n\n\n /**\n * simulate full execution of a UserOperation (including both validation and target execution)\n * this method will always revert with \"ExecutionResult\".\n * it performs full validation of the UserOperation, but ignores signature error.\n * an optional target address is called after the userop succeeds, and its value is returned\n * (before the entire call is reverted)\n * Note that in order to collect the the success/failure of the target call, it must be executed\n * with trace enabled to track the emitted events.\n * @param op the UserOperation to simulate\n * @param target if nonzero, a target address to call after userop simulation. If called, the targetSuccess and targetResult\n * are set to the return from that call.\n * @param targetCallData callData to pass to target address\n */\n function simulateHandleOp(UserOperation06 calldata op, address target, bytes calldata targetCallData) external;\n}\n" + }, + "contracts/legacy/v06/INonceManager06.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.28;\n\ninterface INonceManager06 {\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 function incrementNonce(uint192 key) external;\n}\n" + }, + "contracts/legacy/v06/IPaymaster06.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.28;\n\nimport \"./UserOperation06.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 IPaymaster06 {\n\n enum PostOpMode {\n opSucceeded, // user op succeeded\n opReverted, // user op reverted. still has to pay for gas.\n postOpReverted // user op succeeded, but caused postOp to revert. Now it's a 2nd call, after user's op was deliberately reverted.\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\n * zero length to signify postOp is not required.\n * @return validationData signature and time-range of this operation, encoded the same as the return value of validateUserOperation\n * <20-byte> sigAuthorizer - 0 for valid signature, 1 to mark signature failure,\n * otherwise, an address of an \"authorizer\" contract.\n * <6-byte> validUntil - last timestamp this operation is valid. 0 for \"indefinite\"\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(UserOperation06 calldata userOp, bytes32 userOpHash, 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. still has to pay for gas.\n * postOpReverted - user op succeeded, but caused postOp (in mode=opSucceeded) to revert.\n * Now this is the 2nd call, after user's op was deliberately reverted.\n * @param context - the context value returned by validatePaymasterUserOp\n * @param actualGasCost - actual gas used so far (without this postOp call).\n */\n function postOp(PostOpMode mode, bytes calldata context, uint256 actualGasCost) external;\n}\n" + }, + "contracts/legacy/v06/IStakeManager06.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 IStakeManager06 {\n\n event Deposited(\n address indexed account,\n uint256 totalDeposit\n );\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(\n address indexed account,\n uint256 withdrawTime\n );\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,staked, stake) fit into one cell (used during handleOps)\n * and the rest fit into a 2nd cell.\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 uint112 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 /// @return info - full deposit information of given account\n function getDepositInfo(address account) external view returns (DepositInfo memory info);\n\n /// @return the deposit (for gas payment) of the account\n function balanceOf(address account) external view returns (uint256);\n\n /**\n * add to the deposit of the given account\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(address payable withdrawAddress, uint256 withdrawAmount) external;\n}\n" + }, + "contracts/legacy/v06/UserOperation06.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 callGasLimit the gas limit passed to the callData method call.\n * @param verificationGasLimit gas used for validateUserOp and validatePaymasterUserOp.\n * @param preVerificationGas gas not calculated by the handleOps method, but added to the gas paid. Covers batch overhead.\n * @param maxFeePerGas same as EIP-1559 gas parameter.\n * @param maxPriorityFeePerGas same as EIP-1559 gas parameter.\n * @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.\n * @param signature sender-verified signature over the entire request, the EntryPoint address and the chain ID.\n */\nstruct UserOperation06 {\n address sender;\n uint256 nonce;\n bytes initCode;\n bytes callData;\n uint256 callGasLimit;\n uint256 verificationGasLimit;\n uint256 preVerificationGas;\n uint256 maxFeePerGas;\n uint256 maxPriorityFeePerGas;\n bytes paymasterAndData;\n bytes signature;\n}\n" + }, + "contracts/test/GasCalcPaymasterWithPostOp.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0\npragma solidity ^0.8.28;\n\nimport \"./TestPaymasterAcceptAll.sol\";\n/* solhint-disable no-empty-blocks */\n\n/**\n * test paymaster, that pays for everything, without any check.\n * explicitly returns a context, to test cost (for entrypoint) to call postOp\n */\ncontract GasCalcPaymasterWithPostOp is TestPaymasterAcceptAll {\n constructor(IEntryPoint _entryPoint) TestPaymasterAcceptAll(_entryPoint) {\n }\n\n function _validatePaymasterUserOp(PackedUserOperation calldata, bytes32, uint256)\n internal virtual override view\n returns (bytes memory context, uint256 validationData) {\n // return a context, to force a call for postOp.\n return (\"1\", SIG_VALIDATION_SUCCESS);\n }\n\n function _postOp(PostOpMode, bytes calldata, uint256 actualGasCost, uint256)\n internal override {\n }\n}\n" + }, + "contracts/test/MaliciousAccount.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0\npragma solidity ^0.8.28;\n\n/* solhint-disable gas-custom-errors */\n\nimport \"../interfaces/IAccount.sol\";\nimport \"../interfaces/IEntryPoint.sol\";\nimport \"../core/UserOperationLib.sol\";\nimport \"../core/Helpers.sol\";\n\ncontract MaliciousAccount is IAccount {\n using UserOperationLib for PackedUserOperation;\n IEntryPoint private ep;\n constructor(IEntryPoint _ep) payable {\n ep = _ep;\n }\n function validateUserOp(PackedUserOperation calldata userOp, bytes32, uint256 missingAccountFunds)\n external returns (uint256 validationData) {\n ep.depositTo{value: missingAccountFunds}(address(this));\n // Now calculate basefee per EntryPoint.getUserOpGasPrice() and compare it to the basefe we pass off-chain in the signature\n uint256 externalBaseFee = abi.decode(userOp.signature, (uint256));\n uint256 verificationGasLimit = userOp.unpackVerificationGasLimit();\n uint256 callGasLimit = userOp.unpackCallGasLimit();\n uint256 requiredGas = verificationGasLimit +\n callGasLimit +\n userOp.preVerificationGas;\n uint256 gasPrice = missingAccountFunds / requiredGas;\n uint256 maxPriorityFeePerGas = userOp.unpackMaxPriorityFeePerGas();\n uint256 basefee = gasPrice - maxPriorityFeePerGas;\n require (basefee == externalBaseFee, \"Revert after first validation\");\n return SIG_VALIDATION_SUCCESS;\n }\n}\n" + }, + "contracts/test/TestAggregatedAccount.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0\npragma solidity ^0.8.28;\n\nimport \"../accounts/SimpleAccount.sol\";\nimport \"../core/Helpers.sol\";\n\n/**\n * test aggregated-signature account.\n * works only with TestAggregatedSignature, which doesn't really check signature, but nonce sum\n * a true aggregated account should expose data (e.g. its public key) to the aggregator.\n */\ncontract TestAggregatedAccount is SimpleAccount {\n address public immutable aggregator;\n\n // The constructor is used only for the \"implementation\" and only sets immutable values.\n // Mutable value slots for proxy accounts are set by the 'initialize' function.\n constructor(IEntryPoint anEntryPoint, address anAggregator) SimpleAccount(anEntryPoint) {\n aggregator = anAggregator;\n }\n\n /// @inheritdoc SimpleAccount\n function initialize(address) public virtual override initializer {\n super._initialize(address(0));\n }\n\n function _validateSignature(PackedUserOperation calldata userOp, bytes32 userOpHash)\n internal override view returns (uint256 validationData) {\n (userOp, userOpHash);\n return _packValidationData(ValidationData(aggregator, 0, 0));\n }\n}\n" + }, + "contracts/test/TestAggregatedAccountFactory.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0\npragma solidity ^0.8.28;\n\nimport \"@openzeppelin/contracts/utils/Create2.sol\";\nimport \"@openzeppelin/contracts/proxy/ERC1967/ERC1967Proxy.sol\";\n\nimport \"./TestAggregatedAccount.sol\";\n\n/**\n * Based on SimpleAccountFactory.\n * Cannot be a subclass since both constructor and createAccount depend on the\n * constructor and initializer of the actual account contract.\n */\ncontract TestAggregatedAccountFactory {\n TestAggregatedAccount public immutable accountImplementation;\n\n constructor(IEntryPoint anEntryPoint, address anAggregator){\n accountImplementation = new TestAggregatedAccount(anEntryPoint, anAggregator);\n }\n\n /**\n * create an account, and return its address.\n * returns the address even if the account is already deployed.\n * Note that during UserOperation execution, this method is called only if the account is not deployed.\n * This method returns an existing account address so that entryPoint.getSenderAddress() would work even after account creation\n */\n function createAccount(address owner,uint256 salt) public returns (TestAggregatedAccount ret) {\n address addr = getAddress(owner, salt);\n uint256 codeSize = addr.code.length;\n if (codeSize > 0) {\n return TestAggregatedAccount(payable(addr));\n }\n ret = TestAggregatedAccount(payable(new ERC1967Proxy{salt : bytes32(salt)}(\n address(accountImplementation),\n abi.encodeCall(TestAggregatedAccount.initialize, (owner))\n )));\n }\n\n /**\n * calculate the counterfactual address of this account as it would be returned by createAccount()\n */\n function getAddress(address owner,uint256 salt) public view returns (address) {\n return Create2.computeAddress(bytes32(salt), keccak256(abi.encodePacked(\n type(ERC1967Proxy).creationCode,\n abi.encode(\n address(accountImplementation),\n abi.encodeCall(TestAggregatedAccount.initialize, (owner))\n )\n )));\n }\n}\n" + }, + "contracts/test/TestCallHandleOps.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0\npragma solidity ^0.8.28;\n\n/* solhint-disable avoid-low-level-calls */\n/* solhint-disable gas-custom-errors */\n\nimport \"../interfaces/IAccount.sol\";\nimport \"../interfaces/IEntryPoint.sol\";\nimport \"../core/Helpers.sol\";\n\ncontract TestCallHandleOps is IAccount {\n\n // for the single test where 'TestCallHandleOps' is also EIP-7702 delegated account\n function validateUserOp(\n PackedUserOperation calldata,\n bytes32,\n uint256 missingAccountFunds\n ) external returns (uint256 validationData) {\n (bool success,) = payable(msg.sender).call{value: missingAccountFunds}(\"\");\n require(success, \"prefund failed\");\n return SIG_VALIDATION_SUCCESS;\n }\n\n function callHandleOps(\n IEntryPoint entryPoint,\n PackedUserOperation[] memory ops,\n address payable beneficiary\n ) public {\n entryPoint.handleOps(ops, beneficiary);\n }\n\n function callHandleAggregatedOps(\n IEntryPoint entryPoint,\n IEntryPoint.UserOpsPerAggregator[] calldata opsPerAggregator,\n address payable beneficiary\n ) public {\n entryPoint.handleAggregatedOps(opsPerAggregator, beneficiary);\n }\n}\n" + }, + "contracts/test/TestCallHandleOpsInConstructor.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0\npragma solidity ^0.8.28;\n\nimport \"./TestCallHandleOps.sol\";\n\ncontract TestCallHandleOpsInConstructor is TestCallHandleOps {\n constructor(\n IEntryPoint entryPoint,\n PackedUserOperation[] memory ops,\n address payable beneficiary\n ) {\n callHandleOps(entryPoint, ops, beneficiary);\n }\n}\n" + }, + "contracts/test/TestCounter.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0\npragma solidity ^0.8.28;\n\n/* solhint-disable gas-custom-errors */\n\n// Sample \"receiver\" contract, for testing \"exec\" from account.\ncontract TestCounter {\n mapping(address => uint256) public counters;\n\n function count() public {\n counters[msg.sender] = counters[msg.sender] + 1;\n }\n\n function countFail() public pure {\n revert(\"count failed\");\n }\n\n function justemit() public {\n emit CalledFrom(msg.sender);\n }\n\n event CalledFrom(address sender);\n\n // Helper method to waste gas\n // repeat - waste gas on writing storage in a loop\n // junk - dynamic buffer to stress the function size.\n mapping(uint256 => uint256) public xxx;\n uint256 public offset;\n\n function gasWaster(uint256 repeat, string calldata /*junk*/) external {\n for (uint256 i = 1; i <= repeat; i++) {\n offset++;\n xxx[offset] = i;\n }\n }\n}\n" + }, + "contracts/test/TestCurrentUserOpHash.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0\npragma solidity ^0.8.28;\n\nimport \"../interfaces/IEntryPoint.sol\";\n\n// A test \"receiver\" contract for testing the \"getCurrentUserOpHash\" function.\ncontract TestCurrentUserOpHash {\n uint256 private counter;\n\n event GotCurrentUserOpHash(uint256 count, bytes32 userOpHash);\n\n function getCurrentUserOpHashFromEntryPoint(IEntryPoint entryPoint) public {\n bytes32 userOpHash = entryPoint.getCurrentUserOpHash();\n emit GotCurrentUserOpHash(counter++, userOpHash);\n }\n}\n" + }, + "contracts/test/TestEip7702DelegateAccount.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0\npragma solidity ^0.8.28;\n\n/* solhint-disable gas-custom-errors */\n\nimport \"../accounts/Simple7702Account.sol\";\n\ncontract TestEip7702DelegateAccount is Simple7702Account {\n\n bool public testInitCalled;\n\n constructor(IEntryPoint anEntryPoint) Simple7702Account(anEntryPoint) {}\n\n function testInit() public {\n testInitCalled = true;\n }\n\n function _validateSignature(\n PackedUserOperation calldata userOp,\n bytes32 userOpHash\n ) internal virtual override returns (uint256 validationData) {\n if (userOp.initCode.length > 20) {\n require(testInitCalled, \"testInit not called\");\n }\n return Simple7702Account._validateSignature(userOp, userOpHash);\n }\n}\n" + }, + "contracts/test/TestERC20.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0\npragma solidity ^0.8.28;\n\nimport \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\n\ncontract TestERC20 is ERC20 {\n uint8 private immutable __decimals;\n\n constructor(uint8 _decimals) ERC20(\"TestERC20\", \"T20\") {\n _mint(msg.sender, 1000000000000000000000000);\n __decimals = _decimals;\n }\n\n function decimals() public view override returns (uint8) {\n return __decimals;\n }\n\n function sudoMint(address _to, uint256 _amount) external {\n _mint(_to, _amount);\n }\n\n function sudoTransfer(address _from, address _to) external {\n _transfer(_from, _to, balanceOf(_from));\n }\n\n function sudoApprove(address _from, address _to, uint256 _amount) external {\n _approve(_from, _to, _amount);\n }\n}\n" + }, + "contracts/test/TestExecAccount.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0\npragma solidity ^0.8.28;\n\n/* solhint-disable avoid-low-level-calls */\n/* solhint-disable gas-custom-errors */\n\nimport \"@openzeppelin/contracts/proxy/ERC1967/ERC1967Proxy.sol\";\n\nimport \"../accounts/SimpleAccount.sol\";\nimport \"../interfaces/IAccountExecute.sol\";\n\n/**\n * a sample account with execUserOp.\n * Note that this account does nothing special with the userop, just extract\n * call to execute. In theory, such account can reference the signature, the hash, etc.\n */\ncontract TestExecAccount is SimpleAccount, IAccountExecute {\n\n constructor(IEntryPoint anEntryPoint) SimpleAccount(anEntryPoint){\n }\n\n event Executed(PackedUserOperation userOp, bytes innerCallRet);\n\n function executeUserOp(PackedUserOperation calldata userOp, bytes32 /*userOpHash*/) external {\n _requireForExecute();\n\n // read from the userOp.callData, but skip the \"magic\" prefix (executeUserOp sig),\n // which caused it to call this method.\n bytes calldata innerCall = userOp.callData[4 :];\n\n bytes memory innerCallRet;\n if (innerCall.length > 0) {\n (address target, bytes memory data) = abi.decode(innerCall, (address, bytes));\n bool success;\n (success, innerCallRet) = target.call(data);\n require(success, \"inner call failed\");\n }\n\n emit Executed(userOp, innerCallRet);\n }\n}\n\n" + }, + "contracts/test/TestExecAccountFactory.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0\npragma solidity ^0.8.28;\n\n/* solhint-disable avoid-low-level-calls */\n/* solhint-disable gas-custom-errors */\n\nimport \"@openzeppelin/contracts/utils/Create2.sol\";\n\nimport \"./TestExecAccount.sol\";\n\ncontract TestExecAccountFactory {\n TestExecAccount public immutable accountImplementation;\n\n constructor(IEntryPoint _entryPoint) {\n accountImplementation = new TestExecAccount(_entryPoint);\n }\n\n function createAccount(address owner, uint256 salt) public returns (address ret) {\n address addr = getAddress(owner, salt);\n uint256 codeSize = addr.code.length;\n if (codeSize > 0) {\n return addr;\n }\n ret = address(new ERC1967Proxy{salt: bytes32(salt)}(\n address(accountImplementation),\n abi.encodeCall(SimpleAccount.initialize, (owner))\n ));\n }\n\n /**\n * calculate the counterfactual address of this account as it would be returned by createAccount()\n */\n function getAddress(address owner, uint256 salt) public view returns (address) {\n return Create2.computeAddress(bytes32(salt), keccak256(abi.encodePacked(\n type(ERC1967Proxy).creationCode,\n abi.encode(\n address(accountImplementation),\n abi.encodeCall(SimpleAccount.initialize, (owner))\n )\n )));\n }\n}\n" + }, + "contracts/test/TestExpirePaymaster.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0\npragma solidity ^0.8.28;\n\nimport \"../core/BasePaymaster.sol\";\nimport \"../core/UserOperationLib.sol\";\nimport \"../core/Helpers.sol\";\n\n/**\n * test expiry mechanism: paymasterData encodes the \"validUntil\" and validAfter\" times\n */\ncontract TestExpirePaymaster is BasePaymaster {\n // solhint-disable no-empty-blocks\n constructor(IEntryPoint _entryPoint) BasePaymaster(_entryPoint)\n {}\n\n function _validatePaymasterUserOp(PackedUserOperation calldata userOp, bytes32 userOpHash, uint256 maxCost)\n internal virtual override view\n returns (bytes memory context, uint256 validationData) {\n (userOp, userOpHash, maxCost);\n (uint48 validAfter, uint48 validUntil) = abi.decode(userOp.paymasterAndData[PAYMASTER_DATA_OFFSET :], (uint48, uint48));\n validationData = _packValidationData(false, validUntil, validAfter);\n context = \"\";\n }\n}\n" + }, + "contracts/test/TestExpiryAccount.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0\npragma solidity ^0.8.28;\n\n/* solhint-disable gas-custom-errors */\n\nimport \"../accounts/SimpleAccount.sol\";\nimport \"../core/Helpers.sol\";\n\n/**\n * A test account, for testing expiry.\n * add \"temporary\" owners, each with a time range (since..till) times for each.\n * NOTE: this is not a full \"session key\" implementation: a real session key should probably limit\n * other things, like target contracts and methods to be called.\n * also, the \"since\" value is not really useful, only for testing the entrypoint.\n */\ncontract TestExpiryAccount is SimpleAccount {\n\n mapping(address => uint48) public ownerAfter;\n mapping(address => uint48) public ownerUntil;\n\n // solhint-disable-next-line no-empty-blocks\n constructor(IEntryPoint anEntryPoint) SimpleAccount(anEntryPoint) {}\n\n function initialize(address anOwner) public virtual override initializer {\n super._initialize(anOwner);\n addTemporaryOwner(anOwner, 0, type(uint48).max);\n }\n\n // As this is a test contract, no need for proxy, so no need to disable init\n // solhint-disable-next-line no-empty-blocks\n function _disableInitializers() internal override {}\n\n function addTemporaryOwner(address owner, uint48 _after, uint48 _until) public onlyOwner {\n require(_until > _after, \"wrong until/after\");\n ownerAfter[owner] = _after;\n ownerUntil[owner] = _until;\n }\n\n /// implement template method of BaseAccount\n function _validateSignature(PackedUserOperation calldata userOp, bytes32 userOpHash)\n internal override view returns (uint256 validationData) {\n address signer = ECDSA.recover(userOpHash,userOp.signature);\n uint48 _until = ownerUntil[signer];\n uint48 _after = ownerAfter[signer];\n\n // We have \"until\" value for all valid owners. so zero means \"invalid signature\"\n bool sigFailed = _until == 0;\n return _packValidationData(sigFailed, _until, _after);\n }\n}\n" + }, + "contracts/test/TestHelpers.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0\npragma solidity ^0.8.28;\n\nimport \"../core/Helpers.sol\";\n\ncontract TestHelpers {\n\n function parseValidationData(uint256 validationData) public pure returns (ValidationData memory) {\n return _parseValidationData(validationData);\n }\n\n function packValidationDataStruct(ValidationData memory data) public pure returns (uint256) {\n return _packValidationData(data);\n }\n\n function packValidationData(bool sigFailed, uint48 validUntil, uint48 validAfter) public pure returns (uint256) {\n return _packValidationData(sigFailed, validUntil, validAfter);\n }\n\n function getPaymasterSignatureLength(\n bytes calldata paymasterAndData\n ) public pure returns (uint256 paymasterSignatureLength) {\n return UserOperationLib.getPaymasterSignatureLength(paymasterAndData);\n }\n\n function getPaymasterSignatureWithLength(\n bytes calldata paymasterAndData, uint256 paymasterSignatureLength\n ) public pure returns (bytes calldata) {\n return UserOperationLib.getPaymasterSignatureWithLength(paymasterAndData, paymasterSignatureLength);\n }\n\n function encodePaymasterSignature(bytes calldata paymasterSignature) public pure returns (bytes memory) {\n return UserOperationLib.encodePaymasterSignature(paymasterSignature);\n }\n\n function _calldataKeccakWithSuffix(bytes calldata data, uint256 len, bytes8 suffix) public pure returns (bytes32 ret) {\n return calldataKeccakWithSuffix(data, len, suffix);\n }\n}\n" + }, + "contracts/test/TestPaymasterAcceptAll.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0\npragma solidity ^0.8.28;\n\nimport \"../core/BasePaymaster.sol\";\nimport \"../core/Helpers.sol\";\n\n/**\n * test paymaster, that pays for everything, without any check.\n */\ncontract TestPaymasterAcceptAll is BasePaymaster {\n\n constructor(IEntryPoint _entryPoint) BasePaymaster(_entryPoint) {\n // to support \"deterministic address\" factory\n // solhint-disable avoid-tx-origin\n if (tx.origin != msg.sender) {\n _transferOwnership(tx.origin);\n }\n\n }\n\n function _validatePaymasterUserOp(PackedUserOperation calldata userOp, bytes32 userOpHash, uint256 maxCost)\n internal virtual override view\n returns (bytes memory context, uint256 validationData) {\n (userOp, userOpHash, maxCost);\n return (\"\", SIG_VALIDATION_SUCCESS);\n }\n}\n" + }, + "contracts/test/TestPaymasterRevertCustomError.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0\npragma solidity ^0.8.28;\n\nimport \"../core/BasePaymaster.sol\";\n\n/**\n * test postOp revert with custom error\n */\nerror CustomError(string customReason);\n\ncontract TestPaymasterRevertCustomError is BasePaymaster {\n bytes32 private constant INNER_OUT_OF_GAS = hex\"deaddead\";\n\n enum RevertType {\n customError,\n entryPointError\n }\n\n RevertType private revertType;\n\n // solhint-disable no-empty-blocks\n constructor(IEntryPoint _entryPoint) BasePaymaster(_entryPoint)\n {}\n\n function _validatePaymasterUserOp(PackedUserOperation calldata userOp, bytes32, uint256)\n internal virtual override view\n returns (bytes memory context, uint256 validationData) {\n validationData = 0;\n context = abi.encodePacked(userOp.sender);\n }\n\n function setRevertType(RevertType _revertType) external {\n revertType = _revertType;\n }\n\n function _postOp(PostOpMode, bytes calldata, uint256, uint256) internal view override {\n if (revertType == RevertType.customError){\n // solhint-disable-next-line gas-small-strings\n revert CustomError(\"this is a long revert reason string we are looking for\");\n }\n else if (revertType == RevertType.entryPointError){\n // solhint-disable-next-line no-inline-assembly\n assembly {\n mstore(0, INNER_OUT_OF_GAS)\n revert(0, 32)\n }\n }\n }\n}\n" + }, + "contracts/test/TestPaymasterWithPostOp.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0\npragma solidity ^0.8.28;\n\n/* solhint-disable no-empty-blocks */\n\nimport \"./TestPaymasterAcceptAll.sol\";\n\n/**\n * test paymaster, that pays for everything, without any check.\n * explicitly returns a context, to test cost (for entrypoint) to call postOp\n */\ncontract TestPaymasterWithPostOp is TestPaymasterAcceptAll {\n event PostOpActualGasCost(uint256 actualGasCost, bytes context, bool isSame);\n\n bytes public theContext;\n\n constructor(IEntryPoint _entryPoint) TestPaymasterAcceptAll(_entryPoint) {\n setContext(\"1\");\n }\n\n function setContext(bytes memory _context) public {\n theContext = _context;\n }\n\n function _validatePaymasterUserOp(PackedUserOperation calldata, bytes32, uint256)\n internal virtual override view\n returns (bytes memory context, uint256 validationData) {\n // return a context, to force a call for postOp.\n return (theContext, SIG_VALIDATION_SUCCESS);\n }\n\n function _postOp(PostOpMode, bytes calldata context, uint256 actualGasCost, uint256)\n internal override {\n bool isSame = keccak256(context) == keccak256(theContext);\n emit PostOpActualGasCost(actualGasCost, context, isSame);\n\n }\n}\n" + }, + "contracts/test/TestPaymasterWithSig.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0\npragma solidity ^0.8.28;\n\nimport \"../core/BasePaymaster.sol\";\nimport \"../core/UserOperationLib.sol\";\nimport \"../core/Helpers.sol\";\n\n/* solhint-disable gas-custom-errors */\n\n/**\n * test paymaster sig:\n * a paymaster that handles different \"signature\" appended after the UserOperation was signed by the user.\n * valid signature is when the two uint256 numbers in the signature add to 100...\n */\ncontract TestPaymasterWithSig is BasePaymaster {\n\n // solhint-disable no-empty-blocks\n constructor(IEntryPoint _entryPoint) BasePaymaster(_entryPoint)\n {}\n\n function _validatePaymasterUserOp(PackedUserOperation calldata userOp, bytes32 userOpHash, uint256 maxCost)\n internal virtual override view\n returns (bytes memory context, uint256 validationData) {\n (userOpHash, maxCost);\n (uint256 testData) = abi.decode(UserOperationLib.getSignedPaymasterData(userOp.paymasterAndData), (uint256));\n require(testData & 0xff == 0x11, \"expected testData=0x11\");\n\n uint256 len = UserOperationLib.getPaymasterSignatureLength(userOp.paymasterAndData);\n require(len > 0, \"missing paymasterSig\");\n bytes calldata paymasterSignature = UserOperationLib.getPaymasterSignatureWithLength(userOp.paymasterAndData, len);\n (uint256 a, uint256 b) = abi.decode(paymasterSignature, (uint256, uint256));\n if (a + b != 100) {\n return (\"\", SIG_VALIDATION_FAILED);\n }\n return (\"\", SIG_VALIDATION_SUCCESS);\n }\n}\n" + }, + "contracts/test/TestRevertAccount.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0\npragma solidity ^0.8.28;\n\n/* solhint-disable no-inline-assembly */\n\nimport \"../accounts/SimpleAccount.sol\";\n\ncontract TestRevertAccount is IAccount {\n IEntryPoint private ep;\n constructor(IEntryPoint _ep) payable {\n ep = _ep;\n }\n\n function validateUserOp(PackedUserOperation calldata, bytes32, uint256 missingAccountFunds)\n external override returns (uint256 validationData) {\n ep.depositTo{value : missingAccountFunds}(address(this));\n return SIG_VALIDATION_SUCCESS;\n }\n\n function revertLong(uint256 length) public pure{\n assembly {\n revert(0, length)\n }\n }\n}\n" + }, + "contracts/test/TestSignatureAggregator.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0\npragma solidity ^0.8.28;\n\n/* solhint-disable gas-custom-errors */\n/* solhint-disable gas-small-strings */\n/* solhint-disable reason-string */\n\nimport \"../interfaces/IAggregator.sol\";\nimport \"../interfaces/IEntryPoint.sol\";\nimport \"../accounts/SimpleAccount.sol\";\n\n/**\n * test signature aggregator.\n * the aggregated signature is the SUM of the nonce fields..\n */\ncontract TestSignatureAggregator is IAggregator {\n\n /// @inheritdoc IAggregator\n function validateSignatures(PackedUserOperation[] calldata userOps, bytes calldata signature) external pure override {\n uint256 sum = 0;\n for (uint256 i = 0; i < userOps.length; i++) {\n uint256 nonce = userOps[i].nonce;\n sum += nonce;\n }\n require(signature.length == 32, \"TestSignatureValidator: sig must be uint256\");\n (uint256 sig) = abi.decode(signature, (uint256));\n require(sig == sum, \"TestSignatureValidator: aggregated signature mismatch (nonce sum)\");\n }\n\n /// @inheritdoc IAggregator\n function validateUserOpSignature(PackedUserOperation calldata)\n external pure returns (bytes memory) {\n return \"\";\n }\n\n /**\n * dummy test aggregator: sum all nonce values of UserOps.\n */\n function aggregateSignatures(PackedUserOperation[] calldata userOps) external pure returns (bytes memory aggregatedSignature) {\n uint256 sum = 0;\n for (uint256 i = 0; i < userOps.length; i++) {\n sum += userOps[i].nonce;\n }\n return abi.encode(sum);\n }\n\n /**\n * Calls the 'addStake' method of the EntryPoint. Forwards the entire msg.value to this call.\n * @param entryPoint - the EntryPoint to send the stake to.\n * @param delay - the new lock duration before the deposit can be withdrawn.\n */\n function addStake(IEntryPoint entryPoint, uint32 delay) external payable {\n entryPoint.addStake{value: msg.value}(delay);\n }\n}\n" + }, + "contracts/test/TestToken.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0\npragma solidity ^0.8.28;\n\nimport \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\n\ncontract TestToken is ERC20 {\n constructor ()\n // solhint-disable-next-line no-empty-blocks\n ERC20(\"TST\", \"TestToken\") {\n }\n\n function mint(address sender, uint256 amount) external {\n _mint(sender, amount);\n }\n}\n" + }, + "contracts/test/TestUniswap.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0\npragma solidity ^0.8.28;\n\n/* solhint-disable gas-custom-errors */\n\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport \"@uniswap/v3-periphery/contracts/interfaces/ISwapRouter.sol\";\n\nimport \"./TestWrappedNativeToken.sol\";\n\n/// @notice Very basic simulation of what Uniswap does with the swaps for the unit tests on the TokenPaymaster\n/// @dev Do not use to test any actual Uniswap interaction logic as this is way too simplistic\ncontract TestUniswap {\n TestWrappedNativeToken public weth;\n\n constructor(TestWrappedNativeToken _weth){\n weth = _weth;\n }\n\n event StubUniswapExchangeEvent(uint256 amountIn, uint256 amountOut, address tokenIn, address tokenOut);\n\n function exactOutputSingle(ISwapRouter.ExactOutputSingleParams calldata params) external returns (uint256) {\n uint256 amountIn = params.amountInMaximum - 5;\n emit StubUniswapExchangeEvent(\n amountIn,\n params.amountOut,\n params.tokenIn,\n params.tokenOut\n );\n IERC20(params.tokenIn).transferFrom(msg.sender, address(this), amountIn);\n IERC20(params.tokenOut).transfer(params.recipient, params.amountOut);\n return amountIn;\n }\n\n function exactInputSingle(ISwapRouter.ExactInputSingleParams calldata params) external returns (uint256) {\n uint256 amountOut = params.amountOutMinimum + 5;\n emit StubUniswapExchangeEvent(\n params.amountIn,\n amountOut,\n params.tokenIn,\n params.tokenOut\n );\n IERC20(params.tokenIn).transferFrom(msg.sender, address(this), params.amountIn);\n IERC20(params.tokenOut).transfer(params.recipient, amountOut);\n return amountOut;\n }\n\n /// @notice Simplified code copied from here:\n /// https://github.com/Uniswap/v3-periphery/blob/main/contracts/base/PeripheryPayments.sol#L19\n function unwrapWETH9(uint256 amountMinimum, address recipient) public payable {\n uint256 balanceWETH9 = weth.balanceOf(address(this));\n require(balanceWETH9 >= amountMinimum, \"Insufficient WETH9\");\n\n if (balanceWETH9 > 0) {\n weth.withdraw(balanceWETH9);\n payable(recipient).transfer(balanceWETH9);\n }\n }\n\n // solhint-disable-next-line no-empty-blocks\n receive() external payable {}\n}\n" + }, + "contracts/test/TestUtil.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0\npragma solidity ^0.8.28;\n\nimport \"../interfaces/PackedUserOperation.sol\";\nimport \"../core/Eip7702Support.sol\";\n\ncontract TestUtil {\n using UserOperationLib for PackedUserOperation;\n\n function encodeUserOp(PackedUserOperation calldata op) external pure returns (bytes memory){\n return op.encode(0);\n }\n\n function isEip7702InitCode(bytes calldata initCode) external pure returns (bool) {\n return Eip7702Support._isEip7702InitCode(initCode);\n }\n}\n" + }, + "contracts/test/TestWarmColdAccount.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0\npragma solidity ^0.8.28;\n\n/* solhint-disable no-inline-assembly */\n\nimport \"../interfaces/IEntryPoint.sol\";\nimport \"../interfaces/IAccount.sol\";\nimport \"../core/Helpers.sol\";\n\n// Using eip-2929 (https://eips.ethereum.org/EIPS/eip-2929) warm/cold storage access gas costs to detect simulation vs execution\n// COLD_ACCOUNT_ACCESS_COST == 2600, COLD_SLOAD_COST == 2100, WARM_STORAGE_READ_COST == 100\ncontract TestWarmColdAccount is IAccount {\n IEntryPoint private ep;\n uint256 public state = 1;\n constructor(IEntryPoint _ep) payable {\n ep = _ep;\n }\n\n function validateUserOp(PackedUserOperation calldata userOp, bytes32, uint256 missingAccountFunds)\n external override returns (uint256 validationData) {\n ep.depositTo{value : missingAccountFunds}(address(this));\n if (userOp.nonce == 1) {\n // can only succeed if storage is already warm\n this.touchStorage{gas: 1000}();\n } else if (userOp.nonce == 2) {\n address paymaster = address(bytes20(userOp.paymasterAndData[: 20]));\n // can only succeed if storage is already warm\n this.touchPaymaster{gas: 1000}(paymaster);\n }\n return SIG_VALIDATION_SUCCESS;\n }\n\n function touchStorage() public view returns (uint256) {\n return state;\n }\n\n function touchPaymaster(address paymaster) public view returns (uint256) {\n return paymaster.code.length;\n }\n}\n" + }, + "contracts/test/TestWrappedNativeToken.sol": { + "content": "// SPDX-License-Identifier:GPL-3.0\npragma solidity ^0.8.28;\n\n/* solhint-disable gas-custom-errors */\n\nimport \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\n\n/**\n * @notice The minimal \"Wrapped Ether\" ERC-20 token implementation.\n */\ncontract TestWrappedNativeToken is ERC20 {\n\n // solhint-disable-next-line no-empty-blocks\n constructor() ERC20(\"Wrapped Native Token\", \"wnTok\") {\n }\n\n receive() external payable {\n deposit();\n }\n\n function deposit() public payable {\n _mint(msg.sender, msg.value);\n }\n\n function withdraw(uint256 amount) public {\n _burn(msg.sender, amount);\n // solhint-disable-next-line avoid-low-level-calls\n (bool success,) = msg.sender.call{value:amount}(\"\");\n require(success, \"transfer failed\");\n }\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", + "viaIR": true, + "optimizer": { + "enabled": true, + "runs": 1000000 + }, + "outputSelection": { + "*": { + "*": [ + "abi", + "evm.bytecode", + "evm.deployedBytecode", + "evm.methodIdentifiers", + "metadata", + "devdoc", + "userdoc", + "storageLayout", + "evm.gasEstimates" + ], + "": [ + "ast" + ] + } + }, + "metadata": { + "useLiteralContent": true + } + } +} \ 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.9.0/funding.json similarity index 100% rename from dependencies/eth-infinitism-account-abstraction-0.8.0/funding.json rename to dependencies/eth-infinitism-account-abstraction-0.9.0/funding.json diff --git a/dependencies/eth-infinitism-account-abstraction-0.8.0/gascalc/0-init-gas-checker.ts b/dependencies/eth-infinitism-account-abstraction-0.9.0/gascalc/0-init-gas-checker.ts similarity index 100% rename from dependencies/eth-infinitism-account-abstraction-0.8.0/gascalc/0-init-gas-checker.ts rename to dependencies/eth-infinitism-account-abstraction-0.9.0/gascalc/0-init-gas-checker.ts diff --git a/dependencies/eth-infinitism-account-abstraction-0.8.0/gascalc/1-simple-wallet.gas.ts b/dependencies/eth-infinitism-account-abstraction-0.9.0/gascalc/1-simple-wallet.gas.ts similarity index 100% rename from dependencies/eth-infinitism-account-abstraction-0.8.0/gascalc/1-simple-wallet.gas.ts rename to dependencies/eth-infinitism-account-abstraction-0.9.0/gascalc/1-simple-wallet.gas.ts diff --git a/dependencies/eth-infinitism-account-abstraction-0.8.0/gascalc/2-paymaster.gas.ts b/dependencies/eth-infinitism-account-abstraction-0.9.0/gascalc/2-paymaster.gas.ts similarity index 100% rename from dependencies/eth-infinitism-account-abstraction-0.8.0/gascalc/2-paymaster.gas.ts rename to dependencies/eth-infinitism-account-abstraction-0.9.0/gascalc/2-paymaster.gas.ts diff --git a/dependencies/eth-infinitism-account-abstraction-0.8.0/gascalc/3-huge-tx-gas.ts b/dependencies/eth-infinitism-account-abstraction-0.9.0/gascalc/3-huge-tx-gas.ts similarity index 100% rename from dependencies/eth-infinitism-account-abstraction-0.8.0/gascalc/3-huge-tx-gas.ts rename to dependencies/eth-infinitism-account-abstraction-0.9.0/gascalc/3-huge-tx-gas.ts diff --git a/dependencies/eth-infinitism-account-abstraction-0.8.0/gascalc/4-paymaster-postop.gas.ts b/dependencies/eth-infinitism-account-abstraction-0.9.0/gascalc/4-paymaster-postop.gas.ts similarity index 100% rename from dependencies/eth-infinitism-account-abstraction-0.8.0/gascalc/4-paymaster-postop.gas.ts rename to dependencies/eth-infinitism-account-abstraction-0.9.0/gascalc/4-paymaster-postop.gas.ts diff --git a/dependencies/eth-infinitism-account-abstraction-0.8.0/gascalc/GasChecker.ts b/dependencies/eth-infinitism-account-abstraction-0.9.0/gascalc/GasChecker.ts similarity index 95% rename from dependencies/eth-infinitism-account-abstraction-0.8.0/gascalc/GasChecker.ts rename to dependencies/eth-infinitism-account-abstraction-0.9.0/gascalc/GasChecker.ts index 6ec53ba..2e0c973 100644 --- a/dependencies/eth-infinitism-account-abstraction-0.8.0/gascalc/GasChecker.ts +++ b/dependencies/eth-infinitism-account-abstraction-0.9.0/gascalc/GasChecker.ts @@ -110,11 +110,8 @@ export class GasChecker { } // generate the account "creation code" - accountInitCode (factory: SimpleAccountFactory, salt: BigNumberish): string { - return hexConcat([ - factory.address, - factory.interface.encodeFunctionData('createAccount', [this.accountOwner.address, salt]) - ]) + accountFactoryData (factory: SimpleAccountFactory, salt: BigNumberish): string { + return factory.interface.encodeFunctionData('createAccount', [this.accountOwner.address, salt]) } createdAccounts = new Set() @@ -133,14 +130,12 @@ export class GasChecker { defaultAbiCoder.encode(['address'], [this.entryPoint().address]) ]), 0, 2885201) debug('factaddr', factoryAddress) - const fact = SimpleAccountFactory__factory.connect(factoryAddress, globalSigner) + const factory = 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) + const addr = await factory.getAddress(this.accountOwner.address, salt) if (!this.createdAccounts.has(addr)) { const codeSize = await provider.getCode(addr).then(code => code.length) @@ -149,14 +144,15 @@ export class GasChecker { // not attempt to fill from blockchain. const op = signUserOp(await fillUserOp({ sender: addr, - initCode: this.accountInitCode(fact, salt), + factory: factory.address, + factoryData: this.accountFactoryData(factory, 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)) + }, this.entryPoint()), this.accountOwner, this.entryPoint().address, await provider.getNetwork().then(net => net.chainId)) creationOps.push(packUserOp(op)) } this.createdAccounts.add(addr) diff --git a/dependencies/eth-infinitism-account-abstraction-0.8.0/hardhat.config.ts b/dependencies/eth-infinitism-account-abstraction-0.9.0/hardhat.config.ts similarity index 88% rename from dependencies/eth-infinitism-account-abstraction-0.8.0/hardhat.config.ts rename to dependencies/eth-infinitism-account-abstraction-0.9.0/hardhat.config.ts index cc69649..fd05e9b 100644 --- a/dependencies/eth-infinitism-account-abstraction-0.8.0/hardhat.config.ts +++ b/dependencies/eth-infinitism-account-abstraction-0.9.0/hardhat.config.ts @@ -3,11 +3,9 @@ import '@typechain/hardhat' import { HardhatUserConfig, task } from 'hardhat/config' import 'hardhat-deploy' -import 'solidity-coverage' - import * as fs from 'fs' -const SALT = '0x0a59dbff790c23c976a548690c27297883cc66b4c67024f9117b0238995e35e9' +const SALT = '0x7702864008ddeab30aa67b7adc3d2653bc8d162714b1fe8fe4582df814f3bf61' process.env.SALT = process.env.SALT ?? SALT task('deploy', 'Deploy contracts') @@ -69,10 +67,4 @@ const config: HardhatUserConfig = { } } -// 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.9.0/reports/gas-checker.txt similarity index 88% rename from dependencies/eth-infinitism-account-abstraction-0.8.0/reports/gas-checker.txt rename to dependencies/eth-infinitism-account-abstraction-0.9.0/reports/gas-checker.txt index 0f00a17..daeceb8 100644 --- a/dependencies/eth-infinitism-account-abstraction-0.8.0/reports/gas-checker.txt +++ b/dependencies/eth-infinitism-account-abstraction-0.9.0/reports/gas-checker.txt @@ -2,9 +2,9 @@ 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 "simple" │ 31121 ║ ╟──────────────────────────┼────────╢ -║ gas estimate "big tx 5k" │ 114440 ║ +║ gas estimate "big tx 5k" │ 116566 ║ ╚══════════════════════════╧════════╝ ╔════════════════════════════════╤═══════╤═══════════════╤════════════════╤═════════════════════╗ @@ -12,36 +12,36 @@ ║ │ │ │ (delta for │ (compared to ║ ║ │ │ │ one UserOp) │ account.exec()) ║ ╟────────────────────────────────┼───────┼───────────────┼────────────────┼─────────────────────╢ -║ simple │ 1 │ 77452 │ │ ║ +║ simple │ 1 │ 77742 │ │ ║ ╟────────────────────────────────┼───────┼───────────────┼────────────────┼─────────────────────╢ -║ simple - diff from previous │ 2 │ │ 41508 │ 12509 ║ +║ simple - diff from previous │ 2 │ │ 41882 │ 10761 ║ ╟────────────────────────────────┼───────┼───────────────┼────────────────┼─────────────────────╢ -║ simple │ 10 │ 451096 │ │ ║ +║ simple │ 10 │ 454776 │ │ ║ ╟────────────────────────────────┼───────┼───────────────┼────────────────┼─────────────────────╢ -║ simple - diff from previous │ 11 │ │ 41565 │ 12566 ║ +║ simple - diff from previous │ 11 │ │ 41927 │ 10806 ║ ╟────────────────────────────────┼───────┼───────────────┼────────────────┼─────────────────────╢ -║ simple paymaster │ 1 │ 83158 │ │ ║ +║ simple paymaster │ 1 │ 83434 │ │ ║ ╟────────────────────────────────┼───────┼───────────────┼────────────────┼─────────────────────╢ -║ simple paymaster with diff │ 2 │ │ 39902 │ 10903 ║ +║ simple paymaster with diff │ 2 │ │ 40274 │ 9153 ║ ╟────────────────────────────────┼───────┼───────────────┼────────────────┼─────────────────────╢ -║ simple paymaster │ 10 │ 442507 │ │ ║ +║ simple paymaster │ 10 │ 446011 │ │ ║ ╟────────────────────────────────┼───────┼───────────────┼────────────────┼─────────────────────╢ -║ simple paymaster with diff │ 11 │ │ 39915 │ 10916 ║ +║ simple paymaster with diff │ 11 │ │ 40323 │ 9202 ║ ╟────────────────────────────────┼───────┼───────────────┼────────────────┼─────────────────────╢ -║ big tx 5k │ 1 │ 167230 │ │ ║ +║ big tx 5k │ 1 │ 167520 │ │ ║ ╟────────────────────────────────┼───────┼───────────────┼────────────────┼─────────────────────╢ -║ big tx - diff from previous │ 2 │ │ 130735 │ 16295 ║ +║ big tx - diff from previous │ 2 │ │ 131109 │ 14543 ║ ╟────────────────────────────────┼───────┼───────────────┼────────────────┼─────────────────────╢ -║ big tx 5k │ 10 │ 1343952 │ │ ║ +║ big tx 5k │ 10 │ 1347572 │ │ ║ ╟────────────────────────────────┼───────┼───────────────┼────────────────┼─────────────────────╢ -║ big tx - diff from previous │ 11 │ │ 130732 │ 16292 ║ +║ big tx - diff from previous │ 11 │ │ 131142 │ 14576 ║ ╟────────────────────────────────┼───────┼───────────────┼────────────────┼─────────────────────╢ -║ paymaster+postOp │ 1 │ 84501 │ │ ║ +║ paymaster+postOp │ 1 │ 84782 │ │ ║ ╟────────────────────────────────┼───────┼───────────────┼────────────────┼─────────────────────╢ -║ paymaster+postOp with diff │ 2 │ │ 41294 │ 12295 ║ +║ paymaster+postOp with diff │ 2 │ │ 41659 │ 10538 ║ ╟────────────────────────────────┼───────┼───────────────┼────────────────┼─────────────────────╢ -║ paymaster+postOp │ 10 │ 456054 │ │ ║ +║ paymaster+postOp │ 10 │ 459644 │ │ ║ ╟────────────────────────────────┼───────┼───────────────┼────────────────┼─────────────────────╢ -║ paymaster+postOp with diff │ 11 │ │ 41236 │ 12237 ║ +║ paymaster+postOp with diff │ 11 │ │ 41637 │ 10516 ║ ╚════════════════════════════════╧═══════╧═══════════════╧════════════════╧═════════════════════╝ diff --git a/dependencies/eth-infinitism-account-abstraction-0.8.0/scripts/check-gas-reports b/dependencies/eth-infinitism-account-abstraction-0.9.0/scripts/check-gas-reports similarity index 100% rename from dependencies/eth-infinitism-account-abstraction-0.8.0/scripts/check-gas-reports rename to dependencies/eth-infinitism-account-abstraction-0.9.0/scripts/check-gas-reports diff --git a/dependencies/eth-infinitism-account-abstraction-0.8.0/scripts/docker-gascalc b/dependencies/eth-infinitism-account-abstraction-0.9.0/scripts/docker-gascalc similarity index 100% rename from dependencies/eth-infinitism-account-abstraction-0.8.0/scripts/docker-gascalc rename to dependencies/eth-infinitism-account-abstraction-0.9.0/scripts/docker-gascalc diff --git a/dependencies/eth-infinitism-account-abstraction-0.8.0/scripts/docker-gascalc.yml b/dependencies/eth-infinitism-account-abstraction-0.9.0/scripts/docker-gascalc.yml similarity index 100% rename from dependencies/eth-infinitism-account-abstraction-0.8.0/scripts/docker-gascalc.yml rename to dependencies/eth-infinitism-account-abstraction-0.9.0/scripts/docker-gascalc.yml diff --git a/dependencies/eth-infinitism-account-abstraction-0.8.0/scripts/gascalc b/dependencies/eth-infinitism-account-abstraction-0.9.0/scripts/gascalc similarity index 100% rename from dependencies/eth-infinitism-account-abstraction-0.8.0/scripts/gascalc rename to dependencies/eth-infinitism-account-abstraction-0.9.0/scripts/gascalc diff --git a/dependencies/eth-infinitism-account-abstraction-0.8.0/scripts/geth.sh b/dependencies/eth-infinitism-account-abstraction-0.9.0/scripts/geth.sh similarity index 100% rename from dependencies/eth-infinitism-account-abstraction-0.8.0/scripts/geth.sh rename to dependencies/eth-infinitism-account-abstraction-0.9.0/scripts/geth.sh diff --git a/dependencies/eth-infinitism-account-abstraction-0.8.0/scripts/hh-wrapper b/dependencies/eth-infinitism-account-abstraction-0.9.0/scripts/hh-wrapper similarity index 100% rename from dependencies/eth-infinitism-account-abstraction-0.8.0/scripts/hh-wrapper rename to dependencies/eth-infinitism-account-abstraction-0.9.0/scripts/hh-wrapper diff --git a/dependencies/eth-infinitism-account-abstraction-0.8.0/scripts/postpack-contracts-package.sh b/dependencies/eth-infinitism-account-abstraction-0.9.0/scripts/postpack-contracts-package.sh similarity index 100% rename from dependencies/eth-infinitism-account-abstraction-0.8.0/scripts/postpack-contracts-package.sh rename to dependencies/eth-infinitism-account-abstraction-0.9.0/scripts/postpack-contracts-package.sh diff --git a/dependencies/eth-infinitism-account-abstraction-0.8.0/scripts/prepack-contracts-package.sh b/dependencies/eth-infinitism-account-abstraction-0.9.0/scripts/prepack-contracts-package.sh similarity index 100% rename from dependencies/eth-infinitism-account-abstraction-0.8.0/scripts/prepack-contracts-package.sh rename to dependencies/eth-infinitism-account-abstraction-0.9.0/scripts/prepack-contracts-package.sh diff --git a/dependencies/eth-infinitism-account-abstraction-0.8.0/scripts/sample-script.js b/dependencies/eth-infinitism-account-abstraction-0.9.0/scripts/sample-script.js similarity index 100% rename from dependencies/eth-infinitism-account-abstraction-0.8.0/scripts/sample-script.js rename to dependencies/eth-infinitism-account-abstraction-0.9.0/scripts/sample-script.js diff --git a/dependencies/eth-infinitism-account-abstraction-0.8.0/scripts/solcErrors b/dependencies/eth-infinitism-account-abstraction-0.9.0/scripts/solcErrors similarity index 100% rename from dependencies/eth-infinitism-account-abstraction-0.8.0/scripts/solcErrors rename to dependencies/eth-infinitism-account-abstraction-0.9.0/scripts/solcErrors diff --git a/dependencies/eth-infinitism-account-abstraction-0.8.0/src/AASigner.ts b/dependencies/eth-infinitism-account-abstraction-0.9.0/src/AASigner.ts similarity index 95% rename from dependencies/eth-infinitism-account-abstraction-0.8.0/src/AASigner.ts rename to dependencies/eth-infinitism-account-abstraction-0.9.0/src/AASigner.ts index 3441b42..87a3862 100644 --- a/dependencies/eth-infinitism-account-abstraction-0.8.0/src/AASigner.ts +++ b/dependencies/eth-infinitism-account-abstraction-0.9.0/src/AASigner.ts @@ -5,7 +5,7 @@ import { Deferrable, resolveProperties } from '@ethersproject/properties' import { BaseProvider, Provider, TransactionRequest } from '@ethersproject/providers' import { BigNumber, Bytes, ethers, Event, Signer } from 'ethers' import { clearInterval } from 'timers' -import { decodeRevertReason, getAccountAddress, getAccountInitCode } from '../test/testutils' +import { decodeRevertReason, getAccountAddress, getAccountFactoryData } from '../test/testutils' import { fillAndSign, getUserOpHash, packUserOp } from '../test/UserOp' import { PackedUserOperation, UserOperation } from '../test/UserOperation' import { @@ -33,7 +33,8 @@ export function rpcUserOpSender (provider: ethers.providers.JsonRpcProvider, ent if (debug) { console.log('sending eth_sendUserOperation', { ...userOp, - initCode: (userOp.initCode ?? '').length, + facotry: (userOp.factory ?? '').length, + facotryData: (userOp.factoryData ?? '').length, callData: (userOp.callData ?? '').length }, entryPointAddress) } @@ -169,7 +170,8 @@ export function localUserOpSender (entryPointAddress: string, signer: Signer, be if (debug) { console.log('sending', { ...userOp, - initCode: userOp.initCode.length <= 2 ? userOp.initCode : `` + factory: userOp.factory, + factoryData: (userOp.factoryData != null && userOp.factoryData.length <= 2) ? userOp.factoryData : `` }) } const gasLimit = BigNumber.from(userOp.preVerificationGas).add(userOp.verificationGasLimit).add(userOp.callGasLimit) @@ -373,9 +375,11 @@ export class AASigner extends Signer { const tx: TransactionRequest = await resolveProperties(transaction) await this.syncAccount() - let initCode: BytesLike | undefined + let factory: string | undefined + let factoryData: BytesLike | undefined if (this._isPhantom) { - initCode = getAccountInitCode(await this.signer.getAddress(), this.accountFactory) + factory = this.accountFactory.address + factoryData = getAccountFactoryData(await this.signer.getAddress(), this.accountFactory) } const execFromEntryPoint = await this._account!.populateTransaction.execute(tx.to!, tx.value ?? 0, tx.data!) @@ -388,8 +392,9 @@ export class AASigner extends Signer { } const userOp = await fillAndSign({ sender: this._account!.address, - initCode, - nonce: initCode == null ? tx.nonce : this.index, + factory, + factoryData, + nonce: factoryData == null ? tx.nonce : this.index, callData: execFromEntryPoint.data!, callGasLimit: tx.gasLimit, maxPriorityFeePerGas, diff --git a/dependencies/eth-infinitism-account-abstraction-0.8.0/src/Create2Factory.ts b/dependencies/eth-infinitism-account-abstraction-0.9.0/src/Create2Factory.ts similarity index 100% rename from dependencies/eth-infinitism-account-abstraction-0.8.0/src/Create2Factory.ts rename to dependencies/eth-infinitism-account-abstraction-0.9.0/src/Create2Factory.ts diff --git a/dependencies/eth-infinitism-account-abstraction-0.8.0/src/Utils.ts b/dependencies/eth-infinitism-account-abstraction-0.9.0/src/Utils.ts similarity index 100% rename from dependencies/eth-infinitism-account-abstraction-0.8.0/src/Utils.ts rename to dependencies/eth-infinitism-account-abstraction-0.9.0/src/Utils.ts diff --git a/dependencies/eth-infinitism-account-abstraction-0.8.0/src/runop.ts b/dependencies/eth-infinitism-account-abstraction-0.9.0/src/runop.ts similarity index 100% rename from dependencies/eth-infinitism-account-abstraction-0.8.0/src/runop.ts rename to dependencies/eth-infinitism-account-abstraction-0.9.0/src/runop.ts diff --git a/dependencies/eth-infinitism-account-abstraction-0.8.0/test/0-create2factory.test.ts b/dependencies/eth-infinitism-account-abstraction-0.9.0/test/0-create2factory.test.ts similarity index 100% rename from dependencies/eth-infinitism-account-abstraction-0.8.0/test/0-create2factory.test.ts rename to dependencies/eth-infinitism-account-abstraction-0.9.0/test/0-create2factory.test.ts diff --git a/dependencies/eth-infinitism-account-abstraction-0.8.0/test/GethExecutable.ts b/dependencies/eth-infinitism-account-abstraction-0.9.0/test/GethExecutable.ts similarity index 100% rename from dependencies/eth-infinitism-account-abstraction-0.8.0/test/GethExecutable.ts rename to dependencies/eth-infinitism-account-abstraction-0.9.0/test/GethExecutable.ts diff --git a/dependencies/eth-infinitism-account-abstraction-0.8.0/test/UserOp.ts b/dependencies/eth-infinitism-account-abstraction-0.9.0/test/UserOp.ts similarity index 70% rename from dependencies/eth-infinitism-account-abstraction-0.8.0/test/UserOp.ts rename to dependencies/eth-infinitism-account-abstraction-0.9.0/test/UserOp.ts index 75da306..0f05501 100644 --- a/dependencies/eth-infinitism-account-abstraction-0.8.0/test/UserOp.ts +++ b/dependencies/eth-infinitism-account-abstraction-0.9.0/test/UserOp.ts @@ -1,11 +1,15 @@ import { arrayify, - defaultAbiCoder, hexConcat, hexDataLength, - hexDataSlice, hexlify, + defaultAbiCoder, + hexConcat, + hexDataLength, + hexDataSlice, + hexlify, + hexZeroPad, keccak256 } from 'ethers/lib/utils' import { BigNumber, Contract, Signer, Wallet } from 'ethers' -import { TypedDataSigner, TypedDataDomain, TypedDataField } from '@ethersproject/abstract-signer' +import { TypedDataDomain, TypedDataField, TypedDataSigner } from '@ethersproject/abstract-signer' import { AddressZero, callDataCost, @@ -15,9 +19,7 @@ import { rethrow } from './testutils' import { ecsign, toRpcSig } from 'ethereumjs-util' -import { - EntryPoint, EntryPointSimulations__factory -} from '../typechain' +import { EntryPoint, EntryPointSimulations__factory } from '../typechain' import { PackedUserOperation, UserOperation } from './UserOperation' import { Create2Factory } from '../src/Create2Factory' import { TransactionRequest } from '@ethersproject/abstract-provider' @@ -25,6 +27,7 @@ import { TransactionRequest } from '@ethersproject/abstract-provider' import EntryPointSimulationsJson from '../artifacts/contracts/core/EntryPointSimulations.sol/EntryPointSimulations.json' import { ethers } from 'hardhat' import { IEntryPointSimulations } from '../typechain/contracts/core/EntryPointSimulations' +import { BytesLike } from '@ethersproject/bytes' // Matched to domain name, version from EntryPoint.sol: const DOMAIN_NAME = 'ERC4337' @@ -35,25 +38,81 @@ const PACKED_USEROP_TYPEHASH = keccak256(Buffer.from('PackedUserOperation(addres export const INITCODE_EIP7702_MARKER = '0x7702' -export function packUserOp (userOp: UserOperation): PackedUserOperation { +export const PAYMASTER_SIG_MAGIC = '0x22e325a297439656' // keccak("PaymasterSignature")[:8] + +export function packUserOp (userOp: UserOperation, forSigning: boolean = false): PackedUserOperation { const accountGasLimits = packAccountGasLimits(userOp.verificationGasLimit, userOp.callGasLimit) const gasFees = packAccountGasLimits(userOp.maxPriorityFeePerGas, userOp.maxFeePerGas) let paymasterAndData = '0x' - if (userOp.paymaster?.length >= 20 && userOp.paymaster !== AddressZero) { - paymasterAndData = packPaymasterData(userOp.paymaster as string, userOp.paymasterVerificationGasLimit, userOp.paymasterPostOpGasLimit, userOp.paymasterData as string) + if (userOp.paymaster != null && userOp.paymaster?.length >= 20 && userOp.paymaster !== AddressZero) { + paymasterAndData = packPaymasterData( + userOp.paymaster, + userOp.paymasterVerificationGasLimit!, + userOp.paymasterPostOpGasLimit!, + userOp.paymasterData, + userOp.paymasterSignature, + forSigning + ) + } + let initCode = '0x' + if (userOp.factory != null) { + initCode = hexConcat([userOp.factory, userOp.factoryData ?? '0x']) + } else if (userOp.isEip7702 ?? false) { + initCode = INITCODE_EIP7702_MARKER + if (userOp.factoryData != null && userOp.factoryData !== '0x') { + const initCodeMarker = INITCODE_EIP7702_MARKER + '0'.repeat(42 - INITCODE_EIP7702_MARKER.length) + initCode = hexConcat([initCodeMarker, userOp.factoryData ?? '0x']) + } } return { sender: userOp.sender, nonce: userOp.nonce, callData: userOp.callData, accountGasLimits, - initCode: userOp.initCode, + initCode, preVerificationGas: userOp.preVerificationGas, gasFees, paymasterAndData, signature: userOp.signature } } + +// encode a paymaster signature, to append to the paymasterData field. +export function encodePaymasterSignature (pmSig: BytesLike | undefined, forSigning: boolean = false): string { + if (pmSig == null) { + return '0x' + } + if (forSigning) { + return PAYMASTER_SIG_MAGIC + } + return hexConcat([pmSig, hexZeroPad('0x' + hexDataLength(pmSig).toString(16), 2), PAYMASTER_SIG_MAGIC]) +} + +// decode paymaster signature length from paymasterData +// return nonzero if there is a paymaster signature +function getPaymasterSignatureLength (paymasterAndData: BytesLike): number { + const paymasterDataLength = hexDataLength(paymasterAndData) + const suffixLength = hexDataLength(PAYMASTER_SIG_MAGIC) + if (paymasterDataLength > suffixLength && + hexDataSlice(paymasterAndData, paymasterDataLength - suffixLength).toLowerCase() === PAYMASTER_SIG_MAGIC) { + return BigNumber.from(hexDataSlice(paymasterAndData, paymasterDataLength - 10, paymasterDataLength - 8)).toNumber() + } else { + return 0 + } +} + +function keccakPaymasterAndData (paymasterAndData: string): string { + const pmdLen = hexDataLength(paymasterAndData) + const pmSigLength = getPaymasterSignatureLength(paymasterAndData) + if (pmSigLength !== 0) { + const dataToHash = hexDataSlice(paymasterAndData, 0, pmdLen - pmSigLength - 10) + // if there is a paymasterSignature, remove it before hashing, but still append the SIGNATURE_SUFFIX + return keccak256(hexConcat([dataToHash, PAYMASTER_SIG_MAGIC])) + } else { + return keccak256(paymasterAndData) + } +} + export function encodeUserOp (userOp: UserOperation, forSignature = true): string { const packedUserOp = packUserOp(userOp) if (forSignature) { @@ -65,7 +124,7 @@ export function encodeUserOp (userOp: UserOperation, forSignature = true): strin [PACKED_USEROP_TYPEHASH, packedUserOp.sender, packedUserOp.nonce, keccak256(packedUserOp.initCode), keccak256(packedUserOp.callData), packedUserOp.accountGasLimits, packedUserOp.preVerificationGas, packedUserOp.gasFees, - keccak256(packedUserOp.paymasterAndData)]) + keccakPaymasterAndData(hexlify(packedUserOp.paymasterAndData))]) } else { // for the purpose of calculating gas cost encode also signature (and no keccak of bytes) return defaultAbiCoder.encode( @@ -89,23 +148,12 @@ export function getUserOpHash (op: UserOperation, entryPoint: string, chainId: n ])) } -export function isEip7702UserOp (op: UserOperation): boolean { - return op.initCode != null && hexlify(op.initCode).startsWith(INITCODE_EIP7702_MARKER) -} - export function updateUserOpForEip7702Hash (op: UserOperation, delegate: string): UserOperation { - if (!isEip7702UserOp(op)) { + if (!(op.isEip7702 ?? false)) { throw new Error('initCode should start with INITCODE_EIP7702_MARKER') } - let initCode = hexlify(op.initCode) - if (hexDataLength(initCode) < 20) { - initCode = delegate - } else { - // replace address in initCode with delegate - initCode = hexConcat([delegate, hexDataSlice(initCode, 20)]) - } return { - ...op, initCode + ...op, factory: delegate } } @@ -119,7 +167,6 @@ export function getUserOpHashWithEip7702 (op: UserOperation, entryPoint: string, export const DefaultsForUserOp: UserOperation = { sender: AddressZero, nonce: 0, - initCode: '0x', callData: '0x', callGasLimit: 0, verificationGasLimit: 150000, // default verification gas. will add create2 cost (3200+200*length) if initCode exists @@ -135,7 +182,7 @@ export const DefaultsForUserOp: UserOperation = { export function signUserOp (op: UserOperation, signer: Wallet, entryPoint: string, chainId: number, eip7702delegate?: string): UserOperation { let message - if (isEip7702UserOp(op)) { + if (op.isEip7702 ?? false) { if (eip7702delegate == null) { throw new Error('Must have eip7702delegate to sign') } @@ -189,59 +236,68 @@ export interface FillUserOpOptions { // sender - only in case of construction: fill sender from initCode. // callGasLimit: VERY crude estimation (by estimating call to account, and add rough entryPoint overhead // verificationGasLimit: hard-code default at 100k. should add "create2" cost -export async function fillUserOp (op: Partial, entryPoint?: EntryPoint, options?: FillUserOpOptions): Promise { +export async function fillUserOp ( + op: Partial, + entryPoint?: EntryPoint, options?: FillUserOpOptions): Promise { const getNonceFunction = options?.getNonceFunction ?? 'getNonce' - const op1 = { ...op } + const op1: Partial = { ...op } const provider = entryPoint?.provider - if (op1.initCode != null) { - if (isEip7702UserOp(op1 as UserOperation)) { - if (provider == null) { - throw new Error('must have provider to check eip7702 delegate') - } - const code = await provider.getCode(op1.sender!) - if (code.length === 2) { - if (options?.eip7702delegate == null) { - throw new Error('must have eip7702delegate') - } - } else if (code.length !== 23 * 2 + 2) { - throw new Error('sender is not an eip7702 delegate') - } - if (op1.nonce == null) { - op1.nonce = await provider.getTransactionCount(op1.sender!) - } - } else { - const initAddr = hexDataSlice(op1.initCode!, 0, 20) - const initCallData = hexDataSlice(op1.initCode!, 20) - if (op1.nonce == null) op1.nonce = 0 - if (op1.sender == null) { - // hack: if the init contract is our known deployer, then we know what the address would be, without a view call - if (initAddr.toLowerCase() === Create2Factory.contractAddress.toLowerCase()) { - const ctr = hexDataSlice(initCallData, 32) - const salt = hexDataSlice(initCallData, 0, 32) - op1.sender = Create2Factory.getDeployedAddress(ctr, salt) - } else { - // console.log('\t== not our deployer. our=', Create2Factory.contractAddress, 'got', initAddr) - if (provider == null) throw new Error('no entrypoint/provider') - op1.sender = await entryPoint!.callStatic.getSenderAddress(op1.initCode!).catch(e => e.errorArgs.sender) - } + if (provider == null) { + throw new Error('no entrypoint or provider not set - unable to fillUserOp') + } + let hasDeployedCode = false + if (op1.isEip7702 ?? false) { + const code = await provider.getCode(op1.sender!) + if (code.length === 2) { + if (options?.eip7702delegate == null) { + throw new Error('must have eip7702delegate') } - if (op1.verificationGasLimit == null) { - if (provider == null) throw new Error('no entrypoint/provider') - const senderCreator = await entryPoint?.senderCreator() - const initEstimate = await provider.estimateGas({ - from: senderCreator, - to: initAddr, - data: initCallData, - gasLimit: 10e6 - }) - op1.verificationGasLimit = BigNumber.from(DefaultsForUserOp.verificationGasLimit).add(initEstimate) + } else if (code.length !== 23 * 2 + 2) { + throw new Error('sender is not an eip7702 delegate') + } + hasDeployedCode = true + op1.factoryData = op1.factoryData ?? '0x' + op1.factory = INITCODE_EIP7702_MARKER + if (op1.factoryData != null && op1.factoryData !== '0x') { + op1.factory = INITCODE_EIP7702_MARKER + '0'.repeat(42 - INITCODE_EIP7702_MARKER.length) + } + } else if (op1.factory != null) { + if (op1.sender == null) { + // hack: if the init contract is our known deployer, then we know what the address would be, without a view call + if (op1.factory.toLowerCase() === Create2Factory.contractAddress.toLowerCase()) { + const ctr = hexDataSlice(op1.factoryData!, 32) + const salt = hexDataSlice(op1.factoryData!, 0, 32) + op1.sender = Create2Factory.getDeployedAddress(ctr, salt) + } else { + op1.sender = await entryPoint!.callStatic.getSenderAddress(hexConcat([op1.factory, op1.factoryData!])).catch(e => e.errorArgs.sender) } } + const code = await provider.getCode(op1.sender!) + if (code.length !== 2) { + hasDeployedCode = true + } + if (op1.verificationGasLimit == null) { + const senderCreator = await entryPoint?.senderCreator() + const initEstimate = await provider.estimateGas({ + from: senderCreator, + to: op1.factory, + data: op1.factoryData, + gasLimit: 10e6 + }) + op1.verificationGasLimit = BigNumber.from(DefaultsForUserOp.verificationGasLimit).add(initEstimate) + } + } else { + hasDeployedCode = true } if (op1.nonce == null) { - if (provider == null) throw new Error('must have entryPoint to autofill nonce') - const c = new Contract(op.sender!, [`function ${getNonceFunction}() view returns(uint256)`], provider) - op1.nonce = await c[getNonceFunction]().catch(rethrow()) + if (hasDeployedCode) { + if (provider == null) throw new Error('must have entryPoint to autofill nonce') + if (op.sender == null) throw new Error('must have sender to autofill nonce') + const c = new Contract(op.sender!, [`function ${getNonceFunction}() view returns(uint256)`], provider) + op1.nonce = await c[getNonceFunction]().catch(rethrow()) + } else { + op1.nonce = 0 + } } if (op1.callGasLimit == null && op.callData != null) { if (provider == null) throw new Error('must have entryPoint for callGasLimit estimate') @@ -323,6 +379,24 @@ export function getErc4337TypedDataTypes (): { [type: string]: TypedDataField[] } } +export function updatePaymasterDataForSigning (paymasterData: BytesLike | undefined): string { + if (paymasterData == null) { + return '0x' + } + const pmSigLen = getPaymasterSignatureLength(paymasterData) + if (pmSigLen === 0) { + return hexlify(paymasterData) + } + + // remove signature and length from paymasterData + const paymasterDataLength = hexDataLength(paymasterData) + + return hexConcat([ + hexDataSlice(paymasterData, 0, paymasterDataLength - pmSigLen - 10), + PAYMASTER_SIG_MAGIC + ]) +} + /** * call eth_signTypedData_v4 to sign the UserOp * @param op @@ -339,7 +413,7 @@ export async function asyncSignUserOp (op: UserOperation, signer: Wallet | Signe const typedSigner: TypedDataSigner = signer as any let userOpToSign = op - if (isEip7702UserOp(userOpToSign)) { + if (userOpToSign.isEip7702 ?? false) { if (eip7702delegate == null) { const senderCode = await provider!.getCode(userOpToSign.sender) if (!senderCode.startsWith('0xef0100')) { @@ -353,7 +427,12 @@ export async function asyncSignUserOp (op: UserOperation, signer: Wallet | Signe userOpToSign = updateUserOpForEip7702Hash(userOpToSign, eip7702delegate) } - const packedUserOp = packUserOp(userOpToSign) + userOpToSign = { + ...userOpToSign, + paymasterData: updatePaymasterDataForSigning(userOpToSign.paymasterData) + } + + const packedUserOp = packUserOp(userOpToSign, true) return await typedSigner._signTypedData(getErc4337TypedDataDomain(entryPoint!.address, chainId), getErc4337TypedDataTypes(), packedUserOp) // .catch(e => e.toString()) } diff --git a/dependencies/eth-infinitism-account-abstraction-0.9.0/test/UserOperation.ts b/dependencies/eth-infinitism-account-abstraction-0.9.0/test/UserOperation.ts new file mode 100644 index 0000000..22d1c50 --- /dev/null +++ b/dependencies/eth-infinitism-account-abstraction-0.9.0/test/UserOperation.ts @@ -0,0 +1,34 @@ +import { BigNumberish, BytesLike } from 'ethers' +import * as typ from './solidityTypes' + +export interface UserOperation { + isEip7702?: boolean + sender: string + nonce: BigNumberish + factory?: string + factoryData?: BytesLike + callData: BytesLike + callGasLimit: BigNumberish + verificationGasLimit: BigNumberish + preVerificationGas: BigNumberish + maxFeePerGas: BigNumberish + maxPriorityFeePerGas: BigNumberish + paymaster?: string + paymasterVerificationGasLimit?: BigNumberish + paymasterPostOpGasLimit?: BigNumberish + paymasterData?: BytesLike + paymasterSignature?: BytesLike + signature: BytesLike +} + +export interface PackedUserOperation { + sender: typ.address + nonce: typ.uint256 + initCode: typ.bytes + callData: typ.bytes + accountGasLimits: typ.bytes32 + preVerificationGas: typ.uint256 + gasFees: typ.bytes32 + paymasterAndData: typ.bytes + signature: typ.bytes +} diff --git a/dependencies/eth-infinitism-account-abstraction-0.8.0/test/aa.init.ts b/dependencies/eth-infinitism-account-abstraction-0.9.0/test/aa.init.ts similarity index 100% rename from dependencies/eth-infinitism-account-abstraction-0.8.0/test/aa.init.ts rename to dependencies/eth-infinitism-account-abstraction-0.9.0/test/aa.init.ts diff --git a/dependencies/eth-infinitism-account-abstraction-0.8.0/test/chaiHelper.ts b/dependencies/eth-infinitism-account-abstraction-0.9.0/test/chaiHelper.ts similarity index 100% rename from dependencies/eth-infinitism-account-abstraction-0.8.0/test/chaiHelper.ts rename to dependencies/eth-infinitism-account-abstraction-0.9.0/test/chaiHelper.ts diff --git a/dependencies/eth-infinitism-account-abstraction-0.8.0/test/debugTx.ts b/dependencies/eth-infinitism-account-abstraction-0.9.0/test/debugTx.ts similarity index 100% rename from dependencies/eth-infinitism-account-abstraction-0.8.0/test/debugTx.ts rename to dependencies/eth-infinitism-account-abstraction-0.9.0/test/debugTx.ts diff --git a/dependencies/eth-infinitism-account-abstraction-0.8.0/test/eip7702-wallet.test.ts b/dependencies/eth-infinitism-account-abstraction-0.9.0/test/eip7702-wallet.test.ts similarity index 85% rename from dependencies/eth-infinitism-account-abstraction-0.8.0/test/eip7702-wallet.test.ts rename to dependencies/eth-infinitism-account-abstraction-0.9.0/test/eip7702-wallet.test.ts index 6c21966..1263b6c 100644 --- a/dependencies/eth-infinitism-account-abstraction-0.8.0/test/eip7702-wallet.test.ts +++ b/dependencies/eth-infinitism-account-abstraction-0.9.0/test/eip7702-wallet.test.ts @@ -1,12 +1,13 @@ import { expect } from 'chai' import { Simple7702Account, Simple7702Account__factory, EntryPoint, TestPaymasterAcceptAll__factory } from '../typechain' -import { createAccountOwner, createAddress, deployEntryPoint } from './testutils' -import { fillAndSign, INITCODE_EIP7702_MARKER, packUserOp } from './UserOp' +import { createAccountOwner, createAddress, decodeRevertReason, deployEntryPoint } from './testutils' +import { fillAndSign, packUserOp } from './UserOp' import { hexConcat, parseEther } from 'ethers/lib/utils' import { signEip7702Authorization } from './eip7702helpers' import { GethExecutable } from './GethExecutable' import { Wallet } from 'ethers' +import { toChecksumAddress } from 'ethereumjs-util' describe('Simple7702Account.sol', function () { // can't deploy coverage "entrypoint" on geth (contract too large) @@ -25,7 +26,7 @@ describe('Simple7702Account.sol', function () { entryPoint = await deployEntryPoint(geth.provider) - eip7702delegate = await new Simple7702Account__factory(geth.provider.getSigner()).deploy() + eip7702delegate = await new Simple7702Account__factory(geth.provider.getSigner()).deploy(entryPoint.address) expect(await eip7702delegate.entryPoint()).to.equal(entryPoint.address, 'fix entryPoint in Simple7702Account.sol') console.log('set eip7702delegate=', eip7702delegate.address) }) @@ -58,7 +59,16 @@ describe('Simple7702Account.sol', function () { it('should fail call from another account', async () => { const wallet1 = Simple7702Account__factory.connect(eoa.address, geth.provider.getSigner()) - await expect(wallet1.executeBatch([])).to.revertedWith('not from self or EntryPoint') + try { + await wallet1.executeBatch([]) + expect.fail('Expected transaction to revert') + } catch (error: any) { + const errorData = error?.error?.error?.data + expect(errorData).to.not.be.undefined + const errorDecoded = decodeRevertReason(errorData) + const senderAddress = await geth.provider.getSigner().getAddress() + expect(errorDecoded).to.equal(`NotFromEntryPoint(${toChecksumAddress(senderAddress)},${toChecksumAddress(wallet1.address)},${toChecksumAddress(entryPoint.address)})`) + } }) it('should succeed sending a batch', async () => { @@ -86,7 +96,7 @@ describe('Simple7702Account.sol', function () { const callData = eip7702delegate.interface.encodeFunctionData('execute', [addr1, 1, '0x']) const userop = await fillAndSign({ sender: eoa.address, - initCode: INITCODE_EIP7702_MARKER, + isEip7702: true, nonce: 0, callData }, eoa, entryPoint, { eip7702delegate: eip7702delegate.address }) @@ -118,7 +128,7 @@ describe('Simple7702Account.sol', function () { const userop = await fillAndSign({ sender: eoa.address, paymaster: paymaster.address, - initCode: INITCODE_EIP7702_MARKER, + isEip7702: true, nonce: 0, callData }, eoa, entryPoint, { eip7702delegate: eip7702delegate.address }) diff --git a/dependencies/eth-infinitism-account-abstraction-0.8.0/test/eip7702helpers.ts b/dependencies/eth-infinitism-account-abstraction-0.9.0/test/eip7702helpers.ts similarity index 53% rename from dependencies/eth-infinitism-account-abstraction-0.8.0/test/eip7702helpers.ts rename to dependencies/eth-infinitism-account-abstraction-0.9.0/test/eip7702helpers.ts index 357a8e8..ec4599b 100644 --- a/dependencies/eth-infinitism-account-abstraction-0.8.0/test/eip7702helpers.ts +++ b/dependencies/eth-infinitism-account-abstraction-0.9.0/test/eip7702helpers.ts @@ -2,6 +2,7 @@ import { ecrecover, ecsign, PrefixedHexString, pubToAddress, toBuffer, toChecksu import { BigNumber, BigNumberish, Wallet } from 'ethers' import { arrayify, hexConcat, hexlify, keccak256, RLP } from 'ethers/lib/utils' import { tostr } from './testutils' +import { TransactionRequest } from '@ethersproject/abstract-provider' // from: https://github.com/ethereum/EIPs/blob/master/EIPS/eip-7702.md // authority = ecrecover(keccak(MAGIC || rlp([chain_id, address, nonce])), y_parity, r, s) @@ -72,3 +73,60 @@ export async function signEip7702Authorization (signer: Wallet, authorization: U s: gethHex(sig.s) } } + +// TODO: quickfix; must update Ethers.js to v6, use the normal 'signTransaction' there, and remove this custom function +export async function signEip7702RawTransaction (signer: Wallet, txRequest: TransactionRequest): Promise { + const nonce = txRequest.nonce ?? await signer.getTransactionCount() + const chainId = txRequest.chainId ?? await signer.getChainId() + const gasLimit = txRequest.gasLimit ?? 21000 + const maxFeePerGas = txRequest.maxFeePerGas ?? await signer.provider!.getGasPrice() + const maxPriorityFeePerGas = txRequest.maxPriorityFeePerGas ?? maxFeePerGas + const to = txRequest.to ?? '0x' + const value = txRequest.value ?? 0 + const data = txRequest.data ?? '0x' + const authorizationList = (txRequest as any).authorizationList ?? [] + + // EIP-7702 transaction format (type 0x04): + // 0x04 || rlp([chain_id, nonce, max_priority_fee_per_gas, max_fee_per_gas, gas_limit, destination, value, data, access_list, authorization_list, signature_y_parity, signature_r, signature_s]) + + // Encode authorization list: [[chain_id, address, nonce, y_parity, r, s], ...] + const encodedAuthList = authorizationList.map((auth: any) => [ + toRlpHex(auth.chainId), + toRlpHex(auth.address), + toRlpHex(auth.nonce), + toRlpHex(auth.yParity), + toRlpHex(auth.r), + toRlpHex(auth.s) + ]) + + // Transaction payload without signature + const txData = [ + toRlpHex(chainId), + toRlpHex(nonce), + toRlpHex(maxPriorityFeePerGas), + toRlpHex(maxFeePerGas), + toRlpHex(gasLimit), + toRlpHex(to), + toRlpHex(value), + toRlpHex(data), + [], // access_list (empty for now) + encodedAuthList + ] + + // Hash the unsigned transaction + const txHash = keccak256(hexConcat(['0x04', RLP.encode(txData)])) + + // Sign the transaction + const sig = ecsign(toBuffer(txHash), arrayify(signer.privateKey) as any) + + // Add signature to transaction data + const signedTxData = [ + ...txData, + toRlpHex(sig.v - 27), // y_parity (v - 27 for EIP-155) + toRlpHex('0x' + sig.r.toString('hex')), + toRlpHex('0x' + sig.s.toString('hex')) + ] + + // Encode and return: 0x04 || rlp(transaction) + return hexConcat(['0x04', RLP.encode(signedTxData)]) as PrefixedHexString +} diff --git a/dependencies/eth-infinitism-account-abstraction-0.8.0/test/entrypoint-7702.test.ts b/dependencies/eth-infinitism-account-abstraction-0.9.0/test/entrypoint-7702.test.ts similarity index 69% rename from dependencies/eth-infinitism-account-abstraction-0.8.0/test/entrypoint-7702.test.ts rename to dependencies/eth-infinitism-account-abstraction-0.9.0/test/entrypoint-7702.test.ts index e9621fe..c7bedba 100644 --- a/dependencies/eth-infinitism-account-abstraction-0.8.0/test/entrypoint-7702.test.ts +++ b/dependencies/eth-infinitism-account-abstraction-0.9.0/test/entrypoint-7702.test.ts @@ -1,6 +1,9 @@ import './aa.init' + +import * as chai from 'chai' +import chaiAsPromised from 'chai-as-promised' import { Wallet } from 'ethers' -import { expect } from 'chai' +import { toChecksumAddress } from 'ethereumjs-util' import { EntryPoint, TestEip7702DelegateAccount, @@ -28,7 +31,20 @@ import { ethers } from 'hardhat' import { hexConcat, parseEther } from 'ethers/lib/utils' import { before } from 'mocha' import { GethExecutable } from './GethExecutable' -import { getEip7702AuthorizationSigner, gethHex, signEip7702Authorization } from './eip7702helpers' +import { + getEip7702AuthorizationSigner, + gethHex, + signEip7702Authorization, + signEip7702RawTransaction +} from './eip7702helpers' +import { UserOperation } from './UserOperation' + +async function sleep (number: number): Promise { + return new Promise(resolve => setTimeout(resolve, number)) +} + +chai.use(chaiAsPromised) +const expect = chai.expect describe('EntryPoint EIP-7702 tests', function () { const ethersSigner = ethers.provider.getSigner() @@ -113,41 +129,34 @@ describe('EntryPoint EIP-7702 tests', function () { describe('#getUserOpHashWith7702', () => { it('#getUserOpHashWith7702 just delegate', async () => { - const hash = getUserOpHash({ ...userop, initCode: mockDelegate }, entryPoint.address, chainId) + const hash = getUserOpHash({ ...userop, factory: mockDelegate }, entryPoint.address, chainId) expect(getUserOpHashWithEip7702({ ...userop, - initCode: INITCODE_EIP7702_MARKER + isEip7702: true }, entryPoint.address, chainId, mockDelegate)).to.eql(hash) }) it('#getUserOpHashWith7702 with initcode', async () => { - const hash = getUserOpHash({ ...userop, initCode: mockDelegate + 'b1ab1a' }, entryPoint.address, chainId) + const hash = getUserOpHash({ ...userop, factory: mockDelegate, factoryData: '0xb1ab1a' }, entryPoint.address, chainId) expect(getUserOpHashWithEip7702({ ...userop, - initCode: INITCODE_EIP7702_MARKER.padEnd(42, '0') + 'b1ab1a' + isEip7702: true, + factoryData: '0xb1ab1a' }, entryPoint.address, chainId, mockDelegate)).to.eql(hash) }) }) describe('entryPoint getUserOpHash', () => { it('should return the same hash as calculated locally', async () => { - const op1 = { ...userop, initCode: INITCODE_EIP7702_MARKER } + const op1: UserOperation = { ...userop, isEip7702: true } expect(await callGetUserOpHashWithCode(entryPoint, op1, deployedDelegateCode)).to.eql( getUserOpHashWithEip7702(op1, entryPoint.address, chainId, mockDelegate)) }) it('should fail getUserOpHash marked for eip-7702, without a delegate', async () => { - const op1 = { ...userop, initCode: INITCODE_EIP7702_MARKER } - await expect(callGetUserOpHashWithCode(entryPoint, op1, '0x' + '00'.repeat(23)).catch(e => { throw e.error ?? e.message })).to.revertedWith('not an EIP-7702 delegate') - }) - - it('should allow initCode with INITCODE_EIP7702_MARKER tailed with zeros only, ', async () => { - const op_zero_tail = { ...userop, initCode: INITCODE_EIP7702_MARKER + '00'.repeat(10) } - expect(await callGetUserOpHashWithCode(entryPoint, op_zero_tail, deployedDelegateCode)).to.eql( - getUserOpHashWithEip7702(op_zero_tail, entryPoint.address, chainId, mockDelegate)) - - op_zero_tail.initCode = INITCODE_EIP7702_MARKER + '00'.repeat(30) - expect(await callGetUserOpHashWithCode(entryPoint, op_zero_tail, deployedDelegateCode)).to.eql( - getUserOpHashWithEip7702(op_zero_tail, entryPoint.address, chainId, mockDelegate)) + const op1: UserOperation = { ...userop, isEip7702: true } + await expect(callGetUserOpHashWithCode(entryPoint, op1, '0x' + '00'.repeat(23)).catch(e => { + throw new Error(decodeRevertReason(e.data)!) + })).to.be.rejectedWith(`Eip7702SenderNotDelegate(${toChecksumAddress(op1.sender)})`) }) describe('test with geth', () => { @@ -160,6 +169,7 @@ describe('EntryPoint EIP-7702 tests', function () { let delegate: TestEip7702DelegateAccount const beneficiary = createAddress() let eoa: Wallet + let bundler: Wallet let entryPoint: EntryPoint before(async () => { @@ -167,17 +177,19 @@ describe('EntryPoint EIP-7702 tests', function () { geth = new GethExecutable() await geth.init() eoa = createAccountOwner(geth.provider) + bundler = createAccountOwner(geth.provider) entryPoint = await deployEntryPoint(geth.provider) - delegate = await new TestEip7702DelegateAccount__factory(geth.provider.getSigner()).deploy() + delegate = await new TestEip7702DelegateAccount__factory(geth.provider.getSigner()).deploy(entryPoint.address) console.log('\tdelegate addr=', delegate.address, 'len=', await geth.provider.getCode(delegate.address).then(code => code.length)) await geth.sendTx({ to: eoa.address, value: gethHex(parseEther('1')) }) + await geth.sendTx({ to: bundler.address, value: gethHex(parseEther('1')) }) }) it('should fail without sender delegate', async () => { const eip7702userOp = await fillSignAndPack({ sender: eoa.address, nonce: 0, - initCode: INITCODE_EIP7702_MARKER // not init function, just delegate + isEip7702: true }, eoa, entryPoint, { eip7702delegate: delegate.address }) const handleOpCall = { to: entryPoint.address, @@ -185,16 +197,16 @@ describe('EntryPoint EIP-7702 tests', function () { gasLimit: 1000000 // authorizationList: [eip7702tuple] } - expect(await geth.call(handleOpCall).catch(e => { - return e.error - })).to.match(/not an EIP-7702 delegate|sender has no code/) + await expect(geth.call(handleOpCall).catch(e => { + throw new Error(decodeRevertReason(e.error.data)!) + })).to.rejectedWith(`Eip7702SenderWithoutCode(${toChecksumAddress(eoa.address)})`) }) it('should succeed with authorizationList', async () => { const eip7702userOp = await fillAndSign({ sender: eoa.address, nonce: 0, - initCode: INITCODE_EIP7702_MARKER // not init function, just delegate + isEip7702: true }, eoa, entryPoint, { eip7702delegate: delegate.address }) const eip7702tuple = await signEip7702Authorization(eoa, { address: delegate.address, @@ -214,12 +226,12 @@ describe('EntryPoint EIP-7702 tests', function () { }) }) - // skip until auth works. it('should succeed and call initcode', async () => { const eip7702userOp = await fillSignAndPack({ sender: eoa.address, nonce: 0, - initCode: hexConcat([INITCODE_EIP7702_MARKER + '0'.repeat(42 - INITCODE_EIP7702_MARKER.length), delegate.interface.encodeFunctionData('testInit')]) + isEip7702: true, + factoryData: delegate.interface.encodeFunctionData('testInit') }, eoa, entryPoint, { eip7702delegate: delegate.address }) const eip7702tuple = await signEip7702Authorization(eoa, { @@ -236,6 +248,39 @@ describe('EntryPoint EIP-7702 tests', function () { await geth.call(handleOpCall).catch(e => { throw Error(decodeRevertReason(e)!) }) + // note: we are now sending the actual tx from the EOA, so the authorization nonce has to be incremented first + // handleOpCall.authorizationList[0] = await signEip7702Authorization(eoa, { + // address: delegate.address, + // nonce: await geth.provider.getTransactionCount(eoa.address) + 1, + // chainId: await geth.provider.getNetwork().then(net => net.chainId) + // }) + const rawTx = await signEip7702RawTransaction(bundler, handleOpCall) + const txHash = await geth.provider.send('eth_sendRawTransaction', [rawTx]) + await sleep(100) + const receipt = await geth.provider.getTransactionReceipt(txHash) + + // Check if EIP-7702 authorization was applied correctly + const eoaCode = await geth.provider.getCode(eoa.address) + const eoaAsDelegate = new TestEip7702DelegateAccount__factory(geth.provider.getSigner()).attach(eoa.address) + expect(eoaCode).to.equal(`0xef0100${delegate.address.toLowerCase().slice(2)}`, 'EOA code should contain the delegate address') + expect(receipt.status).to.equal(1, 'handleOps failed') + expect(await eoaAsDelegate.testInitCalled()).to.be.true + + // cannot use 'expectEvent' because the transaction needs to be mined first for the receipt checks + const initEvent = receipt.logs + .map(log => { + try { + return entryPoint.interface.parseLog(log) + } catch { + return null + } + }) + .filter(event => event !== null) + .find(event => event?.name === 'EIP7702AccountInitialized') + + expect(initEvent).to.exist + expect(initEvent?.args[1]).to.equal(eoa.address) + expect(initEvent?.args[2]).to.equal(delegate.address) }) after(async () => { diff --git a/dependencies/eth-infinitism-account-abstraction-0.8.0/test/entrypoint.test.ts b/dependencies/eth-infinitism-account-abstraction-0.9.0/test/entrypoint.test.ts similarity index 86% rename from dependencies/eth-infinitism-account-abstraction-0.8.0/test/entrypoint.test.ts rename to dependencies/eth-infinitism-account-abstraction-0.9.0/test/entrypoint.test.ts index f3a49de..5a7ce60 100644 --- a/dependencies/eth-infinitism-account-abstraction-0.8.0/test/entrypoint.test.ts +++ b/dependencies/eth-infinitism-account-abstraction-0.9.0/test/entrypoint.test.ts @@ -29,6 +29,7 @@ import { TestSignatureAggregator, TestSignatureAggregator__factory, TestWarmColdAccount__factory, + TestCurrentUserOpHash__factory, SimpleAccount__factory } from '../typechain' @@ -44,13 +45,16 @@ import { import { PackedUserOperation, UserOperation } from './UserOperation' import { PopulatedTransaction } from 'ethers/lib/ethers' import { ethers } from 'hardhat' -import { arrayify, defaultAbiCoder, hexZeroPad, parseEther } from 'ethers/lib/utils' +import { arrayify, defaultAbiCoder, hexZeroPad, parseEther, hexConcat } from 'ethers/lib/utils' import { BytesLike } from '@ethersproject/bytes' import { toChecksumAddress } from 'ethereumjs-util' import { getERC165InterfaceID } from '../src/Utils' import { UserOperationEventEvent } from '../typechain/contracts/interfaces/IEntryPoint' import { AddressZero, + HashZero, + ONE_ETH, + TWO_ETH, calcGasUsage, checkForGeth, createAccount, @@ -61,15 +65,13 @@ import { findUserOpWithMin, fund, getAccountAddress, - getAccountInitCode, - getAggregatedAccountInitCode, + getAccountFactoryData, + getAggregatedAccountFactoryData, getBalance, - HashZero, - ONE_ETH, parseValidationData, rethrow, + tonumber, tostr, - TWO_ETH, unpackAccountGasFees } from './testutils' import Debug from 'debug' @@ -83,6 +85,7 @@ describe('EntryPoint', function () { let accountOwner: Wallet const ethersSigner = ethers.provider.getSigner() let simpleAccount: SimpleAccount + let chainId: number const globalUnstakeDelaySec = 2 const paymasterStake = ethers.utils.parseEther('2') @@ -93,7 +96,7 @@ describe('EntryPoint', function () { this.timeout(20000) await checkForGeth() - const chainId = await ethers.provider.getNetwork().then(net => net.chainId) + chainId = await ethers.provider.getNetwork().then(net => net.chainId) entryPoint = await deployEntryPoint() @@ -131,13 +134,13 @@ describe('EntryPoint', function () { describe('without stake', () => { it('should fail to stake without value', async () => { - await expect(entryPoint.addStake(2)).to.revertedWith('no stake specified') + await expect(entryPoint.addStake(2)).to.revertedWith('InvalidStake(0, 0)') }) it('should fail to stake without delay', async () => { - await expect(entryPoint.callStatic.addStake(0, { value: ONE_ETH })).to.revertedWith('must specify unstake delay') + await expect(entryPoint.addStake(0, { value: ONE_ETH })).to.revertedWith('InvalidUnstakeDelay(0, 0)') }) it('should fail to unlock', async () => { - await expect(entryPoint.callStatic.unlockStake()).to.revertedWith('not staked') + await expect(entryPoint.unlockStake()).to.revertedWith('NotStaked(0, 0, false)') }) }) describe('with stake of 2 eth', () => { @@ -161,7 +164,7 @@ describe('EntryPoint', function () { expect(stakeAfter).to.eq(stake.add(ONE_ETH)) }) it('should fail to withdraw before unlock', async () => { - await expect(entryPoint.withdrawStake(AddressZero)).to.revertedWith('must call unlockStake() first') + await expect(entryPoint.withdrawStake(AddressZero)).to.revertedWith('StakeNotUnlocked(0,') }) describe('with unlocked stake', () => { before(async () => { @@ -181,10 +184,10 @@ describe('EntryPoint', function () { }) }) it('should fail to withdraw before unlock timeout', async () => { - await expect(entryPoint.withdrawStake(AddressZero)).to.revertedWith('Stake withdrawal is not due') + await expect(entryPoint.withdrawStake(AddressZero)).to.revertedWith('WithdrawalNotDue') }) it('should fail to unlock again', async () => { - await expect(entryPoint.callStatic.unlockStake()).to.revertedWith('already unstaking') + await expect(entryPoint.unlockStake()).to.revertedWith('NotStaked(3000000000000000000, 2, false)') }) describe('after unstake delay', () => { before(async () => { @@ -212,7 +215,7 @@ describe('EntryPoint', function () { }) it('should fail to unlock again', async () => { - await expect(entryPoint.callStatic.unlockStake()).to.revertedWith('already unstaking') + await expect(entryPoint.unlockStake()).to.revertedWith('NotStaked(3000000000000000000, 2, false)') }) it('should succeed to withdraw', async () => { const { stake } = await entryPoint.getDepositInfo(addr) @@ -253,7 +256,8 @@ describe('EntryPoint', function () { // note: for the actual opcode and storage rule restrictions see the reference bundler ValidationManager it('should not use banned ops during simulateValidation', async () => { const op1 = await fillSignAndPack({ - initCode: getAccountInitCode(accountOwner1.address, simpleAccountFactory), + factory: simpleAccountFactory.address, + factoryData: getAccountFactoryData(accountOwner1.address, simpleAccountFactory), sender: await getAccountAddress(accountOwner1.address, simpleAccountFactory) }, accountOwner1, entryPoint) await fund(op1.sender) @@ -289,7 +293,6 @@ describe('EntryPoint', function () { sender: maliciousAccount.address, nonce: await entryPoint.getNonce(maliciousAccount.address, 0), signature: defaultAbiCoder.encode(['uint256'], [block.baseFeePerGas]), - initCode: '0x', callData: '0x', callGasLimit: '0x' + 1e5.toString(16), verificationGasLimit: '0x' + 1e5.toString(16), @@ -547,6 +550,35 @@ describe('EntryPoint', function () { expect(userOpEvent.args.success).to.eql(false) }) + it('should expose the currentUserOpHash to the execution', async function () { + const testCurrentUserOpHash = await new TestCurrentUserOpHash__factory(ethersSigner).deploy() + const innerCallData = testCurrentUserOpHash.interface.encodeFunctionData('getCurrentUserOpHashFromEntryPoint', [entryPoint.address]) + const callData = simpleAccount.interface.encodeFunctionData('execute', [testCurrentUserOpHash.address, 0, innerCallData]) + const userOp1 = await fillAndSign({ + sender: simpleAccount.address, + nonce, + callData, + callGasLimit: 1000000, + maxFeePerGas, + maxPriorityFeePerGas, + verificationGasLimit: 1000000 + }, accountOwner, entryPoint) + const userOp2 = await fillAndSign({ + sender: simpleAccount.address, + nonce: nonce + 1, + callData, + callGasLimit: 1000000, + maxFeePerGas, + maxPriorityFeePerGas, + verificationGasLimit: 1000000 + }, accountOwner, entryPoint) + const result = await entryPoint.handleOps([packUserOp(userOp1), packUserOp(userOp2)], beneficiary) + const receipt = await result.wait() + expect(receipt.status).to.equal(1, 'handleOps failed') + await expect(result).to.emit(testCurrentUserOpHash, 'GotCurrentUserOpHash').withArgs(0, getUserOpHash(userOp1, entryPoint.address, chainId)) + await expect(result).to.emit(testCurrentUserOpHash, 'GotCurrentUserOpHash').withArgs(1, getUserOpHash(userOp2, entryPoint.address, chainId)) + }) + it('with paymaster', async function () { const current = await counter.counters(simpleAccount.address) @@ -679,19 +711,20 @@ describe('EntryPoint', function () { }, entryPoint) const beneficiary = createAddress() await expect(entryPoint.handleOps([packUserOp(userop)], beneficiary).catch(rethrow())).to.be - .revertedWith('FailedOpWithRevert(0,"AA23 reverted",)') + .revertedWith('FailedOpWithRevert(0,"AA23 reverted",0x)') }) - it('should fail with AA23 (and original error) if account reverts', async () => { + it('should fail with AA23 and original error if account reverts', async () => { // deploy an account with broken entrypoint, so it always reverts with "not from EntryPoint" - const revertingAccount = await new SimpleAccount__factory(ethersSigner).deploy(createAddress()) + const incorrectEntryPointAddress = createAddress() + const revertingAccount = await new SimpleAccount__factory(ethersSigner).deploy(incorrectEntryPointAddress) const userop = await fillUserOp({ sender: revertingAccount.address, nonce: 0 }, entryPoint) const beneficiary = createAddress() await expect(entryPoint.handleOps([packUserOp(userop)], beneficiary).catch(rethrow())).to.be - .revertedWith('FailedOpWithRevert(0,"AA23 reverted",Error(account: not from EntryPoint)') + .revertedWith(`FailedOpWithRevert(0,"AA23 reverted",NotFromEntryPoint(${entryPoint.address},${revertingAccount.address},${incorrectEntryPointAddress}))`) }) it('account should pay a penalty for unused gas only above threshold', async function () { @@ -705,17 +738,26 @@ describe('EntryPoint', function () { // "warmup" userop, for better gas calculation, below await entryPoint.handleOps( - [await fillSignAndPack({ sender: simpleAccount.address, callData: accountExec.data }, accountOwner, entryPoint)], + [await fillSignAndPack({ + sender: simpleAccount.address, + callData: accountExec.data + }, accountOwner, entryPoint)], beneficiaryAddress) await entryPoint.handleOps( - [await fillSignAndPack({ sender: simpleAccount.address, callData: accountExec.data }, accountOwner, entryPoint)], + [await fillSignAndPack({ + sender: simpleAccount.address, + callData: accountExec.data + }, accountOwner, entryPoint)], beneficiaryAddress) - const callGasLimit = await ethersSigner.provider.estimateGas({ + let callGasLimit = await ethersSigner.provider.estimateGas({ from: entryPoint.address, to: simpleAccount.address, data: accountExec.data }) + // TODO: fix; for some reason when switched to solhint 6 and custom errors, + // the gas estimation became too high and triggerred the penalty immediately. + callGasLimit = callGasLimit.sub(4000) const snap = await ethers.provider.send('evm_snapshot', []) // First send a userOp with the estimated callGasLimit it needs @@ -756,7 +798,6 @@ describe('EntryPoint', function () { let expectedGasPenalty = 0 let actualGasPenalty = gasUsed2 - gasUsed1 - console.log(expectedGasPenalty, actualGasPenalty) expect(actualGasPenalty).to.be.eq(expectedGasPenalty) await ethers.provider.send('evm_revert', [snap]) @@ -781,7 +822,6 @@ describe('EntryPoint', function () { expectedGasPenalty = (callGasLimitWithUnusedGas.toNumber() - callGasLimit.toNumber()) * PENALTY_PERCENTAGE / 100 actualGasPenalty = gasUsed3 - gasUsed1 - console.log(expectedGasPenalty, actualGasPenalty) expect(actualGasPenalty).to.be.closeTo(expectedGasPenalty, expectedGasPenalty * 0.01) }) @@ -859,26 +899,6 @@ describe('EntryPoint', function () { await calcGasUsage(rcpt, entryPoint, beneficiaryAddress) }) - it('should fail to call recursively into handleOps', async () => { - const beneficiaryAddress = createAddress() - - const callHandleOps = entryPoint.interface.encodeFunctionData('handleOps', [[], beneficiaryAddress]) - const execHandlePost = simpleAccount.interface.encodeFunctionData('execute', [entryPoint.address, 0, callHandleOps]) - const op = await fillSignAndPack({ - sender: simpleAccount.address, - callData: execHandlePost - }, accountOwner, entryPoint) - - const rcpt = await entryPoint.handleOps([op], beneficiaryAddress, { - gasLimit: 1e7 - }).then(async r => r.wait()) - - const error = rcpt.events?.find(ev => ev.event === 'UserOperationRevertReason') - // console.log(rcpt.events!.map(e => ({ ev: e.event, ...objdump(e.args!) }))) - - expect(decodeRevertReason(error?.args?.revertReason)).to.eql('ReentrancyGuardReentrantCall()', - 'execution of handleOps inside a UserOp should revert') - }) it('should report failure on insufficient verificationGas after creation', async () => { const op0 = await fillSignAndPack({ sender: simpleAccount.address, @@ -902,14 +922,16 @@ describe('EntryPoint', function () { it('should reject create if SenderCreator not called from EntryPoint', async () => { const senderCreatorAddress = await entryPoint.senderCreator() const senderCreator = SenderCreator__factory.connect(senderCreatorAddress, ethersSigner) + const ethersSignerAddress = await ethersSigner.getAddress() await expect( senderCreator.createSender('0xdeadbeef', { gasLimit: 1000000 }) - ).to.be.revertedWith('AA97 should call from EntryPoint') + ).to.be.revertedWith(`NotFromEntryPoint("${ethersSignerAddress}", "${senderCreator.address}", "${entryPoint.address}")`) }) it('should reject create if sender address is wrong', async () => { const op = await fillSignAndPack({ - initCode: getAccountInitCode(accountOwner.address, simpleAccountFactory), + factory: simpleAccountFactory.address, + factoryData: getAccountFactoryData(accountOwner.address, simpleAccountFactory), verificationGasLimit: 2e6, sender: '0x'.padEnd(42, '1') }, accountOwner, entryPoint) @@ -921,7 +943,8 @@ describe('EntryPoint', function () { it('should reject create if account not funded', async () => { const op = await fillSignAndPack({ - initCode: getAccountInitCode(accountOwner.address, simpleAccountFactory, 100), + factory: simpleAccountFactory.address, + factoryData: getAccountFactoryData(accountOwner.address, simpleAccountFactory, 100), verificationGasLimit: 2e6 }, accountOwner, entryPoint) @@ -940,7 +963,8 @@ describe('EntryPoint', function () { const preAddr = await getAccountAddress(accountOwner.address, simpleAccountFactory, salt) await fund(preAddr) createOp = await fillSignAndPack({ - initCode: getAccountInitCode(accountOwner.address, simpleAccountFactory, salt), + factory: simpleAccountFactory.address, + factoryData: getAccountFactoryData(accountOwner.address, simpleAccountFactory, salt), callGasLimit: 1e6, verificationGasLimit: 2e6 @@ -959,15 +983,31 @@ describe('EntryPoint', function () { await calcGasUsage(rcpt!, entryPoint, beneficiaryAddress) }) - it('should reject if account already created', async function () { - const preAddr = await getAccountAddress(accountOwner.address, simpleAccountFactory) - if (await ethers.provider.getCode(preAddr).then(x => x.length) === 2) { - this.skip() - } + it('should accept and ignore initCode if account already created', async function () { + const salt = 20 + const sender = await getAccountAddress(accountOwner.address, simpleAccountFactory, salt) + const factoryData = getAccountFactoryData(accountOwner.address, simpleAccountFactory, salt) + let code = await ethers.provider.getCode(sender) + expect(code).to.not.equal('0x') + const createOp = await fillSignAndPack({ + sender, + factory: simpleAccountFactory.address, + factoryData, + callGasLimit: 1e6, + verificationGasLimit: 2e6 + }, accountOwner, entryPoint) + code = await ethers.provider.getCode(sender) + expect(code).to.not.equal('0x') - await expect(entryPoint.callStatic.handleOps([createOp], beneficiaryAddress, { + const hash = await entryPoint.getUserOpHash(createOp) + // eslint-disable-next-line @typescript-eslint/no-base-to-string + const factoryAddress = toChecksumAddress(createOp.initCode.toString().slice(0, 42)) + await expect(entryPoint.handleOps([createOp], beneficiaryAddress, { gasLimit: 1e7 - })).to.revertedWith('sender already constructed') + })) + .to + .emit(entryPoint, 'IgnoredInitCode') + .withArgs(hash, createOp.sender, factoryAddress) }) }) @@ -1000,7 +1040,8 @@ describe('EntryPoint', function () { await fund(account2.address) // execute and increment counter const op1 = await fillSignAndPack({ - initCode: getAccountInitCode(accountOwner1.address, simpleAccountFactory), + factory: simpleAccountFactory.address, + factoryData: getAccountFactoryData(accountOwner1.address, simpleAccountFactory), callData: accountExecCounterFromEntryPoint.data, callGasLimit: 2e6, verificationGasLimit: 2e6 @@ -1182,16 +1223,18 @@ describe('EntryPoint', function () { }) context('create account', () => { + // todo: rename to 'factoryData' let initCode: BytesLike let addr: string let userOp: PackedUserOperation before(async () => { const factory = await new TestAggregatedAccountFactory__factory(ethersSigner).deploy(entryPoint.address, aggregator.address) - initCode = await getAggregatedAccountInitCode(entryPoint.address, factory) - addr = await entryPoint.callStatic.getSenderAddress(initCode).catch(e => e.errorArgs.sender) + initCode = await getAggregatedAccountFactoryData(entryPoint.address, factory) + addr = await entryPoint.callStatic.getSenderAddress(hexConcat([factory.address, initCode])).catch(e => e.errorArgs.sender) await ethersSigner.sendTransaction({ to: addr, value: parseEther('0.1') }) userOp = await fillSignAndPack({ - initCode + factory: factory.address, + factoryData: initCode }, accountOwner, entryPoint) }) it('simulateValidation should return aggregator and its stake', async () => { @@ -1234,12 +1277,13 @@ describe('EntryPoint', function () { it('handleOps should fail with zero-address paymaster', async () => { const op = await fillSignAndPack({ callData: accountExecFromEntryPoint.data, - initCode: getAccountInitCode(account2Owner.address, simpleAccountFactory), + factory: simpleAccountFactory.address, + factoryData: getAccountFactoryData(account2Owner.address, simpleAccountFactory), verificationGasLimit: 3e6, callGasLimit: 1e6 }, account2Owner, entryPoint) op.paymasterAndData = AddressZero.padEnd(200, '0') - await expect(entryPoint.handleOps([op], beneficiaryAddress)).to.revertedWith('AA98 invalid paymaster') + await expect(entryPoint.handleOps([op], beneficiaryAddress)).to.revertedWith('InvalidPaymaster("0x0000000000000000000000000000000000000000")') }) it('should fail with nonexistent paymaster', async () => { const pm = createAddress() @@ -1248,7 +1292,8 @@ describe('EntryPoint', function () { paymaster: pm, paymasterVerificationGasLimit: 3e6, callData: accountExecFromEntryPoint.data, - initCode: getAccountInitCode(account2Owner.address, simpleAccountFactory), + factory: simpleAccountFactory.address, + factoryData: getAccountFactoryData(account2Owner.address, simpleAccountFactory), verificationGasLimit: 3e6, callGasLimit: 1e6 }, account2Owner, entryPoint) @@ -1260,7 +1305,8 @@ describe('EntryPoint', function () { paymaster: testPaymasterAcceptAll.address, paymasterVerificationGasLimit: 3e6, callData: accountExecFromEntryPoint.data, - initCode: getAccountInitCode(account2Owner.address, simpleAccountFactory), + factory: simpleAccountFactory.address, + factoryData: getAccountFactoryData(account2Owner.address, simpleAccountFactory), verificationGasLimit: 3e6, callGasLimit: 1e6 @@ -1280,7 +1326,8 @@ describe('EntryPoint', function () { paymasterPostOpGasLimit: 1e5, paymasterVerificationGasLimit: 3e6, callData: accountExecFromEntryPoint.data, - initCode: getAccountInitCode(account3Owner.address, simpleAccountFactory), + factory: simpleAccountFactory.address, + factoryData: getAccountFactoryData(account3Owner.address, simpleAccountFactory), verificationGasLimit: 3e6, callGasLimit: 1e6 @@ -1304,7 +1351,8 @@ describe('EntryPoint', function () { const op = await fillSignAndPack({ paymaster: errorPostOp.address, callData: accountExecFromEntryPoint.data, - initCode: getAccountInitCode(account3Owner.address, simpleAccountFactory), + factory: simpleAccountFactory.address, + factoryData: getAccountFactoryData(account3Owner.address, simpleAccountFactory), verificationGasLimit: 3e6, callGasLimit: 1e6 @@ -1318,14 +1366,15 @@ describe('EntryPoint', function () { async function testPaymasterActualGasCost (withPostOp: boolean): Promise { const paymaster = withPostOp ? testPaymasterWithPostOp : testPaymasterAcceptAll await paymaster.deposit({ value: ONE_ETH }) - const unpackedOp = { + const unpackedOp: Partial = { maxFeePerGas: 1, maxPriorityFeePerGas: 1, callGasLimit: 5e5, paymaster: paymaster.address, paymasterVerificationGasLimit: 1e6, - callData: accountExecFromEntryPoint.data, - initCode: getAccountInitCode(account2Owner.address, simpleAccountFactory), + callData: accountExecFromEntryPoint.data!, + factory: simpleAccountFactory.address, + factoryData: getAccountFactoryData(account2Owner.address, simpleAccountFactory), paymasterPostOpGasLimit: withPostOp ? 1e4 : undefined } const op = await fillSignAndPack(unpackedOp, account2Owner, entryPoint) @@ -1356,8 +1405,8 @@ describe('EntryPoint', function () { const unusedGas = BigNumber.from(1e7) const opWithUnusedGas = await fillSignAndPack({ ...unpackedOp, - callGasLimit: unpackedOp.callGasLimit + unusedGas.toNumber(), - paymasterPostOpGasLimit: withPostOp ? unpackedOp.paymasterPostOpGasLimit! + unusedGas.toNumber() : undefined + callGasLimit: tonumber(unpackedOp.callGasLimit) + unusedGas.toNumber(), + paymasterPostOpGasLimit: withPostOp ? tonumber(unpackedOp.paymasterPostOpGasLimit!) + unusedGas.toNumber() : undefined }, account2Owner, entryPoint) const maxFeePerGas = BigNumber.from(unpackAccountGasFees(opWithUnusedGas.gasFees as string).maxFeePerGas) @@ -1414,7 +1463,8 @@ describe('EntryPoint', function () { paymaster: testPaymasterAcceptAll.address, paymasterVerificationGasLimit: 1e6, callData: accountExecFromEntryPoint.data, - initCode: getAccountInitCode(anOwner.address, simpleAccountFactory) + factory: simpleAccountFactory.address, + factoryData: getAccountFactoryData(anOwner.address, simpleAccountFactory) }, anOwner, entryPoint) const { paymasterInfo } = await simulateValidation(op, entryPoint.address) @@ -1431,11 +1481,15 @@ describe('EntryPoint', function () { describe('Validation time-range', () => { const beneficiary = createAddress() let testExpiryAccount: TestExpiryAccount + let testExpirePaymaster: TestExpirePaymaster let now: number let sessionOwner: Wallet before('init account with session key', async () => { // create a test account. The primary owner is the global ethersSigner, so that we can easily add a temporaryOwner, below testExpiryAccount = await new TestExpiryAccount__factory(ethersSigner).deploy(entryPoint.address) + testExpirePaymaster = await new TestExpirePaymaster__factory(ethersSigner).deploy(entryPoint.address) + await testExpirePaymaster.addStake(1, { value: paymasterStake }) + await testExpirePaymaster.deposit({ value: parseEther('0.1') }) await testExpiryAccount.initialize(await ethersSigner.getAddress()) await ethersSigner.sendTransaction({ to: testExpiryAccount.address, value: parseEther('0.1') }) now = await ethers.provider.getBlock('latest').then(block => block.timestamp) @@ -1504,7 +1558,7 @@ describe('EntryPoint', function () { expect(validAfter).to.eql(321) }) }) - describe('handleOps should abort on time-range', () => { + describe('handleOps should abort on invalid time-range or block-range', () => { it('should revert on expired account', async () => { const expiredOwner = createAccountOwner() await testExpiryAccount.addTemporaryOwner(expiredOwner.address, 1, 2) @@ -1524,6 +1578,56 @@ describe('EntryPoint', function () { await expect(entryPoint.handleOps([userOp], beneficiary)) .to.revertedWith('AA22 expired or not due') }) + + it('should revert on expired account block range', async () => { + const expiredOwner = createAccountOwner() + await testExpiryAccount.addTemporaryOwner(expiredOwner.address, BigNumber.from(0x800000000001), BigNumber.from(0x800000000003)) + const userOp = await fillSignAndPack({ + sender: testExpiryAccount.address + }, expiredOwner, entryPoint) + await expect(entryPoint.handleOps([userOp], beneficiary)) + .to.revertedWith('AA27 outside valid block range') + }) + + it('should accept account with valid block range', async () => { + const expiredOwner = createAccountOwner() + const blockNumber = await ethers.provider.getBlockNumber() + const validAfter = 0x800000000000 + blockNumber + 1 + const validUntil = 0x800000000000 + blockNumber + 2 + await testExpiryAccount.addTemporaryOwner(expiredOwner.address, validAfter, validUntil) + const userOp = await fillSignAndPack({ + sender: testExpiryAccount.address + }, expiredOwner, entryPoint) + await entryPoint.handleOps([userOp], beneficiary) + }) + + it('should revert on expired paymaster block range', async () => { + const blockRange = defaultAbiCoder.encode(['uint48', 'uint48'], [0x800000000001, 0x800000000002]) + const expiredOwner = createAccountOwner() + await testExpiryAccount.addTemporaryOwner(expiredOwner.address, 0, 0xffffffffffff) + const userOp = await fillSignAndPack({ + sender: testExpiryAccount.address, + paymaster: testExpirePaymaster.address, + paymasterData: blockRange + }, expiredOwner, entryPoint) + await expect(entryPoint.handleOps([userOp], beneficiary)) + .to.revertedWith('AA37 paymaster inval block range') + }) + + it('should accept paymaster with valid block range', async () => { + const expiredOwner = createAccountOwner() + await testExpiryAccount.addTemporaryOwner(expiredOwner.address, 0, 0xffffffffffff) + const blockNumber = await ethers.provider.getBlockNumber() + const validAfter = 0x800000000000 + blockNumber + const validUntil = 0x800000000000 + blockNumber + 1 + const blockRange = defaultAbiCoder.encode(['uint48', 'uint48'], [validAfter, validUntil]) + const userOp = await fillSignAndPack({ + sender: testExpiryAccount.address, + paymaster: testExpirePaymaster.address, + paymasterData: blockRange + }, expiredOwner, entryPoint) + await entryPoint.handleOps([userOp], beneficiary) + }) }) }) }) diff --git a/dependencies/eth-infinitism-account-abstraction-0.8.0/test/entrypointsimulations.test.ts b/dependencies/eth-infinitism-account-abstraction-0.9.0/test/entrypointsimulations.test.ts similarity index 92% rename from dependencies/eth-infinitism-account-abstraction-0.8.0/test/entrypointsimulations.test.ts rename to dependencies/eth-infinitism-account-abstraction-0.9.0/test/entrypointsimulations.test.ts index 65e1530..30ae434 100644 --- a/dependencies/eth-infinitism-account-abstraction-0.8.0/test/entrypointsimulations.test.ts +++ b/dependencies/eth-infinitism-account-abstraction-0.9.0/test/entrypointsimulations.test.ts @@ -16,10 +16,13 @@ import { createAccount, createAccountOwner, createAddress, + decodeRevertReason, + deployEntryPoint, + findSimulationUserOpWithMin, fund, getAccountAddress, - getAccountInitCode, - getBalance, deployEntryPoint, decodeRevertReason, findSimulationUserOpWithMin + getAccountFactoryData, + getBalance } from './testutils' import { fillAndSign, fillSignAndPack, packUserOp, simulateHandleOp, simulateValidation } from './UserOp' @@ -68,6 +71,7 @@ describe('EntryPointSimulations', function () { expect(diff).to.be.within(0, max, `${message} cost ${simCost.toNumber()} should be (up to ${max}) above ep cost ${epCost.toNumber()}`) } + it('deposit on simulation must be >= real entrypoint', async () => { costInRange( await epSimulation.estimateGas.depositTo(addr, { value: 1 }), @@ -149,7 +153,10 @@ describe('EntryPointSimulations', function () { }) it('should revert on oog if not enough verificationGas', async () => { - const op = await fillSignAndPack({ sender: account.address, verificationGasLimit: 1000 }, accountOwner, entryPoint) + const op = await fillSignAndPack({ + sender: account.address, + verificationGasLimit: 1000 + }, accountOwner, entryPoint) await expect(simulateValidation(op, entryPoint.address)).to .revertedWith('AA23 reverted') }) @@ -190,7 +197,8 @@ describe('EntryPointSimulations', function () { it('should fail creation for wrong sender', async () => { const op1 = await fillSignAndPack({ - initCode: getAccountInitCode(accountOwner1.address, simpleAccountFactory), + factory: simpleAccountFactory.address, + factoryData: getAccountFactoryData(accountOwner1.address, simpleAccountFactory), sender: '0x'.padEnd(42, '1'), verificationGasLimit: 30e6 }, accountOwner1, entryPoint) @@ -199,10 +207,11 @@ describe('EntryPointSimulations', function () { }) it('should report failure on insufficient verificationGas (OOG) for creation', async () => { - const initCode = getAccountInitCode(accountOwner1.address, simpleAccountFactory) - const sender = await entryPoint.callStatic.getSenderAddress(initCode).catch(e => e.errorArgs.sender) + const initCode = getAccountFactoryData(accountOwner1.address, simpleAccountFactory) + const sender = await entryPoint.callStatic.getSenderAddress(hexConcat([simpleAccountFactory.address, initCode])).catch(e => e.errorArgs.sender) const op0 = await fillSignAndPack({ - initCode, + factory: simpleAccountFactory.address, + factoryData: initCode, sender, verificationGasLimit: 5e5, maxFeePerGas: 0 @@ -211,7 +220,8 @@ describe('EntryPointSimulations', function () { await simulateValidation(op0, entryPoint.address, { gas: '0xF4240' }) const op1 = await fillSignAndPack({ - initCode, + factory: simpleAccountFactory.address, + factoryData: initCode, sender, verificationGasLimit: 1e5, maxFeePerGas: 0 @@ -224,7 +234,8 @@ describe('EntryPointSimulations', function () { const sender = await getAccountAddress(accountOwner1.address, simpleAccountFactory) const op1 = await fillSignAndPack({ sender, - initCode: getAccountInitCode(accountOwner1.address, simpleAccountFactory) + factory: simpleAccountFactory.address, + factoryData: getAccountFactoryData(accountOwner1.address, simpleAccountFactory) }, accountOwner1, entryPoint) await fund(op1.sender) @@ -237,10 +248,8 @@ describe('EntryPointSimulations', function () { const sender = createAddress() const op1 = await fillSignAndPack({ verificationGasLimit: 150000, // providing default value as gas estimation will fail - initCode: hexConcat([ - account.address, - account.interface.encodeFunctionData('execute', [sender, 0, '0x']) - ]), + factory: account.address, + factoryData: account.interface.encodeFunctionData('execute', [sender, 0, '0x']), sender }, accountOwner, entryPoint) const error = await simulateValidation(op1, entryPoint.address).catch(e => e) @@ -311,10 +320,7 @@ describe('EntryPointSimulations', function () { it('should simulate creation', async () => { const accountOwner1 = createAccountOwner() const factory = await new SimpleAccountFactory__factory(ethersSigner).deploy(entryPoint.address) - const initCode = hexConcat([ - factory.address, - factory.interface.encodeFunctionData('createAccount', [accountOwner1.address, 0]) - ]) + const factoryData = factory.interface.encodeFunctionData('createAccount', [accountOwner1.address, 0]) const sender = await factory.getAddress(accountOwner1.address, 0) @@ -328,7 +334,8 @@ describe('EntryPointSimulations', function () { // deliberately broken signature. simulate should work with it too. const userOp = await fillSignAndPack({ sender, - initCode, + factory: factory.address, + factoryData, callData, callGasLimit: 1e5 // fillAndSign can't estimate calls during creation }, accountOwner1, entryPoint) diff --git a/dependencies/eth-infinitism-account-abstraction-0.8.0/test/helpers.test.ts b/dependencies/eth-infinitism-account-abstraction-0.9.0/test/helpers.test.ts similarity index 100% rename from dependencies/eth-infinitism-account-abstraction-0.8.0/test/helpers.test.ts rename to dependencies/eth-infinitism-account-abstraction-0.9.0/test/helpers.test.ts diff --git a/dependencies/eth-infinitism-account-abstraction-0.9.0/test/paymaster-signature.test.ts b/dependencies/eth-infinitism-account-abstraction-0.9.0/test/paymaster-signature.test.ts new file mode 100644 index 0000000..c3c1e02 --- /dev/null +++ b/dependencies/eth-infinitism-account-abstraction-0.9.0/test/paymaster-signature.test.ts @@ -0,0 +1,75 @@ +import { + createAccount, + createAccountOwner, + createAddress, decodeRevertReason, + deployEntryPoint +} from './testutils' +import { fillAndSign, fillSignAndPack, packUserOp, encodePaymasterSignature } from './UserOp' +import { ethers } from 'hardhat' +import { + EntryPoint, SimpleAccount, + TestPaymasterWithSig, TestPaymasterWithSig__factory +} from '../typechain' +import { expect } from 'chai' +import { defaultAbiCoder, hexConcat, parseEther } from 'ethers/lib/utils' + +describe('#paymaster-signature', () => { + const ethersSigner = ethers.provider.getSigner() + let entryPoint: EntryPoint + + let paymaster: TestPaymasterWithSig + + const beneficiary = createAddress() + let account: SimpleAccount + + before(async function () { + entryPoint = await deployEntryPoint() + + paymaster = await new TestPaymasterWithSig__factory(ethersSigner).deploy(entryPoint.address) + await entryPoint.depositTo(paymaster.address, { value: parseEther('1') }) + const created = await createAccount(ethersSigner, owner.address, entryPoint.address) + account = created.proxy + }) + + const owner = createAccountOwner() + const signedPmd = defaultAbiCoder.encode(['uint256'], ['0x11']) + it('test without any paymasterSig', async () => { + const op = await fillSignAndPack({ + sender: account.address, + paymaster: paymaster.address, + paymasterData: signedPmd + }, owner, entryPoint) + + expect(await entryPoint.handleOps([op], beneficiary) + .catch(decodeRevertReason)).to + .match(/missing paymasterSig/) + }) + + it('test with paymasterSig', async () => { + // sign with any signature (even empty) - but it does encode it with the magic suffix. + const op = await fillAndSign({ + sender: account.address, + paymaster: paymaster.address, + paymasterData: signedPmd, + paymasterSignature: '0x12' + }, owner, entryPoint) + + op.paymasterSignature = defaultAbiCoder.encode(['uint256', 'uint256'], [10, 90]) + + // submit userOp with paymasterSignature + await entryPoint.callStatic.handleOps([packUserOp(op)], beneficiary) + .catch(e => { + throw new Error(decodeRevertReason(e)!) + }) + + const unsignedPmd = defaultAbiCoder.encode(['uint256'], ['0xaa11']) + op.paymasterData = hexConcat([ + unsignedPmd, + encodePaymasterSignature( + defaultAbiCoder.encode(['uint256', 'uint256'], [10, 90])) + ]) + + // modifying paymasterData should cause signature failure + expect(await entryPoint.handleOps([packUserOp(op)], beneficiary).catch(decodeRevertReason)).to.match(/AA24 signature error/) + }) +}) diff --git a/dependencies/eth-infinitism-account-abstraction-0.8.0/test/postop.test.ts b/dependencies/eth-infinitism-account-abstraction-0.9.0/test/postop.test.ts similarity index 100% rename from dependencies/eth-infinitism-account-abstraction-0.8.0/test/postop.test.ts rename to dependencies/eth-infinitism-account-abstraction-0.9.0/test/postop.test.ts diff --git a/dependencies/eth-infinitism-account-abstraction-0.8.0/test/simple-wallet.test.ts b/dependencies/eth-infinitism-account-abstraction-0.9.0/test/simple-wallet.test.ts similarity index 92% rename from dependencies/eth-infinitism-account-abstraction-0.8.0/test/simple-wallet.test.ts rename to dependencies/eth-infinitism-account-abstraction-0.9.0/test/simple-wallet.test.ts index 5fa6b6d..467efe3 100644 --- a/dependencies/eth-infinitism-account-abstraction-0.8.0/test/simple-wallet.test.ts +++ b/dependencies/eth-infinitism-account-abstraction-0.9.0/test/simple-wallet.test.ts @@ -52,8 +52,10 @@ describe('SimpleAccount', function () { }) it('other account should not be able to call transfer', async () => { const { proxy: account } = await createAccount(ethers.provider.getSigner(), accounts[0], entryPoint.address) - await expect(account.connect(ethers.provider.getSigner(1)).execute(accounts[2], ONE_ETH, '0x')) - .to.be.revertedWith('account: not Owner or EntryPoint') + const ethersSigner = ethers.provider.getSigner(1) + const ethersSignerAddress = await ethersSigner.getAddress() + await expect(account.connect(ethersSigner).execute(accounts[2], ONE_ETH, '0x')) + .to.be.revertedWith(`NotOwnerOrEntryPoint("${ethersSignerAddress}", "${account.address}", "${entryPoint.address}", "${accounts[0]}")`) }) it('should pack in js the same as solidity', async () => { @@ -145,11 +147,12 @@ describe('SimpleAccount', function () { it('should reject calls coming from any address that is not SenderCreator', async () => { const ownerAddr = createAddress() let deployer = await new SimpleAccountFactory__factory(ethersSigner).deploy(entryPoint.address) + const ethersSignerAddress = await ethersSigner.getAddress() + const senderCreator = await entryPoint.senderCreator() await expect(deployer.createAccount(ownerAddr, 1234)) - .to.be.revertedWith('only callable from SenderCreator') + .to.be.revertedWith(`NotSenderCreator("${ethersSignerAddress}", "${deployer.address}", "${senderCreator}")`) // switch deployer contract to an impersonating signer - const senderCreator = await entryPoint.senderCreator() await (ethersSigner.provider as JsonRpcProvider).send('hardhat_setBalance', [senderCreator, toHex(100e18)]) const senderCreatorSigner = await ethers.getImpersonatedSigner(senderCreator) deployer = deployer.connect(senderCreatorSigner) diff --git a/dependencies/eth-infinitism-account-abstraction-0.8.0/test/solidityTypes.ts b/dependencies/eth-infinitism-account-abstraction-0.9.0/test/solidityTypes.ts similarity index 100% rename from dependencies/eth-infinitism-account-abstraction-0.8.0/test/solidityTypes.ts rename to dependencies/eth-infinitism-account-abstraction-0.9.0/test/solidityTypes.ts diff --git a/dependencies/eth-infinitism-account-abstraction-0.8.0/test/testExecAccount.test.ts b/dependencies/eth-infinitism-account-abstraction-0.9.0/test/testExecAccount.test.ts similarity index 100% rename from dependencies/eth-infinitism-account-abstraction-0.8.0/test/testExecAccount.test.ts rename to dependencies/eth-infinitism-account-abstraction-0.9.0/test/testExecAccount.test.ts diff --git a/dependencies/eth-infinitism-account-abstraction-0.8.0/test/testutils.ts b/dependencies/eth-infinitism-account-abstraction-0.9.0/test/testutils.ts similarity index 93% rename from dependencies/eth-infinitism-account-abstraction-0.8.0/test/testutils.ts rename to dependencies/eth-infinitism-account-abstraction-0.9.0/test/testutils.ts index 41b9b74..4b88e09 100644 --- a/dependencies/eth-infinitism-account-abstraction-0.8.0/test/testutils.ts +++ b/dependencies/eth-infinitism-account-abstraction-0.9.0/test/testutils.ts @@ -2,7 +2,6 @@ import { ethers } from 'hardhat' import { toHex } from 'hardhat/internal/util/bigint' import { arrayify, - hexConcat, hexDataSlice, hexlify, hexZeroPad, @@ -15,19 +14,22 @@ import { EntryPoint, EntryPoint__factory, IERC20, + Simple7702Account__factory, SimpleAccount, + SimpleAccountFactory, SimpleAccountFactory__factory, SimpleAccount__factory, - SimpleAccountFactory, - TestAggregatedAccountFactory, TestPaymasterRevertCustomError__factory, TestERC20__factory + TestAggregatedAccountFactory, + TestERC20__factory, + TestPaymasterRevertCustomError__factory } from '../typechain' -import { BytesLike, Hexable } from '@ethersproject/bytes' +import { BytesLike } from '@ethersproject/bytes' import { JsonRpcProvider, Provider } from '@ethersproject/providers' import { expect } from 'chai' import { Create2Factory } from '../src/Create2Factory' import { debugTransaction } from './debugTx' import { UserOperation } from './UserOperation' -import { packUserOp, simulateValidation } from './UserOp' +import { encodePaymasterSignature, packUserOp, simulateValidation } from './UserOp' import Debug from 'debug' import { toChecksumAddress } from 'ethereumjs-util' @@ -105,20 +107,14 @@ export async function calcGasUsage (rcpt: ContractReceipt, entryPoint: EntryPoin } // helper function to create the initCode to deploy the account, using our account factory. -export function getAccountInitCode (owner: string, factory: SimpleAccountFactory, salt = 0): BytesLike { - return hexConcat([ - factory.address, - factory.interface.encodeFunctionData('createAccount', [owner, salt]) - ]) +export function getAccountFactoryData (owner: string, factory: SimpleAccountFactory, salt = 0): BytesLike { + return factory.interface.encodeFunctionData('createAccount', [owner, salt]) } -export async function getAggregatedAccountInitCode (entryPoint: string, factory: TestAggregatedAccountFactory, salt = 0): Promise { +export async function getAggregatedAccountFactoryData (entryPoint: string, factory: TestAggregatedAccountFactory, salt = 0): Promise { // the test aggregated account doesn't check the owner... const owner = AddressZero - return hexConcat([ - factory.address, - factory.interface.encodeFunctionData('createAccount', [owner, salt]) - ]) + return factory.interface.encodeFunctionData('createAccount', [owner, salt]) } // given the parameters as AccountDeployer, return the resulting "counterfactual address" that it would create. @@ -171,6 +167,7 @@ const decodeRevertReasonContracts = new Interface([ ...EntryPoint__factory.createInterface().fragments, ...TestPaymasterRevertCustomError__factory.createInterface().fragments, ...TestERC20__factory.createInterface().fragments, // for OZ errors, + ...Simple7702Account__factory.createInterface().fragments, 'error ECDSAInvalidSignature()' ]) // .filter(f => f.type === 'error')) @@ -199,7 +196,7 @@ export function decodeRevertReason (data: string | Error, nullIfNoMatch = true): // treat any error "bytes" argument as possible error to decode (e.g. FailedOpWithRevert, PostOpReverted) const args = err.args.map((arg: any, index) => { switch (err.errorFragment.inputs[index].type) { - case 'bytes' : return decodeRevertReason(arg) + case 'bytes' : return decodeRevertReason(arg, false) case 'string': return `"${(arg as string)}"` default: return arg } @@ -325,10 +322,20 @@ export function packAccountGasLimits (verificationGasLimit: BigNumberish, callGa ]) } -export function packPaymasterData (paymaster: string, paymasterVerificationGasLimit: BytesLike | Hexable | number | bigint, postOpGasLimit: BytesLike | Hexable | number | bigint, paymasterData: string): string { +export function packPaymasterData ( + paymaster: string, + paymasterVerificationGasLimit: BigNumberish, + postOpGasLimit: BigNumberish, + paymasterData: BytesLike | undefined, + paymasterSignature: BytesLike | undefined, + forSigning: boolean +): string { return ethers.utils.hexConcat([ - paymaster, hexZeroPad(hexlify(paymasterVerificationGasLimit, { hexPad: 'left' }), 16), - hexZeroPad(hexlify(postOpGasLimit, { hexPad: 'left' }), 16), paymasterData + paymaster, + hexZeroPad(hexlify(paymasterVerificationGasLimit, { hexPad: 'left' }), 16), + hexZeroPad(hexlify(postOpGasLimit, { hexPad: 'left' }), 16), + paymasterData ?? '0x', + encodePaymasterSignature(paymasterSignature, forSigning) ]) } diff --git a/dependencies/eth-infinitism-account-abstraction-0.9.0/test/userOpHash.test.ts b/dependencies/eth-infinitism-account-abstraction-0.9.0/test/userOpHash.test.ts new file mode 100644 index 0000000..d296032 --- /dev/null +++ b/dependencies/eth-infinitism-account-abstraction-0.9.0/test/userOpHash.test.ts @@ -0,0 +1,155 @@ +import { createAddress, decodeRevertReason, deployEntryPoint } from './testutils' +import { EntryPoint, TestHelpers, TestHelpers__factory } from '../typechain' +import { UserOperation } from './UserOperation' +import { getUserOpHash, PAYMASTER_SIG_MAGIC, packUserOp } from './UserOp' +import { expect } from 'chai' +import { hexConcat, hexDataLength, hexDataSlice, hexZeroPad, keccak256 } from 'ethers/lib/utils' +import { ethers } from 'hardhat' + +import * as chai from 'chai' +import chaiAsPromised from 'chai-as-promised' + +chai.use(chaiAsPromised) + +const provider = ethers.provider +const ethersSigner = provider.getSigner() + +// encode a paymaster signature, to append to the paymasterData field. +export function encodePaymasterSignature (pmSig: string): string { + if (pmSig.length <= 2) { + return '0x' + } + return hexConcat([pmSig, hexZeroPad('0x' + hexDataLength(pmSig).toString(16), 2), PAYMASTER_SIG_MAGIC]) +} + +describe('#getUserOpHash', () => { + let entryPoint: EntryPoint + + let chainId: number + before(async () => { + entryPoint = await deployEntryPoint() + chainId = (await entryPoint.provider.getNetwork()).chainId + }) + + const defaultUserOp: UserOperation = { + sender: createAddress(), + nonce: 123, + callData: '0xca11', + callGasLimit: 10, + verificationGasLimit: 20, + preVerificationGas: 30, + maxFeePerGas: 40, + maxPriorityFeePerGas: 50, + signature: '0xdeadface', + paymaster: createAddress(), + paymasterVerificationGasLimit: 60, + paymasterPostOpGasLimit: 70, + paymasterData: '0xcafe' + } + + describe('UserOperationLib funcs', () => { + let helpers: TestHelpers + before(async () => { + helpers = await new TestHelpers__factory(ethersSigner).deploy() + }) + it('#encodePaymasterSignature', async () => { + expect(await helpers.encodePaymasterSignature('0x')).to.equal( + encodePaymasterSignature('0x')) + expect(await helpers.encodePaymasterSignature('0x123456')).to.equal( + encodePaymasterSignature('0x123456')) + }) + + it('#getPaymasterSignatureLength', async () => { + expect(await helpers.getPaymasterSignatureLength('0x')).to.equal(0) + expect(await helpers.getPaymasterSignatureLength('0x1234')).to.equal(0) + expect(await helpers.getPaymasterSignatureLength(hexConcat([hexZeroPad('0x', 52), '0x0000', PAYMASTER_SIG_MAGIC]))).to.equal(0) + expect(await helpers.getPaymasterSignatureLength(hexConcat([hexZeroPad('0x', 53), '0x0001', PAYMASTER_SIG_MAGIC]))).to.equal(1) + }) + it('#getPaymasterSignatureLength should not extend before paymasterData', async () => { + await expect(helpers.getPaymasterSignatureLength(hexConcat([hexZeroPad('0x', 52), '0x0001', PAYMASTER_SIG_MAGIC])) + .catch(e => { + throw new Error(decodeRevertReason(e.data)!) + })) + .to.be.rejectedWith('InvalidPaymasterSignatureLength(62,1)') + await expect(helpers.getPaymasterSignatureLength(hexConcat([hexZeroPad('0x', 53), '0x0002', PAYMASTER_SIG_MAGIC])) + .catch(e => { + throw new Error(decodeRevertReason(e.data)!) + })) + .to.be.rejectedWith('InvalidPaymasterSignatureLength(63,2)') + }) + + it('#paymasterDataKeccak', async () => { + const suffix = '0x1122334455667788' + expect(await helpers._calldataKeccakWithSuffix('0xabcdef', 2, suffix)).to + .eql(keccak256(hexConcat(['0xabcd', suffix]))) + }) + + it('#getPaymasterSignature', async () => { + // getPaymasterSignature expects a valid pmSig length, as returned by getPaymasterSignatureLength + expect(await helpers.getPaymasterSignatureWithLength('0x', 0)).to.equal('0x') + await expect(helpers.getPaymasterSignatureWithLength('0x', 123)).revertedWith('') + }) + }) + + function createUserOp (overrides: Partial = {}): UserOperation { + return { + ...defaultUserOp, ...overrides + } + } + + async function epGetUserOpHash (userOp: UserOperation): Promise { + return entryPoint.getUserOpHash(packUserOp(userOp, false)) + } + + describe('#getUserOpHash', () => { + // check that helper getUserOpHash matches solidity implementation + async function checkUserOpHash (userOp: UserOperation): Promise { + // console.log('packed=', packUserOp(userOp)) + expect(await epGetUserOpHash(userOp)) + .to.equal(getUserOpHash(userOp, entryPoint.address, chainId)) + } + + it('simpler userOp', async () => { + await checkUserOpHash(createUserOp()) + }) + it('simpler userOp without paymaster', async () => { + await checkUserOpHash(createUserOp({ paymaster: undefined })) + }) + + it('with valid pmSignature', async () => { + await checkUserOpHash(createUserOp({ paymasterData: '0xcafe', paymasterSignature: '0x123456' })) + }) + + it('with invalid length pmSignature', async () => { + // length is longer than actual data + const pmSignatureLength = 200 + const pmSig = hexDataSlice(encodePaymasterSignature(hexZeroPad('0x', pmSignatureLength)), 180) + // if pmSignature is broken, it is OK for getUserOpHash to revert... + const userOp = createUserOp({ paymasterData: hexConcat(['0xcafe', pmSig]) }) + const dataLength = hexDataLength(packUserOp(userOp).paymasterAndData) + await expect(checkUserOpHash(userOp).catch(e => { + throw new Error(decodeRevertReason(e.data)!) + })).to.rejectedWith(`InvalidPaymasterSignatureLength(${dataLength},${pmSignatureLength})`) + }) + }) + + it('appending paymasterSig to paymasterData should change userOpHash', async () => { + expect(await epGetUserOpHash(createUserOp({ + paymasterData: '0xcafe' + }) + )).to.not.eql(await epGetUserOpHash(createUserOp({ + paymasterData: '0xcafe', paymasterSignature: '0x1234' + }) + )) + }) + + it('changing paymasterSig to paymasterData should not change userOpHash', async () => { + expect(await epGetUserOpHash(createUserOp({ + paymasterData: '0xcafe', paymasterSignature: '0x1234' + }) + )).to.eql(await epGetUserOpHash(createUserOp({ + paymasterData: '0xcafe', paymasterSignature: '0xabcdef' + }) + )) + }) +}) diff --git a/dependencies/eth-infinitism-account-abstraction-0.8.0/tsconfig.json b/dependencies/eth-infinitism-account-abstraction-0.9.0/tsconfig.json similarity index 100% rename from dependencies/eth-infinitism-account-abstraction-0.8.0/tsconfig.json rename to dependencies/eth-infinitism-account-abstraction-0.9.0/tsconfig.json diff --git a/dependencies/eth-infinitism-account-abstraction-0.8.0/yarn.lock b/dependencies/eth-infinitism-account-abstraction-0.9.0/yarn.lock similarity index 95% rename from dependencies/eth-infinitism-account-abstraction-0.8.0/yarn.lock rename to dependencies/eth-infinitism-account-abstraction-0.9.0/yarn.lock index 3b9b4fa..a72b95a 100644 --- a/dependencies/eth-infinitism-account-abstraction-0.8.0/yarn.lock +++ b/dependencies/eth-infinitism-account-abstraction-0.9.0/yarn.lock @@ -24,6 +24,15 @@ js-tokens "^4.0.0" picocolors "^1.0.0" +"@babel/code-frame@^7.27.1": + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.27.1.tgz#200f715e66d52a23b221a9435534a91cc13ad5be" + integrity sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg== + dependencies: + "@babel/helper-validator-identifier" "^7.27.1" + js-tokens "^4.0.0" + picocolors "^1.1.1" + "@babel/generator@^7.26.5": version "7.26.5" resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.26.5.tgz#e44d4ab3176bbcaf78a5725da5f1dc28802a9458" @@ -50,6 +59,11 @@ resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.25.9.tgz#24b64e2c3ec7cd3b3c547729b8d16871f22cbdc7" integrity sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ== +"@babel/helper-validator-identifier@^7.27.1": + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.27.1.tgz#a7054dcc145a967dd4dc8fee845a57c1316c9df8" + integrity sha512-D2hP9eA+Sqx1kBZgzxZh0y1trbuU+JoDkiEwqhQ36nodYqJwyEIhPSdMNd7lOm/4io72luTPWH20Yda0xOuUow== + "@babel/highlight@^7.22.13": version "7.22.20" resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.22.20.tgz#4ca92b71d80554b01427815e06f2df965b9c1f54" @@ -233,7 +247,7 @@ "@ethersproject/properties" ">=5.0.0-beta.131" "@ethersproject/strings" ">=5.0.0-beta.130" -"@ethersproject/abi@5.7.0", "@ethersproject/abi@^5.0.9", "@ethersproject/abi@^5.1.2", "@ethersproject/abi@^5.5.0", "@ethersproject/abi@^5.7.0": +"@ethersproject/abi@5.7.0", "@ethersproject/abi@^5.1.2", "@ethersproject/abi@^5.5.0", "@ethersproject/abi@^5.7.0": version "5.7.0" resolved "https://registry.yarnpkg.com/@ethersproject/abi/-/abi-5.7.0.tgz#b3f3e045bbbeed1af3947335c247ad625a44e449" integrity sha512-351ktp42TiRcYB3H1OP8yajPeAQstMW/yCFokj/AthP9bLHzQFPlOrxOcwYEDkUAICmOHljvN4K39OMTMUa9RA== @@ -594,6 +608,11 @@ resolved "https://registry.yarnpkg.com/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz#af5b2691a22b44be847b0ca81641c5fb6ad0172c" integrity sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA== +"@humanwhocodes/momoa@^2.0.4": + version "2.0.4" + resolved "https://registry.yarnpkg.com/@humanwhocodes/momoa/-/momoa-2.0.4.tgz#8b9e7a629651d15009c3587d07a222deeb829385" + integrity sha512-RE815I4arJFtt+FVeU1Tgp9/Xvecacji8w/V6XtXsWWH/wz/eNkNbhb+ny/+PlVZjV0rxQpRSQKNKE3lcktHEA== + "@humanwhocodes/object-schema@^1.2.1": version "1.2.1" resolved "https://registry.yarnpkg.com/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz#b520529ec21d8e5945a1851dfd1c32e94e39ff45" @@ -886,6 +905,27 @@ resolved "https://registry.yarnpkg.com/@openzeppelin/contracts/-/contracts-5.1.0.tgz#4e61162f2a2bf414c4e10c45eca98ce5f1aadbd4" integrity sha512-p1ULhl7BXzjjbha5aqst+QMLY+4/LCWADXOCsmLHRM77AqiPjnd9vvUN9sosUfhL9JGKpZ0TjEGxgvnizmWGSA== +"@pnpm/config.env-replace@^1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@pnpm/config.env-replace/-/config.env-replace-1.1.0.tgz#ab29da53df41e8948a00f2433f085f54de8b3a4c" + integrity sha512-htyl8TWnKL7K/ESFa1oW2UB5lVDxuF5DpM7tBi6Hu2LNL3mWkIzNLG6N4zoCUP1lCKNxWy/3iu8mS8MvToGd6w== + +"@pnpm/network.ca-file@^1.0.1": + version "1.0.2" + resolved "https://registry.yarnpkg.com/@pnpm/network.ca-file/-/network.ca-file-1.0.2.tgz#2ab05e09c1af0cdf2fcf5035bea1484e222f7983" + integrity sha512-YcPQ8a0jwYU9bTdJDpXjMi7Brhkr1mXsXrUJvjqM2mQDgkRiz8jFaQGOdaLxgjtUfQgZhKy/O3cG/YwmgKaxLA== + dependencies: + graceful-fs "4.2.10" + +"@pnpm/npm-conf@^2.1.0": + version "2.3.1" + resolved "https://registry.yarnpkg.com/@pnpm/npm-conf/-/npm-conf-2.3.1.tgz#bb375a571a0bd63ab0a23bece33033c683e9b6b0" + integrity sha512-c83qWb22rNRuB0UaVCI0uRPNRr8Z0FWnEIvT47jiHAmOIUHbBOg5XvV7pM5x+rKn9HRpjxquDbXYSXr3fAKFcw== + dependencies: + "@pnpm/config.env-replace" "^1.1.0" + "@pnpm/network.ca-file" "^1.0.1" + config-chain "^1.1.11" + "@resolver-engine/core@^0.3.3": version "0.3.3" resolved "https://registry.yarnpkg.com/@resolver-engine/core/-/core-0.3.3.tgz#590f77d85d45bc7ecc4e06c654f41345db6ca967" @@ -1040,17 +1080,15 @@ resolved "https://registry.yarnpkg.com/@sindresorhus/is/-/is-4.6.0.tgz#3c7c9c46e678feefe7a2e5bb609d3dbd665ffb3f" integrity sha512-t09vSN3MdfsyCHoFcTRCH/iUtG7OJ0CsjzB8cjAmKc/va/kIgeDI/TxsigdncE/4be734m0cvIYwNaV4i2XqAw== -"@solidity-parser/parser@^0.16.0": - version "0.16.1" - resolved "https://registry.yarnpkg.com/@solidity-parser/parser/-/parser-0.16.1.tgz#f7c8a686974e1536da0105466c4db6727311253c" - integrity sha512-PdhRFNhbTtu3x8Axm0uYpqOy/lODYQK+MlYSgqIsq2L8SFYEHJPHNUiOTAJbDGzNjjr1/n9AcIayxafR/fWmYw== - dependencies: - antlr4ts "^0.5.0-alpha.4" +"@sindresorhus/is@^5.2.0": + version "5.6.0" + resolved "https://registry.yarnpkg.com/@sindresorhus/is/-/is-5.6.0.tgz#41dd6093d34652cddb5d5bdeee04eafc33826668" + integrity sha512-TV7t8GKYaJWsn00tFDqBw8+Uqmr8A0fRU1tvTQhyZzGv0sJCGRQL3JGMI3ucuKo3XIZdUP+Lx7/gh2t3lewy7g== -"@solidity-parser/parser@^0.19.0": - version "0.19.0" - resolved "https://registry.yarnpkg.com/@solidity-parser/parser/-/parser-0.19.0.tgz#37a8983b2725af9b14ff8c4a475fa0e98d773c3f" - integrity sha512-RV16k/qIxW/wWc+mLzV3ARyKUaMUTBy9tOLMzFhtNSKYeTAanQ3a5MudJKf/8arIFnA2L27SNjarQKmFg0w/jA== +"@solidity-parser/parser@^0.20.2": + version "0.20.2" + resolved "https://registry.yarnpkg.com/@solidity-parser/parser/-/parser-0.20.2.tgz#e07053488ed60dae1b54f6fe37bb6d2c5fe146a7" + integrity sha512-rbu0bzwNvMcwAjH86hiEAcOeRI2EeK8zCkHDrFykh/Al8mvJeFmjy3UrE7GYQjNwOgbGUUtCn5/k8CB8zIu7QA== "@szmarczak/http-timer@^1.1.2": version "1.1.2" @@ -1066,6 +1104,13 @@ dependencies: defer-to-connect "^2.0.0" +"@szmarczak/http-timer@^5.0.1": + version "5.0.1" + resolved "https://registry.yarnpkg.com/@szmarczak/http-timer/-/http-timer-5.0.1.tgz#c7c1bf1141cdd4751b0399c8fc7b8b664cd5be3a" + integrity sha512-+PmQX0PiAYPMeVYe237LJAYvOMYW1j2rH5YROyS3b4CTVJum34HfRvKvAzozHAQG0TnHNdUfY9nCeUyRAs//cw== + dependencies: + defer-to-connect "^2.0.1" + "@tsconfig/node10@^1.0.7": version "1.0.9" resolved "https://registry.yarnpkg.com/@tsconfig/node10/-/node10-1.0.9.tgz#df4907fc07a886922637b15e02d4cebc4c0021b2" @@ -1132,10 +1177,24 @@ "@types/node" "*" "@types/responselike" "^1.0.0" -"@types/chai@^4.2.21": - version "4.3.9" - resolved "https://registry.yarnpkg.com/@types/chai/-/chai-4.3.9.tgz#144d762491967db8c6dea38e03d2206c2623feec" - integrity sha512-69TtiDzu0bcmKQv3yg1Zx409/Kd7r0b5F1PfpYJfSHzLGtB53547V4u+9iqKYsTu/O2ai6KTb0TInNpvuQ3qmg== +"@types/chai-as-promised@^7.1.8": + version "7.1.8" + resolved "https://registry.yarnpkg.com/@types/chai-as-promised/-/chai-as-promised-7.1.8.tgz#f2b3d82d53c59626b5d6bbc087667ccb4b677fe9" + integrity sha512-ThlRVIJhr69FLlh6IctTXFkmhtP3NpMZ2QGq69StYLyKZFp/HOp1VdKZj7RvfNWYYcJ1xlbLGLLWj1UvP5u/Gw== + dependencies: + "@types/chai" "*" + +"@types/chai@*": + version "5.2.2" + resolved "https://registry.yarnpkg.com/@types/chai/-/chai-5.2.2.tgz#6f14cea18180ffc4416bc0fd12be05fdd73bdd6b" + integrity sha512-8kB30R7Hwqf40JPiKhVzodJs2Qc1ZJ5zuT3uzw5Hq/dhNCl3G3l83jfpdI1e20BP348+fV7VIL/+FxaXkqBmWg== + dependencies: + "@types/deep-eql" "*" + +"@types/chai@^4.3.20": + version "4.3.20" + resolved "https://registry.yarnpkg.com/@types/chai/-/chai-4.3.20.tgz#cb291577ed342ca92600430841a00329ba05cecc" + integrity sha512-/pC9HAB5I/xMlc5FP77qjCnI16ChlJfW0tGa0IUcFn38VJrTV6DeZ60NU5KZBtaOZqjdpwTWohz5HU1RrhiYxQ== "@types/debug@^4.1.12": version "4.1.12" @@ -1144,19 +1203,21 @@ dependencies: "@types/ms" "*" -"@types/glob@^7.1.1": - version "7.2.0" - resolved "https://registry.yarnpkg.com/@types/glob/-/glob-7.2.0.tgz#bc1b5bf3aa92f25bd5dd39f35c57361bdce5b2eb" - integrity sha512-ZUxbzKl0IfJILTS6t7ip5fQQM/J3TJYubDm3nMbgubNNYS62eXeUpoLUC8/7fJNiFYHTrGPQn7hspDUzIHX3UA== - dependencies: - "@types/minimatch" "*" - "@types/node" "*" +"@types/deep-eql@*": + version "4.0.2" + resolved "https://registry.yarnpkg.com/@types/deep-eql/-/deep-eql-4.0.2.tgz#334311971d3a07121e7eb91b684a605e7eea9cbd" + integrity sha512-c9h9dVVMigMPc4bwTvC5dxqtqJZwQPePsWjPlpSOnojbor6pGqdk541lfA7AqFQr5pB1BRdq0juY9db81BwyFw== "@types/http-cache-semantics@*": version "4.0.3" resolved "https://registry.yarnpkg.com/@types/http-cache-semantics/-/http-cache-semantics-4.0.3.tgz#a3ff232bf7d5c55f38e4e45693eda2ebb545794d" integrity sha512-V46MYLFp08Wf2mmaBhvgjStM3tPa+2GAdy/iqoX+noX1//zje2x4XmrIU0cAwyClATsTmahbtoQ2EwP7I5WSiA== +"@types/http-cache-semantics@^4.0.2": + version "4.0.4" + resolved "https://registry.yarnpkg.com/@types/http-cache-semantics/-/http-cache-semantics-4.0.4.tgz#b979ebad3919799c979b17c72621c0bc0a31c6c4" + integrity sha512-1m0bIFVc7eJWyve9S0RnuRgcQqF/Xd5QsUZAZeQFr1Q3/p9JWoQQEqmVy+DPTNpGXwhgIetAoYF8JSc33q29QA== + "@types/json-schema@^7.0.9": version "7.0.14" resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.14.tgz#74a97a5573980802f32c8e47b663530ab3b6b7d1" @@ -1179,11 +1240,6 @@ resolved "https://registry.yarnpkg.com/@types/lru-cache/-/lru-cache-5.1.1.tgz#c48c2e27b65d2a153b19bfc1a317e30872e01eef" integrity sha512-ssE3Vlrys7sdIzs5LOxCzTVMsU7i9oa/IaW92wF32JFb3CVczqOkru2xspuKczHEbG3nvmPY7IFqVmGGHdNbYw== -"@types/minimatch@*": - version "5.1.2" - resolved "https://registry.yarnpkg.com/@types/minimatch/-/minimatch-5.1.2.tgz#07508b45797cb81ec3f273011b054cd0755eddca" - integrity sha512-K0VQKziLUWkVKiRVrx4a40iPaxTUefQmjtkQofBkYRcoaaL/8rhwDWww9qWbrgicNOgnpIsMxyNIUM4+n6dUIA== - "@types/minimatch@^3.0.3": version "3.0.5" resolved "https://registry.yarnpkg.com/@types/minimatch/-/minimatch-3.0.5.tgz#1001cc5e6a3704b83c236027e77f2f58ea010f40" @@ -1485,16 +1541,6 @@ resolved "https://registry.yarnpkg.com/@yarnpkg/lockfile/-/lockfile-1.1.0.tgz#e77a97fbd345b76d83245edcd17d393b1b41fb31" integrity sha512-GpSwvyXOcOOlV70vbnzjj4fW5xW/FdUF6nQEt1ENy7m4ZCczi1+/buVUPAqmGfqznsORNFzUMjctTIp8a9tuCQ== -abbrev@1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.1.1.tgz#f8f2c887ad10bf67f634f005b6987fed3179aac8" - integrity sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q== - -abbrev@1.0.x: - version "1.0.9" - resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.0.9.tgz#91b4792588a7738c25f35dd6f63752a2f8776135" - integrity sha512-LEyx4aLEC3x6T0UguF6YILf+ntvmOaWsVfENmIW0E9H09vKlLDGelMjjSm0jkDHALj8A8quZ/HapKNigzwge+Q== - abstract-leveldown@3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/abstract-leveldown/-/abstract-leveldown-3.0.0.tgz#5cb89f958a44f526779d740d1440e743e0c30a57" @@ -1576,6 +1622,11 @@ aggregate-error@^3.0.0: clean-stack "^2.0.0" indent-string "^4.0.0" +ajv-errors@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/ajv-errors/-/ajv-errors-1.0.1.tgz#f35986aceb91afadec4102fbd85014950cefa64d" + integrity sha512-DCRfO/4nQ+89p/RK43i8Ezd41EqdGIU4ld7nGF8OQ14oc/we5rEntLCUa7+jrn3nn83BosfwZA0wb4pon2o8iQ== + ajv@^6.12.3, ajv@^6.12.4, ajv@^6.12.6: version "6.12.6" resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4" @@ -1596,11 +1647,6 @@ ajv@^8.0.1: require-from-string "^2.0.2" uri-js "^4.2.2" -amdefine@>=0.0.4: - version "1.0.1" - resolved "https://registry.yarnpkg.com/amdefine/-/amdefine-1.0.1.tgz#4a5282ac164729e93619bcfd3ad151f817ce91f5" - integrity sha512-S2Hw0TtNkMJhIabBwIojKL9YHO5T0n5eNqWJ7Lrlel/zDbftQpxpapi8tZs3X1HWa+u+QeydGmzzNU0m09+Rcg== - ansi-align@^3.0.0: version "3.0.1" resolved "https://registry.yarnpkg.com/ansi-align/-/ansi-align-3.0.1.tgz#0cdf12e111ace773a86e9a1fad1225c43cb19a59" @@ -1613,7 +1659,7 @@ ansi-colors@4.1.1: resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-4.1.1.tgz#cbb9ae256bf750af1eab344f229aa27fe94ba348" integrity sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA== -ansi-colors@^4.1.1, ansi-colors@^4.1.3: +ansi-colors@^4.1.1: version "4.1.3" resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-4.1.3.tgz#37611340eb2243e70cc604cad35d63270d48781b" integrity sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw== @@ -1654,15 +1700,10 @@ ansi-styles@^4.0.0, ansi-styles@^4.1.0: dependencies: color-convert "^2.0.1" -antlr4@^4.11.0: - version "4.13.1" - resolved "https://registry.yarnpkg.com/antlr4/-/antlr4-4.13.1.tgz#1e0a1830a08faeb86217cb2e6c34716004e4253d" - integrity sha512-kiXTspaRYvnIArgE97z5YVVf/cDVQABr3abFRR6mE7yesLMkgu4ujuyV/sgxafQ8wgve0DJQUJ38Z8tkgA2izA== - -antlr4ts@^0.5.0-alpha.4: - version "0.5.0-alpha.4" - resolved "https://registry.yarnpkg.com/antlr4ts/-/antlr4ts-0.5.0-alpha.4.tgz#71702865a87478ed0b40c0709f422cf14d51652a" - integrity sha512-WPQDt1B74OfPv/IMS2ekXAKkTZIHl88uMetg6q3OTqgFxZ/dxDXI0EWLyZid/1Pe6hTftyg5N7gel5wNAGxXyQ== +antlr4@^4.13.1-patch-1: + version "4.13.2" + resolved "https://registry.yarnpkg.com/antlr4/-/antlr4-4.13.2.tgz#0d084ad0e32620482a9c3a0e2470c02e72e4006d" + integrity sha512-QiVbZhyy4xAZ17UPEuG3YTOt8ZaoeOR1CvEAqrEsDBsOqINslaB147i9xqljZqoyf5S+EUlGStaj+t22LT9MOg== anymatch@~3.1.2: version "3.1.3" @@ -1822,11 +1863,6 @@ arraybuffer.prototype.slice@^1.0.2: is-array-buffer "^3.0.2" is-shared-array-buffer "^1.0.2" -arrify@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/arrify/-/arrify-1.0.1.tgz#898508da2226f380df904728456849c1501a4b0d" - integrity sha512-3CYzex9M9FGQjCGMGyi6/31c8GJbgb0qGyrx5HWxPd0aCwh4cB2YjMb2Xf9UuoogrMrlO9cTqnB5rI5GHZTcUA== - arrify@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/arrify/-/arrify-2.0.1.tgz#c9655e9331e0abcd588d2a7cad7e9956f66701fa" @@ -1886,11 +1922,6 @@ async-limiter@~1.0.0: resolved "https://registry.yarnpkg.com/async-limiter/-/async-limiter-1.0.1.tgz#dd379e94f0db8310b08291f9d64c3209766617fd" integrity sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ== -async@1.x, async@^1.4.2: - version "1.5.2" - resolved "https://registry.yarnpkg.com/async/-/async-1.5.2.tgz#ec6a61ae56480c0c3cb241c95618e20892f9672a" - integrity sha512-nSVgobk4rv61R9PUSDtYt7mPVB2olxNR5RWJcAsH676/ef11bUZwvu7+RGYrYauVdDPcO519v68wRhXQtxsV9w== - async@2.6.2: version "2.6.2" resolved "https://registry.yarnpkg.com/async/-/async-2.6.2.tgz#18330ea7e6e313887f5d2f2a904bac6fe4dd5381" @@ -1898,6 +1929,11 @@ async@2.6.2: dependencies: lodash "^4.17.11" +async@^1.4.2: + version "1.5.2" + resolved "https://registry.yarnpkg.com/async/-/async-1.5.2.tgz#ec6a61ae56480c0c3cb241c95618e20892f9672a" + integrity sha512-nSVgobk4rv61R9PUSDtYt7mPVB2olxNR5RWJcAsH676/ef11bUZwvu7+RGYrYauVdDPcO519v68wRhXQtxsV9w== + async@^2.0.1, async@^2.1.2, async@^2.4.0, async@^2.5.0, async@^2.6.1: version "2.6.4" resolved "https://registry.yarnpkg.com/async/-/async-2.6.4.tgz#706b7ff6084664cd7eae713f6f965433b5504221" @@ -2515,6 +2551,17 @@ bech32@1.1.4: resolved "https://registry.yarnpkg.com/bech32/-/bech32-1.1.4.tgz#e38c9f37bf179b8eb16ae3a772b40c356d4832e9" integrity sha512-s0IrSOzLlbvX7yp4WBfPITzpAU8sqQcpsmwXDiKwrG4r491vwCO/XpejasRNl0piBMe/DvP4Tz0mIS/X1DPJBQ== +better-ajv-errors@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/better-ajv-errors/-/better-ajv-errors-2.0.2.tgz#868e7b9ea091077de0fca41770995868baa30ed6" + integrity sha512-1cLrJXEq46n0hjV8dDYwg9LKYjDb3KbeW7nZTv4kvfoDD9c2DXHIE31nxM+Y/cIfXMggLUfmxbm6h/JoM/yotA== + dependencies: + "@babel/code-frame" "^7.27.1" + "@humanwhocodes/momoa" "^2.0.4" + chalk "^4.1.2" + jsonpointer "^5.0.1" + leven "^3.1.0 < 4" + bignumber.js@^9.0.0: version "9.1.2" resolved "https://registry.yarnpkg.com/bignumber.js/-/bignumber.js-9.1.2.tgz#b7c4242259c008903b13707983b5f4bbd31eda0c" @@ -2654,7 +2701,7 @@ brorand@^1.0.1, brorand@^1.1.0: resolved "https://registry.yarnpkg.com/brorand/-/brorand-1.1.0.tgz#12c25efe40a45e3c323eb8675a0a0ce57b22371f" integrity sha512-cKV8tMCEpQs4hK/ik71d6LrPOnpkpGBR0wzxqr68g2m/LB2GxVYQroAjMJZRVM1Y4BCjCKc3vAamxSzOY2RP+w== -browser-stdout@1.3.1, browser-stdout@^1.3.1: +browser-stdout@1.3.1: version "1.3.1" resolved "https://registry.yarnpkg.com/browser-stdout/-/browser-stdout-1.3.1.tgz#baa559ee14ced73452229bad7326467c61fabd60" integrity sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw== @@ -2737,7 +2784,7 @@ bs58check@^2.1.2: create-hash "^1.1.0" safe-buffer "^5.1.2" -buffer-from@^1.0.0, buffer-from@^1.1.0: +buffer-from@^1.0.0: version "1.1.2" resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.2.tgz#2b146a6fd72e80b4f55d255f35ed59a3a9a41bd5" integrity sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ== @@ -2814,6 +2861,24 @@ cacheable-lookup@^5.0.3: resolved "https://registry.yarnpkg.com/cacheable-lookup/-/cacheable-lookup-5.0.4.tgz#5a6b865b2c44357be3d5ebc2a467b032719a7005" integrity sha512-2/kNscPhpcxrOigMZzbiWF7dz8ilhb/nIHU3EyZiXWXpeq/au8qJ8VhdftMkty3n7Gj6HIGalQG8oiBNB3AJgA== +cacheable-lookup@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/cacheable-lookup/-/cacheable-lookup-7.0.0.tgz#3476a8215d046e5a3202a9209dd13fec1f933a27" + integrity sha512-+qJyx4xiKra8mZrcwhjMRMUhD5NR1R8esPkzIYxX96JiecFoxAXFuz/GpR3+ev4PE1WamHip78wV0vcmPQtp8w== + +cacheable-request@^10.2.8: + version "10.2.14" + resolved "https://registry.yarnpkg.com/cacheable-request/-/cacheable-request-10.2.14.tgz#eb915b665fda41b79652782df3f553449c406b9d" + integrity sha512-zkDT5WAF4hSSoUgyfg5tFIxz8XQK+25W/TLVojJTMKBaxevLBBtLxgqguAuVQB8PVW79FVjHcU+GJ9tVbDZ9mQ== + dependencies: + "@types/http-cache-semantics" "^4.0.2" + get-stream "^6.0.1" + http-cache-semantics "^4.1.1" + keyv "^4.5.3" + mimic-response "^4.0.0" + normalize-url "^8.0.0" + responselike "^3.0.0" + cacheable-request@^6.0.0: version "6.1.0" resolved "https://registry.yarnpkg.com/cacheable-request/-/cacheable-request-6.1.0.tgz#20ffb8bd162ba4be11e9567d823db651052ca912" @@ -2886,10 +2951,17 @@ caseless@~0.12.0: resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc" integrity sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw== -chai@^4.3.4: - version "4.3.10" - resolved "https://registry.yarnpkg.com/chai/-/chai-4.3.10.tgz#d784cec635e3b7e2ffb66446a63b4e33bd390384" - integrity sha512-0UXG04VuVbruMUYbJ6JctvH0YnC/4q3/AkT18q4NaITo91CUm0liMS9VqzT9vZhVQ/1eqPanMWjBM+Juhfb/9g== +chai-as-promised@^7.1.2: + version "7.1.2" + resolved "https://registry.yarnpkg.com/chai-as-promised/-/chai-as-promised-7.1.2.tgz#70cd73b74afd519754161386421fb71832c6d041" + integrity sha512-aBDHZxRzYnUYuIAIPBH2s511DjlKPzXNlXSGFC8CwmroWQLfrW0LtE1nK3MAwwNhJPa9raEjNCmRoFpG0Hurdw== + dependencies: + check-error "^1.0.2" + +chai@^4.5.0: + version "4.5.0" + resolved "https://registry.yarnpkg.com/chai/-/chai-4.5.0.tgz#707e49923afdd9b13a8b0b47d33d732d13812fd8" + integrity sha512-RITGBfijLkBddZvnn8jdqoTypxvqbOLYQkGGxXzeFjVHvudaPw0HNFD9x928/eUwYWd2dPCugVqspGALTZZQKw== dependencies: assertion-error "^1.1.0" check-error "^1.0.3" @@ -2897,7 +2969,7 @@ chai@^4.3.4: get-func-name "^2.0.2" loupe "^2.3.6" pathval "^1.1.1" - type-detect "^4.0.8" + type-detect "^4.1.0" chalk@^1.1.3: version "1.1.3" @@ -2927,7 +2999,7 @@ chalk@^4.0.0, chalk@^4.1.0, chalk@^4.1.2: ansi-styles "^4.1.0" supports-color "^7.1.0" -check-error@^1.0.3: +check-error@^1.0.2, check-error@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/check-error/-/check-error-1.0.3.tgz#a6502e4312a7ee969f646e83bb3ddd56281bd694" integrity sha512-iKEoDYaRmd1mxM90a2OEfWhjsjPpYPuQ+lMYsoxB126+t8fw7ySEO48nmDg5COTjxDI65/Y2OWpeEHk3ZOe8zg== @@ -2956,21 +3028,6 @@ chokidar@3.5.3, chokidar@^3.5.2: optionalDependencies: fsevents "~2.3.2" -chokidar@^3.5.3: - version "3.6.0" - resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.6.0.tgz#197c6cc669ef2a8dc5e7b4d97ee4e092c3eb0d5b" - integrity sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw== - dependencies: - anymatch "~3.1.2" - braces "~3.0.2" - glob-parent "~5.1.2" - is-binary-path "~2.1.0" - is-glob "~4.0.1" - normalize-path "~3.0.0" - readdirp "~3.6.0" - optionalDependencies: - fsevents "~2.3.2" - chokidar@^4.0.0: version "4.0.2" resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-4.0.2.tgz#97b9562c9f59de559177f069eadf5dcc67d24798" @@ -3175,6 +3232,14 @@ concat-stream@^1.5.1: readable-stream "^2.2.2" typedarray "^0.0.6" +config-chain@^1.1.11: + version "1.1.13" + resolved "https://registry.yarnpkg.com/config-chain/-/config-chain-1.1.13.tgz#fad0795aa6a6cdaff9ed1b68e9dff94372c232f4" + integrity sha512-qj+f8APARXHrM0hraqXYb2/bOVSV4PvJQlNZ/DVj0QrmNM2q2euizkeuVckQ57J+W0mRH6Hvi+k50M4Jul2VRQ== + dependencies: + ini "^1.3.4" + proto-list "~1.2.1" + content-disposition@0.5.4: version "0.5.4" resolved "https://registry.yarnpkg.com/content-disposition/-/content-disposition-0.5.4.tgz#8b82b4efac82512a02bb0b1dcec9d2c5e8eb5bfe" @@ -3371,11 +3436,6 @@ dashdash@^1.12.0: dependencies: assert-plus "^1.0.0" -death@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/death/-/death-1.1.0.tgz#01aa9c401edd92750514470b8266390c66c67318" - integrity sha512-vsV6S4KVHvTGxbEcij7hkWRv0It+sGGWVOM67dQde/o5Xjnr+KmLjxWJii2uEObIrt1CcM9w0Yaovx+iOlIL+w== - debug@2.6.9, debug@^2.2.0, debug@^2.3.3, debug@^2.6.8, debug@^2.6.9: version "2.6.9" resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" @@ -3404,13 +3464,6 @@ debug@^3.1.0, debug@^3.2.7: dependencies: ms "^2.1.1" -debug@^4.3.5: - version "4.4.0" - resolved "https://registry.yarnpkg.com/debug/-/debug-4.4.0.tgz#2b3f2aea2ffeb776477460267377dc8710faba8a" - integrity sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA== - dependencies: - ms "^2.1.3" - decamelize@^1.1.1: version "1.2.0" resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290" @@ -3441,9 +3494,9 @@ decompress-response@^6.0.0: mimic-response "^3.1.0" deep-eql@^4.1.3: - version "4.1.3" - resolved "https://registry.yarnpkg.com/deep-eql/-/deep-eql-4.1.3.tgz#7c7775513092f7df98d8df9996dd085eb668cc6d" - integrity sha512-WaEtAOpRA1MQ0eohqZjpGD8zdI0Ovsm8mmFhaDN8dvDZzyoUMcYDnf5Y6iu7HTXxf8JDS23qWa4a+hKCDyOPzw== + version "4.1.4" + resolved "https://registry.yarnpkg.com/deep-eql/-/deep-eql-4.1.4.tgz#d0d3912865911bb8fac5afb4e3acfa6a28dc72b7" + integrity sha512-SUwdGfqdKOwxCPeVYjwSyRpJ7Z+fhpwIAtmCUdZIWZ/YP5R9WAsyuSgpLVDi9bjWoN2LXHNss/dk3urXtdQxGg== dependencies: type-detect "^4.0.0" @@ -3459,12 +3512,12 @@ deep-equal@~1.1.1: object-keys "^1.1.1" regexp.prototype.flags "^1.2.0" -deep-extend@~0.6.0: +deep-extend@^0.6.0, deep-extend@~0.6.0: version "0.6.0" resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.6.0.tgz#c4fa7c95404a17a9c3e8ca7e1537312b736330ac" integrity sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA== -deep-is@^0.1.3, deep-is@~0.1.3: +deep-is@^0.1.3: version "0.1.4" resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.4.tgz#a6f2dce612fadd2ef1f519b73551f17e85199831" integrity sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ== @@ -3474,7 +3527,7 @@ defer-to-connect@^1.0.1: resolved "https://registry.yarnpkg.com/defer-to-connect/-/defer-to-connect-1.1.3.tgz#331ae050c08dcf789f8c83a7b81f0ed94f4ac591" integrity sha512-0ISdNousHvZT2EiFlZeZAHBUvSxmKswVCEf8hW7KWgG4a8MVEu/3Vb6uWYozkjylyCxe0JBIiRB1jV45S70WVQ== -defer-to-connect@^2.0.0: +defer-to-connect@^2.0.0, defer-to-connect@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/defer-to-connect/-/defer-to-connect-2.0.1.tgz#8016bdb4143e4632b77a3449c6236277de520587" integrity sha512-4tvttepXG1VaYGrRibk5EwJd1t4udunSOVMdLSAL6mId1ix438oPwPZMALY41FCijukO1L0twNcGsdzS7dHgDg== @@ -3613,21 +3666,11 @@ diff@5.0.0: resolved "https://registry.yarnpkg.com/diff/-/diff-5.0.0.tgz#7ed6ad76d859d030787ec35855f5b1daf31d852b" integrity sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w== -diff@^3.1.0: - version "3.5.0" - resolved "https://registry.yarnpkg.com/diff/-/diff-3.5.0.tgz#800c0dd1e0a8bfbc95835c202ad220fe317e5a12" - integrity sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA== - diff@^4.0.1: version "4.0.2" resolved "https://registry.yarnpkg.com/diff/-/diff-4.0.2.tgz#60f3aecb89d5fae520c11aa19efc2bb982aade7d" integrity sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A== -diff@^5.2.0: - version "5.2.0" - resolved "https://registry.yarnpkg.com/diff/-/diff-5.2.0.tgz#26ded047cd1179b78b9537d5ef725503ce1ae531" - integrity sha512-uIFDxqpRZGZ6ThOk84hEfqWoHx2devRFvpTZcTHur85vImfaxUbTW9Ryh4CpCuDnToOP1CEtXKIgytHBPVff5A== - diffie-hellman@^5.0.0: version "5.0.3" resolved "https://registry.yarnpkg.com/diffie-hellman/-/diffie-hellman-5.0.3.tgz#40e8ee98f55a2149607146921c63e1ae5f3d2875" @@ -3637,13 +3680,6 @@ diffie-hellman@^5.0.0: miller-rabin "^4.0.0" randombytes "^2.0.0" -difflib@^0.2.4: - version "0.2.4" - resolved "https://registry.yarnpkg.com/difflib/-/difflib-0.2.4.tgz#b5e30361a6db023176d562892db85940a718f47e" - integrity sha512-9YVwmMb0wQHQNr5J9m6BSj6fk4pfGITGQOOs+D9Fl+INODWFOfvhIU1hNv6GgR1RBoC/9NJcwu77zShxV0kT7w== - dependencies: - heap ">= 0.2.0" - dir-glob@^3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/dir-glob/-/dir-glob-3.0.1.tgz#56dbf73d992a4a93ba1584f4534063fd2e41717f" @@ -3906,18 +3942,6 @@ escape-string-regexp@^1.0.2, escape-string-regexp@^1.0.5: resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" integrity sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg== -escodegen@1.8.x: - version "1.8.1" - resolved "https://registry.yarnpkg.com/escodegen/-/escodegen-1.8.1.tgz#5a5b53af4693110bebb0867aa3430dd3b70a1018" - integrity sha512-yhi5S+mNTOuRvyW4gWlg5W1byMaQGWWSYHXsuFZ7GBo7tpyOwi2EdzMP/QWxh9hwkD2m+wDVHJsxhRIj+v/b/A== - dependencies: - esprima "^2.7.1" - estraverse "^1.9.1" - esutils "^2.0.2" - optionator "^0.8.1" - optionalDependencies: - source-map "~0.2.0" - eslint-config-standard-with-typescript@^21.0.1: version "21.0.1" resolved "https://registry.yarnpkg.com/eslint-config-standard-with-typescript/-/eslint-config-standard-with-typescript-21.0.1.tgz#f4c8bb883d8dfd634005239a54c3c222746e3c64" @@ -4085,11 +4109,6 @@ espree@^9.6.0, espree@^9.6.1: acorn-jsx "^5.3.2" eslint-visitor-keys "^3.4.1" -esprima@2.7.x, esprima@^2.7.1: - version "2.7.3" - resolved "https://registry.yarnpkg.com/esprima/-/esprima-2.7.3.tgz#96e3b70d5779f6ad49cd032673d1c312767ba581" - integrity sha512-OarPfz0lFCiW4/AV2Oy1Rp9qu0iusTKqykwTspGCZtPxmF81JR4MmIebvF1F9+UOKth2ZubLQ4XGGaU+hSn99A== - esprima@^4.0.0: version "4.0.1" resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71" @@ -4109,11 +4128,6 @@ esrecurse@^4.3.0: dependencies: estraverse "^5.2.0" -estraverse@^1.9.1: - version "1.9.3" - resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-1.9.3.tgz#af67f2dc922582415950926091a4005d29c9bb44" - integrity sha512-25w1fMXQrGdoquWnScXZGckOv+Wes+JDnuN/+7ex3SauFRS72r2lFDec0EKPt2YD1wUJ/IrfEex+9yp4hfSOJA== - estraverse@^4.1.1: version "4.3.0" resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-4.3.0.tgz#398ad3f3c5a24948be7725e83d11a7de28cdbd1d" @@ -4734,7 +4748,7 @@ fast-diff@^1.2.0: resolved "https://registry.yarnpkg.com/fast-diff/-/fast-diff-1.3.0.tgz#ece407fa550a64d638536cd727e129c61616e0f0" integrity sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw== -fast-glob@^3.0.3, fast-glob@^3.2.9: +fast-glob@^3.2.9: version "3.3.1" resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.3.1.tgz#784b4e897340f3dbbef17413b3f11acf03c874c4" integrity sha512-kNFPyjhh5cKjrUltxs+wFx+ZkbRaxxmZ+X0ZU31SOsxCEtP9VPgtq2teZw1DebupL5GmDaNQ6yKMMVcM41iqDg== @@ -4750,7 +4764,7 @@ fast-json-stable-stringify@^2.0.0: resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633" integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw== -fast-levenshtein@^2.0.6, fast-levenshtein@~2.0.6: +fast-levenshtein@^2.0.6: version "2.0.6" resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" integrity sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw== @@ -4920,6 +4934,11 @@ forever-agent@~0.6.1: resolved "https://registry.yarnpkg.com/forever-agent/-/forever-agent-0.6.1.tgz#fbc71f0c41adeb37f96c577ad1ed42d8fdacca91" integrity sha512-j0KLYPhm6zeac4lz3oJ3o65qvgQCcPubiyotZrXqEaG4hNagNYO8qdlUrX5vwqv9ohqeT/Z3j6+yW067yWWdUw== +form-data-encoder@^2.1.2: + version "2.1.4" + resolved "https://registry.yarnpkg.com/form-data-encoder/-/form-data-encoder-2.1.4.tgz#261ea35d2a70d48d30ec7a9603130fa5515e9cd5" + integrity sha512-yDYSgNMraqvnxiEXO4hi88+YZxaHC6QKzb5N84iRCTDeRO7ZALpir/lVmf/uXUhnwUr2O4HU8s/n6x+yNjQkHw== + form-data@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/form-data/-/form-data-4.0.0.tgz#93919daeaf361ee529584b9b31664dc12c9fa452" @@ -5003,15 +5022,6 @@ fs-extra@^7.0.0, fs-extra@^7.0.1: jsonfile "^4.0.0" universalify "^0.1.0" -fs-extra@^8.1.0: - version "8.1.0" - resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-8.1.0.tgz#49d43c45a88cd9677668cb7be1b46efdb8d2e1c0" - integrity sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g== - dependencies: - graceful-fs "^4.2.0" - jsonfile "^4.0.0" - universalify "^0.1.0" - fs-extra@^9.0.0, fs-extra@^9.1.0: version "9.1.0" resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-9.1.0.tgz#5954460c764a8da2094ba3554bf839e6b9a7c86d" @@ -5140,6 +5150,11 @@ get-stream@^5.1.0: dependencies: pump "^3.0.0" +get-stream@^6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-6.0.1.tgz#a262d8eef67aced57c2852ad6167526a43cbf7b7" + integrity sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg== + get-symbol-description@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/get-symbol-description/-/get-symbol-description-1.0.0.tgz#7fdb81c900101fbd564dd5f1a30af5aadc1e58d6" @@ -5160,14 +5175,6 @@ getpass@^0.1.1: dependencies: assert-plus "^1.0.0" -ghost-testrpc@^0.0.2: - version "0.0.2" - resolved "https://registry.yarnpkg.com/ghost-testrpc/-/ghost-testrpc-0.0.2.tgz#c4de9557b1d1ae7b2d20bbe474a91378ca90ce92" - integrity sha512-i08dAEgJ2g8z5buJIrCTduwPIhih3DP+hOCTyyryikfV8T0bNvHnGXO67i0DD1H4GBDETTclPy9njZbfluQYrQ== - dependencies: - chalk "^2.4.2" - node-emoji "^1.10.0" - glob-parent@^5.1.2, glob-parent@~5.1.2: version "5.1.2" resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4" @@ -5206,18 +5213,7 @@ glob@7.2.0: once "^1.3.0" path-is-absolute "^1.0.0" -glob@^5.0.15: - version "5.0.15" - resolved "https://registry.yarnpkg.com/glob/-/glob-5.0.15.tgz#1bc936b9e02f4a603fcc222ecf7633d30b8b93b1" - integrity sha512-c9IPMazfRITpmAAKi22dK1VKxGDX9ehhqfABDriL/lzO92xcUKEJPQHrVA/2YHSNFB4iFlykVmWvwo48nr3OxA== - dependencies: - inflight "^1.0.4" - inherits "2" - minimatch "2 || 3" - once "^1.3.0" - path-is-absolute "^1.0.0" - -glob@^7.0.0, glob@^7.1.2, glob@^7.1.3, glob@~7.2.3: +glob@^7.1.2, glob@^7.1.3, glob@~7.2.3: version "7.2.3" resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.3.tgz#b8df0fb802bbfa8e89bd1d938b4e16578ed44f2b" integrity sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q== @@ -5229,7 +5225,7 @@ glob@^7.0.0, glob@^7.1.2, glob@^7.1.3, glob@~7.2.3: once "^1.3.0" path-is-absolute "^1.0.0" -glob@^8.0.3, glob@^8.1.0: +glob@^8.0.3: version "8.1.0" resolved "https://registry.yarnpkg.com/glob/-/glob-8.1.0.tgz#d388f656593ef708ee3e34640fdfb99a9fd1c33e" integrity sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ== @@ -5249,13 +5245,6 @@ global-modules@^1.0.0: is-windows "^1.0.1" resolve-dir "^1.0.0" -global-modules@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/global-modules/-/global-modules-2.0.0.tgz#997605ad2345f27f51539bea26574421215c7780" - integrity sha512-NGbfmJBp9x8IxyJSd1P+otYK8vonoJactOogrVfFRIAEY1ukil8RSKDz2Yo7wh1oihl51l/r6W4epkeKJHqL8A== - dependencies: - global-prefix "^3.0.0" - global-prefix@^1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/global-prefix/-/global-prefix-1.0.2.tgz#dbf743c6c14992593c655568cb66ed32c0122ebe" @@ -5267,15 +5256,6 @@ global-prefix@^1.0.1: is-windows "^1.0.1" which "^1.2.14" -global-prefix@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/global-prefix/-/global-prefix-3.0.0.tgz#fc85f73064df69f50421f47f883fe5b913ba9b97" - integrity sha512-awConJSVCHVGND6x3tmMaKcQvwXLhjdkmomy2W+Goaui8YPgYgXJZewhg3fWC+DlfqqQuWg8AwqjGTD2nAPVWg== - dependencies: - ini "^1.3.5" - kind-of "^6.0.2" - which "^1.3.1" - global@~4.4.0: version "4.4.0" resolved "https://registry.yarnpkg.com/global/-/global-4.4.0.tgz#3e7b105179006a323ed71aafca3e9c57a5cc6406" @@ -5308,20 +5288,6 @@ globalthis@^1.0.3: dependencies: define-properties "^1.1.3" -globby@^10.0.1: - version "10.0.2" - resolved "https://registry.yarnpkg.com/globby/-/globby-10.0.2.tgz#277593e745acaa4646c3ab411289ec47a0392543" - integrity sha512-7dUi7RvCoT/xast/o/dLN53oqND4yk0nsHkhRgn9w65C4PofCLOoJ39iSOg+qVDdWQPIEj+eszMHQ+aLVwwQSg== - dependencies: - "@types/glob" "^7.1.1" - array-union "^2.1.0" - dir-glob "^3.0.1" - fast-glob "^3.0.3" - glob "^7.1.3" - ignore "^5.1.1" - merge2 "^1.2.3" - slash "^3.0.0" - globby@^11.0.3, globby@^11.1.0: version "11.1.0" resolved "https://registry.yarnpkg.com/globby/-/globby-11.1.0.tgz#bd4be98bb042f83d796f7e3811991fbe82a0d34b" @@ -5375,6 +5341,28 @@ got@^11.8.5: p-cancelable "^2.0.0" responselike "^2.0.0" +got@^12.1.0: + version "12.6.1" + resolved "https://registry.yarnpkg.com/got/-/got-12.6.1.tgz#8869560d1383353204b5a9435f782df9c091f549" + integrity sha512-mThBblvlAF1d4O5oqyvN+ZxLAYwIJK7bpMxgYqPD9okW0C3qm5FFn7k811QrcuEBwaogR3ngOFoCfs6mRv7teQ== + dependencies: + "@sindresorhus/is" "^5.2.0" + "@szmarczak/http-timer" "^5.0.1" + cacheable-lookup "^7.0.0" + cacheable-request "^10.2.8" + decompress-response "^6.0.0" + form-data-encoder "^2.1.2" + get-stream "^6.0.1" + http2-wrapper "^2.1.10" + lowercase-keys "^3.0.0" + p-cancelable "^3.0.0" + responselike "^3.0.0" + +graceful-fs@4.2.10: + version "4.2.10" + resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.10.tgz#147d3a006da4ca3ce14728c7aefc287c367d7a6c" + integrity sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA== + graceful-fs@^4.1.11, graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.1.9, graceful-fs@^4.2.0: version "4.2.11" resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.11.tgz#4183e4e8bf08bb6e05bbb2f7d2e0c8f712ca40e3" @@ -5385,18 +5373,6 @@ graphemer@^1.4.0: resolved "https://registry.yarnpkg.com/graphemer/-/graphemer-1.4.0.tgz#fb2f1d55e0e3a1849aeffc90c4fa0dd53a0e66c6" integrity sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag== -handlebars@^4.0.1: - version "4.7.8" - resolved "https://registry.yarnpkg.com/handlebars/-/handlebars-4.7.8.tgz#41c42c18b1be2365439188c77c6afae71c0cd9e9" - integrity sha512-vafaFqs8MZkRrSX7sFVUdo3ap/eNiLnb4IakshzvP56X5Nr1iGKAIqdX6tMlm6HcNRIkr6AxO5jFEoJzzpT8aQ== - dependencies: - minimist "^1.2.5" - neo-async "^2.6.2" - source-map "^0.6.1" - wordwrap "^1.0.0" - optionalDependencies: - uglify-js "^3.1.4" - har-schema@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/har-schema/-/har-schema-2.0.0.tgz#a94c2224ebcac04782a0d9035521f24735b7ec92" @@ -5502,11 +5478,6 @@ has-bigints@^1.0.1, has-bigints@^1.0.2: resolved "https://registry.yarnpkg.com/has-bigints/-/has-bigints-1.0.2.tgz#0871bd3e3d51626f6ca0966668ba35d5602d6eaa" integrity sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ== -has-flag@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-1.0.0.tgz#9d9e793165ce017a00f00418c43f942a7b1d11fa" - integrity sha512-DyYHfIYwAJmjAjSSPKANxI8bFY9YtFrgkAfinBojQ8YJTOuOuav64tMUJv584SES4xl74PmuaevIyaLESHdTAA== - has-flag@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" @@ -5601,7 +5572,7 @@ hasown@^2.0.2: dependencies: function-bind "^1.1.2" -he@1.2.0, he@^1.2.0: +he@1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/he/-/he-1.2.0.tgz#84ae65fa7eafb165fddb61566ae14baf05664f0f" integrity sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw== @@ -5611,11 +5582,6 @@ heap@0.2.6: resolved "https://registry.yarnpkg.com/heap/-/heap-0.2.6.tgz#087e1f10b046932fc8594dd9e6d378afc9d1e5ac" integrity sha512-MzzWcnfB1e4EG2vHi3dXHoBupmuXNZzx6pY6HldVS55JKKBoq3xOyzfSaZRkJp37HIhEYC78knabHff3zc4dQQ== -"heap@>= 0.2.0": - version "0.2.7" - resolved "https://registry.yarnpkg.com/heap/-/heap-0.2.7.tgz#1e6adf711d3f27ce35a81fe3b7bd576c2260a8fc" - integrity sha512-2bsegYkkHO+h/9MGbn6KWcE45cHZgPANo5LXF7EvWdT0yT2EguSVO1nDgU5c8+ZOPwp2vMNa7YFsJhVcDR9Sdg== - hmac-drbg@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/hmac-drbg/-/hmac-drbg-1.0.1.tgz#d2745701025a6c775a6c545793ed502fc0c649a1" @@ -5650,6 +5616,11 @@ http-cache-semantics@^4.0.0: resolved "https://registry.yarnpkg.com/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz#abe02fcb2985460bf0323be664436ec3476a6d5a" integrity sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ== +http-cache-semantics@^4.1.1: + version "4.2.0" + resolved "https://registry.yarnpkg.com/http-cache-semantics/-/http-cache-semantics-4.2.0.tgz#205f4db64f8562b76a4ff9235aa5279839a09dd5" + integrity sha512-dTxcvPXqPvXBQpq5dUr6mEMJX4oIEFv6bwom3FDwKRDsuIjjJGANqhBuoAn9c1RQJIdAKav33ED65E2ys+87QQ== + http-errors@2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-2.0.0.tgz#b7774a1486ef73cf7667ac9ae0858c012c57b9d3" @@ -5683,6 +5654,14 @@ http2-wrapper@^1.0.0-beta.5.2: quick-lru "^5.1.1" resolve-alpn "^1.0.0" +http2-wrapper@^2.1.10: + version "2.2.1" + resolved "https://registry.yarnpkg.com/http2-wrapper/-/http2-wrapper-2.2.1.tgz#310968153dcdedb160d8b72114363ef5fce1f64a" + integrity sha512-V5nVw1PAOgfI3Lmeaj2Exmeg7fenjhRUgz1lPSezy1CuhPYbgQtbQj4jZfEAEMlaL+vupsvhjqCyjzob0yxsmQ== + dependencies: + quick-lru "^5.1.1" + resolve-alpn "^1.2.0" + https-proxy-agent@^5.0.0: version "5.0.1" resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz#c59ef224a04fe8b754f3db0063a25ea30d0005d6" @@ -5773,7 +5752,7 @@ inherits@2, inherits@2.0.4, inherits@^2.0.1, inherits@^2.0.3, inherits@^2.0.4, i resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== -ini@^1.3.4, ini@^1.3.5: +ini@^1.3.4, ini@~1.3.0: version "1.3.8" resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.8.tgz#a29da425b48806f34767a4efce397269af28432c" integrity sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew== @@ -5787,11 +5766,6 @@ internal-slot@^1.0.5: has "^1.0.3" side-channel "^1.0.4" -interpret@^1.0.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/interpret/-/interpret-1.4.0.tgz#665ab8bc4da27a774a40584e812e3e0fa45b1a1e" - integrity sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA== - invariant@^2.2.2: version "2.2.4" resolved "https://registry.yarnpkg.com/invariant/-/invariant-2.2.4.tgz#610f3c92c9359ce1db616e538008d23ff35158e6" @@ -6183,14 +6157,6 @@ js-tokens@^3.0.2: resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-3.0.2.tgz#9866df395102130e38f7f996bceb65443209c25b" integrity sha512-RjTcuD4xjtthQkaWH7dFlH85L+QaVtSoOyGdZ3g6HFhS9dFNDfLyqgm2NFe2X6cQpeFmt0452FJjFG5UameExg== -js-yaml@3.x, js-yaml@^3.14.1: - version "3.14.1" - resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.14.1.tgz#dae812fdb3825fa306609a8717383c50c36a0537" - integrity sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g== - dependencies: - argparse "^1.0.7" - esprima "^4.0.0" - js-yaml@4.1.0, js-yaml@^4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-4.1.0.tgz#c1fb65f8f5017901cdd2c951864ba18458a10602" @@ -6198,6 +6164,14 @@ js-yaml@4.1.0, js-yaml@^4.1.0: dependencies: argparse "^2.0.1" +js-yaml@^3.14.1: + version "3.14.1" + resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.14.1.tgz#dae812fdb3825fa306609a8717383c50c36a0537" + integrity sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g== + dependencies: + argparse "^1.0.7" + esprima "^4.0.0" + jsbn@~0.1.0: version "0.1.1" resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-0.1.1.tgz#a5e654c2e5a2deb5f201d96cefbca80c0ef2f513" @@ -6339,10 +6313,10 @@ jsonify@^0.0.1: resolved "https://registry.yarnpkg.com/jsonify/-/jsonify-0.0.1.tgz#2aa3111dae3d34a0f151c63f3a45d995d9420978" integrity sha512-2/Ki0GcmuqSrgFyelQq9M05y7PS0mEwuIzrf3f1fPqkVDVRvZrPZtVSMHxdgo8Aq0sxAOb/cr2aqqA3LeWHVPg== -jsonschema@^1.2.4: - version "1.4.1" - resolved "https://registry.yarnpkg.com/jsonschema/-/jsonschema-1.4.1.tgz#cc4c3f0077fb4542982973d8a083b6b34f482dab" - integrity sha512-S6cATIPVv1z0IlxdN+zUk5EPjkGCdnhN4wVSBlvoUO1tOLJootbo9CquNJmbIh4yikWHiUedhRYrNPn1arpEmQ== +jsonpointer@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/jsonpointer/-/jsonpointer-5.0.1.tgz#2110e0af0900fd37467b5907ecd13a7884a1b559" + integrity sha512-p/nXbhSEcu3pZRdkW1OfJhpsVtW1gd4Wa1fnQc9YLiTfAjn0312eMKimbdIQzuZl9aa9xUGaRlP9T/CJE/ditQ== jsprim@^1.2.2: version "1.4.2" @@ -6423,6 +6397,13 @@ klaw@^1.0.0: optionalDependencies: graceful-fs "^4.1.9" +latest-version@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/latest-version/-/latest-version-7.0.0.tgz#843201591ea81a4d404932eeb61240fe04e9e5da" + integrity sha512-KvNT4XqAMzdcL6ka6Tl3i2lYeFDgXNCuIX+xNx6ZMVR1dFq+idXd9FLKNMOIx0t9mJ9/HudyX4oZWXZQ0UJHeg== + dependencies: + package-json "^8.1.0" + lcid@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/lcid/-/lcid-1.0.0.tgz#308accafa0bc483a3867b4b6f2b9506251d1b835" @@ -6570,6 +6551,11 @@ levelup@^1.2.1: semver "~5.4.1" xtend "~4.0.0" +"leven@^3.1.0 < 4": + version "3.1.0" + resolved "https://registry.yarnpkg.com/leven/-/leven-3.1.0.tgz#77891de834064cccba82ae7842bb6b14a13ed7f2" + integrity sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A== + levn@^0.4.1: version "0.4.1" resolved "https://registry.yarnpkg.com/levn/-/levn-0.4.1.tgz#ae4562c007473b932a6200d403268dd2fffc6ade" @@ -6578,14 +6564,6 @@ levn@^0.4.1: prelude-ls "^1.2.1" type-check "~0.4.0" -levn@~0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/levn/-/levn-0.3.0.tgz#3b09924edf9f083c0490fdd4c0bc4421e04764ee" - integrity sha512-0OO4y2iOHix2W6ujICbKIaEQXvFQHue65vUG3pb5EUomzPI90z9hsA1VsO/dbIIpC53J8gxM9Q4Oho0jrCM/yA== - dependencies: - prelude-ls "~1.1.2" - type-check "~0.3.2" - lines-and-columns@^1.1.6: version "1.2.4" resolved "https://registry.yarnpkg.com/lines-and-columns/-/lines-and-columns-1.2.4.tgz#eca284f75d2965079309dc0ad9255abb2ebc1632" @@ -6639,7 +6617,7 @@ lodash@^4.17.11, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.21, lodash@^4.17 resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== -log-symbols@4.1.0, log-symbols@^4.1.0: +log-symbols@4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-4.1.0.tgz#3fbdbb95b4683ac9fc785111e792e558d4abd503" integrity sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg== @@ -6681,6 +6659,11 @@ lowercase-keys@^2.0.0: resolved "https://registry.yarnpkg.com/lowercase-keys/-/lowercase-keys-2.0.0.tgz#2603e78b7b4b0006cbca2fbcc8a3202558ac9479" integrity sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA== +lowercase-keys@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/lowercase-keys/-/lowercase-keys-3.0.0.tgz#c5e7d442e37ead247ae9db117a9d0a467c89d4f2" + integrity sha512-ozCC6gdQ+glXOQsveKD0YsDy8DSQFjDTz4zyzEHNV5+JP5D62LmfDZ6o1cycFx9ouG940M5dE8C8CTewdj2YWQ== + lru-cache@5.1.1, lru-cache@^5.1.1: version "5.1.1" resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-5.1.1.tgz#1da27e6710271947695daf6848e847f01d84b920" @@ -6794,7 +6777,7 @@ merge-descriptors@1.0.1: resolved "https://registry.yarnpkg.com/merge-descriptors/-/merge-descriptors-1.0.1.tgz#b00aaa556dd8b44568150ec9d1b953f3f90cbb61" integrity sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w== -merge2@^1.2.3, merge2@^1.3.0, merge2@^1.4.1: +merge2@^1.3.0, merge2@^1.4.1: version "1.4.1" resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae" integrity sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg== @@ -6898,6 +6881,11 @@ mimic-response@^3.1.0: resolved "https://registry.yarnpkg.com/mimic-response/-/mimic-response-3.1.0.tgz#2d1d59af9c1b129815accc2c46a022a5ce1fa3c9" integrity sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ== +mimic-response@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/mimic-response/-/mimic-response-4.0.0.tgz#35468b19e7c75d10f5165ea25e75a5ceea7cf70f" + integrity sha512-e5ISH9xMYU0DzrT+jl8q2ze9D6eWBto+I8CNpe+VI+K2J/F/k3PdkdTdz4wvGVH4NTpo+NRYTVIuMQEMMcsLqg== + min-document@^2.19.0: version "2.19.0" resolved "https://registry.yarnpkg.com/min-document/-/min-document-2.19.0.tgz#7bd282e3f5842ed295bb748cdd9f1ffa2c824685" @@ -6915,13 +6903,6 @@ minimalistic-crypto-utils@^1.0.1: resolved "https://registry.yarnpkg.com/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz#f6c00c1c0b082246e5c4d99dfb8c7c083b2b582a" integrity sha512-JIYlbt6g8i5jKfJ3xz7rF0LXmv2TkDxBLUkiBeZ7bAx4GnnNMr8xFpGnOxn6GhTEHx3SjRrZEoU+j04prX1ktg== -"minimatch@2 || 3", minimatch@^3.0.4, minimatch@^3.0.5, minimatch@^3.1.1, minimatch@^3.1.2: - version "3.1.2" - resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b" - integrity sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw== - dependencies: - brace-expansion "^1.1.7" - minimatch@5.0.1: version "5.0.1" resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-5.0.1.tgz#fb9022f7528125187c92bd9e9b6366be1cf3415b" @@ -6929,7 +6910,14 @@ minimatch@5.0.1: dependencies: brace-expansion "^2.0.1" -minimatch@^5.0.1, minimatch@^5.1.6: +minimatch@^3.0.4, minimatch@^3.0.5, minimatch@^3.1.1, minimatch@^3.1.2: + version "3.1.2" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b" + integrity sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw== + dependencies: + brace-expansion "^1.1.7" + +minimatch@^5.0.1: version "5.1.6" resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-5.1.6.tgz#1cfcb8cf5522ea69952cd2af95ae09477f122a96" integrity sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g== @@ -6943,7 +6931,7 @@ minimatch@^7.4.6: dependencies: brace-expansion "^2.0.1" -minimist@^1.2.0, minimist@^1.2.5, minimist@^1.2.6, minimist@~1.2.8: +minimist@^1.2.0, minimist@^1.2.6, minimist@~1.2.8: version "1.2.8" resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.8.tgz#c1a464e7693302e082a075cee0c057741ac4772c" integrity sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA== @@ -6983,7 +6971,7 @@ mkdirp@*: resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-3.0.1.tgz#e44e4c5607fb279c168241713cc6e0fea9adcb50" integrity sha512-+NsyUUAZDmo6YVHzL/stxSu3t9YS1iljliy3BSDrXJ/dkn1KYdmtZODGGjLcc9XLgVVpH4KshHB8XmZgMhaBXg== -mkdirp@0.5.x, mkdirp@^0.5.1, mkdirp@^0.5.5: +mkdirp@^0.5.1, mkdirp@^0.5.5: version "0.5.6" resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.6.tgz#7def03d2432dcae4ba1d611445c48396062255f6" integrity sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw== @@ -7029,32 +7017,6 @@ mocha@10.2.0, mocha@^10.0.0: yargs-parser "20.2.4" yargs-unparser "2.0.0" -mocha@^10.2.0: - version "10.8.2" - resolved "https://registry.yarnpkg.com/mocha/-/mocha-10.8.2.tgz#8d8342d016ed411b12a429eb731b825f961afb96" - integrity sha512-VZlYo/WE8t1tstuRmqgeyBgCbJc/lEdopaa+axcKzTBJ+UIdlAB9XnmvTCAH4pwR4ElNInaedhEBmZD8iCSVEg== - dependencies: - ansi-colors "^4.1.3" - browser-stdout "^1.3.1" - chokidar "^3.5.3" - debug "^4.3.5" - diff "^5.2.0" - escape-string-regexp "^4.0.0" - find-up "^5.0.0" - glob "^8.1.0" - he "^1.2.0" - js-yaml "^4.1.0" - log-symbols "^4.1.0" - minimatch "^5.1.6" - ms "^2.1.3" - serialize-javascript "^6.0.2" - strip-json-comments "^3.1.1" - supports-color "^8.1.1" - workerpool "^6.5.1" - yargs "^16.2.0" - yargs-parser "^20.2.9" - yargs-unparser "^2.0.0" - mock-fs@^4.1.0: version "4.14.0" resolved "https://registry.yarnpkg.com/mock-fs/-/mock-fs-4.14.0.tgz#ce5124d2c601421255985e6e94da80a7357b1b18" @@ -7082,7 +7044,7 @@ ms@2.1.2: resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== -ms@2.1.3, ms@^2.1.1, ms@^2.1.3: +ms@2.1.3, ms@^2.1.1: version "2.1.3" resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== @@ -7194,11 +7156,6 @@ negotiator@0.6.3: resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.3.tgz#58e323a72fedc0d6f9cd4d31fe49f51479590ccd" integrity sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg== -neo-async@^2.6.2: - version "2.6.2" - resolved "https://registry.yarnpkg.com/neo-async/-/neo-async-2.6.2.tgz#b4aafb93e3aeb2d8174ca53cf163ab7d7308305f" - integrity sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw== - next-tick@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/next-tick/-/next-tick-1.1.0.tgz#1836ee30ad56d67ef281b22bd199f709449b35eb" @@ -7214,13 +7171,6 @@ node-addon-api@^2.0.0: resolved "https://registry.yarnpkg.com/node-addon-api/-/node-addon-api-2.0.2.tgz#432cfa82962ce494b132e9d72a15b29f71ff5d32" integrity sha512-Ntyt4AIXyaLIuMHF6IOoTakB3K+RWxwtsHNRxllEoA6vPwP9o4866g6YWDLUdnucilZhmkxiHwHr11gAENw+QA== -node-emoji@^1.10.0: - version "1.11.0" - resolved "https://registry.yarnpkg.com/node-emoji/-/node-emoji-1.11.0.tgz#69a0150e6946e2f115e9d7ea4df7971e2628301c" - integrity sha512-wo2DpQkQp7Sjm2A0cq+sN7EHKO6Sl0ctXeBdFZrL9T9+UywORbufTcTZxom8YqpLQt/FqNMUkOpkZrJVYSKD3A== - dependencies: - lodash "^4.17.21" - node-fetch@^2.6.1, node-fetch@^2.6.7: version "2.7.0" resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.7.0.tgz#d0f0fa6e3e2dc1d27efcd8ad99d550bda94d187d" @@ -7241,13 +7191,6 @@ node-gyp-build@^4.2.0, node-gyp-build@^4.3.0: resolved "https://registry.yarnpkg.com/node-gyp-build/-/node-gyp-build-4.6.1.tgz#24b6d075e5e391b8d5539d98c7fc5c210cac8a3e" integrity sha512-24vnklJmyRS8ViBNI8KbtK/r/DmXQMRiOMXTNz2nrTnAYUwjmEEbnnpB/+kt+yWRv73bPsSPRFddrcIbAxSiMQ== -nopt@3.x: - version "3.0.6" - resolved "https://registry.yarnpkg.com/nopt/-/nopt-3.0.6.tgz#c6465dbf08abcd4db359317f79ac68a646b28ff9" - integrity sha512-4GUt3kSEYmk4ITxzB/b9vaIDfUVWN/Ml1Fwl11IlnIG2iaJ9O6WXZ9SrYM9NLI8OCBieN2Y8SWC2oJV0RQ7qYg== - dependencies: - abbrev "1" - normalize-package-data@^2.3.2: version "2.5.0" resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-2.5.0.tgz#e66db1838b200c1dfc233225d12cb36520e234a8" @@ -7273,6 +7216,11 @@ normalize-url@^6.0.1: resolved "https://registry.yarnpkg.com/normalize-url/-/normalize-url-6.1.0.tgz#40d0885b535deffe3f3147bec877d05fe4c5668a" integrity sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A== +normalize-url@^8.0.0: + version "8.1.0" + resolved "https://registry.yarnpkg.com/normalize-url/-/normalize-url-8.1.0.tgz#d33504f67970decf612946fd4880bc8c0983486d" + integrity sha512-X06Mfd/5aKsRHc0O0J5CUedwnPmnDtLF2+nq+KN9KSDlJHkPuh0JUviWjEWMe0SW/9TDdSLVPuk7L5gGTIA1/w== + number-is-nan@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/number-is-nan/-/number-is-nan-1.0.1.tgz#097b602b53422a522c1afb8790318336941a011d" @@ -7415,7 +7363,7 @@ on-finished@2.4.1: dependencies: ee-first "1.1.1" -once@1.x, once@^1.3.0, once@^1.3.1, once@^1.4.0: +once@^1.3.0, once@^1.3.1, once@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" integrity sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w== @@ -7430,18 +7378,6 @@ open@^7.4.2: is-docker "^2.0.0" is-wsl "^2.1.1" -optionator@^0.8.1: - version "0.8.3" - resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.8.3.tgz#84fa1d036fe9d3c7e21d99884b601167ec8fb495" - integrity sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA== - dependencies: - deep-is "~0.1.3" - fast-levenshtein "~2.0.6" - levn "~0.3.0" - prelude-ls "~1.1.2" - type-check "~0.3.2" - word-wrap "~1.2.3" - optionator@^0.9.3: version "0.9.3" resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.9.3.tgz#007397d44ed1872fdc6ed31360190f81814e2c64" @@ -7481,6 +7417,11 @@ p-cancelable@^2.0.0: resolved "https://registry.yarnpkg.com/p-cancelable/-/p-cancelable-2.1.1.tgz#aab7fbd416582fa32a3db49859c122487c5ed2cf" integrity sha512-BZOr3nRQHOntUjTrH8+Lh54smKHoHyur8We1V8DSMVrl5A2malOOwuJRnKRDjSnkoeBh4at6BwEnb5I7Jl31wg== +p-cancelable@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/p-cancelable/-/p-cancelable-3.0.0.tgz#63826694b54d61ca1c20ebcb6d3ecf5e14cd8050" + integrity sha512-mlVgR3PGuzlo0MmTdk4cXqXWlwQDLnONTAg6sm62XkMJEiRxN3GL3SffkYvqwonbkJBcrI7Uvv5Zh9yjvn2iUw== + p-limit@^3.0.2: version "3.1.0" resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-3.1.0.tgz#e1daccbe78d0d1388ca18c64fea38e3e57e3706b" @@ -7502,6 +7443,16 @@ p-map@^4.0.0: dependencies: aggregate-error "^3.0.0" +package-json@^8.1.0: + version "8.1.1" + resolved "https://registry.yarnpkg.com/package-json/-/package-json-8.1.1.tgz#3e9948e43df40d1e8e78a85485f1070bf8f03dc8" + integrity sha512-cbH9IAIJHNj9uXi196JVsRlt7cHKak6u/e6AkL/bkRelZ7rlL3X1YKxsZwa36xipOEKAsdtmaG6aAJoM1fx2zA== + dependencies: + got "^12.1.0" + registry-auth-token "^5.0.1" + registry-url "^6.0.0" + semver "^7.3.7" + parent-module@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/parent-module/-/parent-module-1.0.1.tgz#691d2709e78c79fae3a156622452d00762caaaa2" @@ -7692,11 +7643,6 @@ pify@^2.0.0, pify@^2.3.0: resolved "https://registry.yarnpkg.com/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c" integrity sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog== -pify@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/pify/-/pify-4.0.1.tgz#4b2cd25c50d598735c50292224fd8c6df41e3231" - integrity sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g== - pinkie-promise@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/pinkie-promise/-/pinkie-promise-2.0.1.tgz#2135d6dfa7a358c069ac9b178776288228450ffa" @@ -7750,11 +7696,6 @@ prelude-ls@^1.2.1: resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.2.1.tgz#debc6489d7a6e6b0e7611888cec880337d316396" integrity sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g== -prelude-ls@~1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.1.2.tgz#21932a549f5e52ffd9a827f570e04be62a97da54" - integrity sha512-ESF23V4SKG6lVSGZgYNpbsiaAkdab6ZgOxe52p7+Kid3W3u3bxR4Vfd/o21dmN7jSt0IwgZ4v5MUd26FEtXE9w== - prepend-http@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/prepend-http/-/prepend-http-2.0.0.tgz#e92434bfa5ea8c19f41cdfd401d741a3c819d897" @@ -7788,6 +7729,11 @@ promise-to-callback@^1.0.0: is-fn "^1.0.0" set-immediate-shim "^1.0.1" +proto-list@~1.2.1: + version "1.2.4" + resolved "https://registry.yarnpkg.com/proto-list/-/proto-list-1.2.4.tgz#212d5bfe1318306a420f6402b8e26ff39647a849" + integrity sha512-vtK/94akxsTMhe0/cbfpR+syPuszcuwhqVjJq26CuNDgFGj682oRBXOP5MJpv2r7JtE8MsiepGIqvvOTBwn2vA== + proxy-addr@~2.0.7: version "2.0.7" resolved "https://registry.yarnpkg.com/proxy-addr/-/proxy-addr-2.0.7.tgz#f19fe69ceab311eeb94b42e70e8c2070f9ba1025" @@ -7972,6 +7918,16 @@ raw-body@2.5.2, raw-body@^2.4.1: iconv-lite "0.4.24" unpipe "1.0.0" +rc@1.2.8: + version "1.2.8" + resolved "https://registry.yarnpkg.com/rc/-/rc-1.2.8.tgz#cd924bf5200a075b83c188cd6b9e211b7fc0d3ed" + integrity sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw== + dependencies: + deep-extend "^0.6.0" + ini "~1.3.0" + minimist "^1.2.0" + strip-json-comments "~2.0.1" + read-pkg-up@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-1.0.1.tgz#9d63c13276c065918d57f002a57f40a1b643fb02" @@ -8043,20 +7999,6 @@ readdirp@^4.0.1: resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-4.0.2.tgz#388fccb8b75665da3abffe2d8f8ed59fe74c230a" integrity sha512-yDMz9g+VaZkqBYS/ozoBJwaBhTbZo3UNYQHNRw1D3UFQB8oHB4uS/tAODO+ZLjGWmUbKnIlOWO+aaIiAxrUWHA== -rechoir@^0.6.2: - version "0.6.2" - resolved "https://registry.yarnpkg.com/rechoir/-/rechoir-0.6.2.tgz#85204b54dba82d5742e28c96756ef43af50e3384" - integrity sha512-HFM8rkZ+i3zrV+4LQjwQ0W+ez98pApMGM3HUrN04j3CqzPOzl9nmP15Y8YXNm8QHGv/eacOVEjqhmWpkRV0NAw== - dependencies: - resolve "^1.1.6" - -recursive-readdir@^2.2.2: - version "2.2.3" - resolved "https://registry.yarnpkg.com/recursive-readdir/-/recursive-readdir-2.2.3.tgz#e726f328c0d69153bcabd5c322d3195252379372" - integrity sha512-8HrF5ZsXk5FAH9dgsx3BlUer73nIhuj+9OrQwEbLTPOBzGkL1lsFCR01am+v+0m2Cmbs1nP12hLDl5FA7EszKA== - dependencies: - minimatch "^3.0.5" - reduce-flatten@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/reduce-flatten/-/reduce-flatten-2.0.0.tgz#734fd84e65f375d7ca4465c69798c25c9d10ae27" @@ -8112,6 +8054,20 @@ regexpu-core@^2.0.0: regjsgen "^0.2.0" regjsparser "^0.1.4" +registry-auth-token@^5.0.1: + version "5.1.0" + resolved "https://registry.yarnpkg.com/registry-auth-token/-/registry-auth-token-5.1.0.tgz#3c659047ecd4caebd25bc1570a3aa979ae490eca" + integrity sha512-GdekYuwLXLxMuFTwAPg5UKGLW/UXzQrZvH/Zj791BQif5T05T0RsaLfHc9q3ZOKi7n+BoprPD9mJ0O0k4xzUlw== + dependencies: + "@pnpm/npm-conf" "^2.1.0" + +registry-url@^6.0.0: + version "6.0.1" + resolved "https://registry.yarnpkg.com/registry-url/-/registry-url-6.0.1.tgz#056d9343680f2f64400032b1e199faa692286c58" + integrity sha512-+crtS5QjFRqFCoQmvGduwYWEBng99ZvmFvF+cUJkGYF1L1BfU8C6Zp9T7f5vPAwyLkUExpvK+ANVZmGU49qi4Q== + dependencies: + rc "1.2.8" + regjsgen@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/regjsgen/-/regjsgen-0.2.0.tgz#6c016adeac554f75823fe37ac05b92d5a4edb1f7" @@ -8192,7 +8148,7 @@ require-package-name@^2.0.1: resolved "https://registry.yarnpkg.com/require-package-name/-/require-package-name-2.0.1.tgz#c11e97276b65b8e2923f75dabf5fb2ef0c3841b9" integrity sha512-uuoJ1hU/k6M0779t3VMVIYpb2VMJk05cehCaABFhXaibcbvfgR8wKiozLjVFSzJPmQMRqIcO0HMyTFqfV09V6Q== -resolve-alpn@^1.0.0: +resolve-alpn@^1.0.0, resolve-alpn@^1.2.0: version "1.2.1" resolved "https://registry.yarnpkg.com/resolve-alpn/-/resolve-alpn-1.2.1.tgz#b7adbdac3546aaaec20b45e7d8265927072726f9" integrity sha512-0a1F4l73/ZFZOakJnQ3FvkJ2+gSTQWz/r2KE5OdDY0TxPm5h4GkqkWWfM47T7HsbnOtcJVEF4epCVy6u7Q3K+g== @@ -8220,11 +8176,6 @@ resolve-url@^0.2.1: resolved "https://registry.yarnpkg.com/resolve-url/-/resolve-url-0.2.1.tgz#2c637fe77c893afd2a663fe21aa9080068e2052a" integrity sha512-ZuF55hVUQaaczgOIwqWzkEcEidmlD/xl44x1UZnhOXcYuFN2S6+rcxpG+C1N3So0wvNI3DmJICUFfu2SxhBmvg== -resolve@1.1.x: - version "1.1.7" - resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.1.7.tgz#203114d82ad2c5ed9e8e0411b3932875e889e97b" - integrity sha512-9znBF0vBcaSN3W2j7wKvdERPwqTxSpCq+if5C0WoTCyV9n24rua28jeuQ2pL/HOf+yUe/Mef+H/5p60K0Id3bg== - resolve@1.17.0: version "1.17.0" resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.17.0.tgz#b25941b54968231cc2d1bb76a79cb7f2c0bf8444" @@ -8232,7 +8183,7 @@ resolve@1.17.0: dependencies: path-parse "^1.0.6" -resolve@^1.1.6, resolve@^1.10.0, resolve@^1.10.1, resolve@^1.22.4, resolve@^1.8.1, resolve@~1.22.6: +resolve@^1.10.0, resolve@^1.10.1, resolve@^1.22.4, resolve@^1.8.1, resolve@~1.22.6: version "1.22.8" resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.8.tgz#b6c87a9f2aa06dfab52e3d70ac8cde321fa5a48d" integrity sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw== @@ -8264,6 +8215,13 @@ responselike@^2.0.0: dependencies: lowercase-keys "^2.0.0" +responselike@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/responselike/-/responselike-3.0.0.tgz#20decb6c298aff0dbee1c355ca95461d42823626" + integrity sha512-40yHxbNcl2+rzXvZuVkrYohathsSJlMTXKryG5y8uciHv1+xDLHQpgjG64JUO9nrEq2jGLH6IZ8BcZyw3wrweg== + dependencies: + lowercase-keys "^3.0.0" + ret@~0.1.10: version "0.1.15" resolved "https://registry.yarnpkg.com/ret/-/ret-0.1.15.tgz#b8a4825d5bdb1fc3f6f53c2bc33f81388681c7bc" @@ -8363,26 +8321,6 @@ safe-regex@^1.1.0: resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== -sc-istanbul@^0.4.5: - version "0.4.6" - resolved "https://registry.yarnpkg.com/sc-istanbul/-/sc-istanbul-0.4.6.tgz#cf6784355ff2076f92d70d59047d71c13703e839" - integrity sha512-qJFF/8tW/zJsbyfh/iT/ZM5QNHE3CXxtLJbZsL+CzdJLBsPD7SedJZoUA4d8iAcN2IoMp/Dx80shOOd2x96X/g== - dependencies: - abbrev "1.0.x" - async "1.x" - escodegen "1.8.x" - esprima "2.7.x" - glob "^5.0.15" - handlebars "^4.0.1" - js-yaml "3.x" - mkdirp "0.5.x" - nopt "3.x" - once "1.x" - resolve "1.1.x" - supports-color "^3.1.0" - which "^1.1.1" - wordwrap "^1.0.0" - scrypt-js@3.0.1, scrypt-js@^3.0.0, scrypt-js@^3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/scrypt-js/-/scrypt-js-3.0.1.tgz#d314a57c2aef69d1ad98a138a21fe9eafa9ee312" @@ -8429,7 +8367,7 @@ semver@^6.1.0, semver@^6.3.0, semver@^6.3.1: resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.1.tgz#556d2ef8689146e46dcea4bfdd095f3434dffcb4" integrity sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA== -semver@^7.3.4, semver@^7.3.5, semver@^7.3.7, semver@^7.5.2: +semver@^7.3.5, semver@^7.3.7, semver@^7.5.2: version "7.5.4" resolved "https://registry.yarnpkg.com/semver/-/semver-7.5.4.tgz#483986ec4ed38e1c6c48c34894a9182dbff68a6e" integrity sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA== @@ -8472,13 +8410,6 @@ serialize-javascript@6.0.0: dependencies: randombytes "^2.1.0" -serialize-javascript@^6.0.2: - version "6.0.2" - resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-6.0.2.tgz#defa1e055c83bf6d59ea805d8da862254eb6a6c2" - integrity sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g== - dependencies: - randombytes "^2.1.0" - serve-static@1.15.0: version "1.15.0" resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-1.15.0.tgz#faaef08cffe0a1a62f60cad0c4e513cff0ac9540" @@ -8571,15 +8502,6 @@ shebang-regex@^3.0.0: resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172" integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A== -shelljs@^0.8.3: - version "0.8.5" - resolved "https://registry.yarnpkg.com/shelljs/-/shelljs-0.8.5.tgz#de055408d8361bed66c669d2f000538ced8ee20c" - integrity sha512-TiwcRcrkhHvbrZbnRcFYMLl30Dfov3HKqzp5tO5b4pt6G/SezKcYhmDg15zXVBswHmctSAQKznqNW2LO5tTDow== - dependencies: - glob "^7.0.0" - interpret "^1.0.0" - rechoir "^0.6.2" - side-channel@^1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/side-channel/-/side-channel-1.0.4.tgz#efce5c8fdc104ee751b25c58d4290011fa5ea2cf" @@ -8695,15 +8617,17 @@ solc@^0.6.3: semver "^5.5.0" tmp "0.0.33" -solhint@^3.3.7: - version "3.6.2" - resolved "https://registry.yarnpkg.com/solhint/-/solhint-3.6.2.tgz#2b2acbec8fdc37b2c68206a71ba89c7f519943fe" - integrity sha512-85EeLbmkcPwD+3JR7aEMKsVC9YrRSxd4qkXuMzrlf7+z2Eqdfm1wHWq1ffTuo5aDhoZxp2I9yF3QkxZOxOL7aQ== +solhint@^6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/solhint/-/solhint-6.0.1.tgz#aecf21f114ad060674f6e761e8971c35fd140944" + integrity sha512-Lew5nhmkXqHPybzBzkMzvvWkpOJSSLTkfTZwRriWvfR2naS4YW2PsjVGaoX9tZFmHh7SuS+e2GEGo5FPYYmJ8g== dependencies: - "@solidity-parser/parser" "^0.16.0" + "@solidity-parser/parser" "^0.20.2" ajv "^6.12.6" - antlr4 "^4.11.0" + ajv-errors "^1.0.1" + antlr4 "^4.13.1-patch-1" ast-parents "^0.0.1" + better-ajv-errors "^2.0.2" chalk "^4.1.2" commander "^10.0.0" cosmiconfig "^8.0.0" @@ -8711,40 +8635,15 @@ solhint@^3.3.7: glob "^8.0.3" ignore "^5.2.4" js-yaml "^4.1.0" + latest-version "^7.0.0" lodash "^4.17.21" pluralize "^8.0.0" semver "^7.5.2" - strip-ansi "^6.0.1" table "^6.8.1" text-table "^0.2.0" optionalDependencies: prettier "^2.8.3" -solidity-coverage@^0.8.14: - version "0.8.14" - resolved "https://registry.yarnpkg.com/solidity-coverage/-/solidity-coverage-0.8.14.tgz#db9bfcc10e3bc369fc074b35b267d665bcc6ae2e" - integrity sha512-ItAAObe5GaEOp20kXC2BZRnph+9P7Rtoqg2mQc2SXGEHgSDF2wWd1Wxz3ntzQWXkbCtIIGdJT918HG00cObwbA== - dependencies: - "@ethersproject/abi" "^5.0.9" - "@solidity-parser/parser" "^0.19.0" - chalk "^2.4.2" - death "^1.1.0" - difflib "^0.2.4" - fs-extra "^8.1.0" - ghost-testrpc "^0.0.2" - global-modules "^2.0.0" - globby "^10.0.1" - jsonschema "^1.2.4" - lodash "^4.17.21" - mocha "^10.2.0" - node-emoji "^1.10.0" - pify "^4.0.1" - recursive-readdir "^2.2.2" - sc-istanbul "^0.4.5" - semver "^7.3.4" - shelljs "^0.8.3" - web3-utils "^1.3.6" - source-map-js@^1.2.0, source-map-js@^1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-1.2.1.tgz#1ce5650fddd87abc099eda37dcff024c2667ae46" @@ -8776,7 +8675,7 @@ source-map-support@^0.4.15: dependencies: source-map "^0.5.6" -source-map-support@^0.5.13, source-map-support@^0.5.6: +source-map-support@^0.5.13: version "0.5.21" resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.21.tgz#04fe7c7f9e1ed2d662233c28cb2b35b9f63f6e4f" integrity sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w== @@ -8794,18 +8693,11 @@ source-map@^0.5.6, source-map@^0.5.7: resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc" integrity sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ== -source-map@^0.6.0, source-map@^0.6.1: +source-map@^0.6.0: version "0.6.1" resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== -source-map@~0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.2.0.tgz#dab73fbcfc2ba819b4de03bd6f6eaa48164b3f9d" - integrity sha512-CBdZ2oa/BHhS4xj5DlhjWNHcan57/5YuvfdLf17iVmIpd9KRm+DFLmC6nBNj+6Ua7Kt3TmOjDpQT1aTYOQtoUA== - dependencies: - amdefine ">=0.0.4" - spdx-correct@^3.0.0: version "3.2.0" resolved "https://registry.yarnpkg.com/spdx-correct/-/spdx-correct-3.2.0.tgz#4f5ab0668f0059e34f9c00dce331784a12de4e9c" @@ -8999,7 +8891,12 @@ strip-json-comments@3.1.1, strip-json-comments@^3.1.1: resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006" integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig== -supports-color@8.1.1, supports-color@^8.1.1: +strip-json-comments@~2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a" + integrity sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ== + +supports-color@8.1.1: version "8.1.1" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-8.1.1.tgz#cd6fc17e28500cff56c1b86c0a7fd4a54a73005c" integrity sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q== @@ -9011,13 +8908,6 @@ supports-color@^2.0.0: resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-2.0.0.tgz#535d045ce6b6363fa40117084629995e9df324c7" integrity sha512-KKNVtd6pCYgPIKU4cp2733HWYCpplQhddZLBUryaAHou723x+FRzQ5Df824Fj+IyyuiQTRoub4SnIFfIcrp70g== -supports-color@^3.1.0: - version "3.2.3" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-3.2.3.tgz#65ac0504b3954171d8a64946b2ae3cbb8a5f54f6" - integrity sha512-Jds2VIYDrlp5ui7t8abHN2bjAu4LV/q4N2KivFPpGH0lrka0BMq/33AmECUXlKPcHigkNaqfXRENFju+rlcy+A== - dependencies: - has-flag "^1.0.0" - supports-color@^5.3.0: version "5.5.0" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f" @@ -9268,28 +9158,10 @@ ts-generator@^0.1.1: resolve "^1.8.1" ts-essentials "^1.0.0" -ts-mocha@^10.0.0: - version "10.0.0" - resolved "https://registry.yarnpkg.com/ts-mocha/-/ts-mocha-10.0.0.tgz#41a8d099ac90dbbc64b06976c5025ffaebc53cb9" - integrity sha512-VRfgDO+iiuJFlNB18tzOfypJ21xn2xbuZyDvJvqpTbWgkAgD17ONGr8t+Tl8rcBtOBdjXp5e/Rk+d39f7XBHRw== - dependencies: - ts-node "7.0.1" - optionalDependencies: - tsconfig-paths "^3.5.0" - -ts-node@7.0.1: - version "7.0.1" - resolved "https://registry.yarnpkg.com/ts-node/-/ts-node-7.0.1.tgz#9562dc2d1e6d248d24bc55f773e3f614337d9baf" - integrity sha512-BVwVbPJRspzNh2yfslyT1PSbl5uIk03EZlb493RKHN4qej/D06n1cEhjlOJG69oFsE7OT8XjpTUcYf6pKTLMhw== - dependencies: - arrify "^1.0.0" - buffer-from "^1.1.0" - diff "^3.1.0" - make-error "^1.1.1" - minimist "^1.2.0" - mkdirp "^0.5.1" - source-map-support "^0.5.6" - yn "^2.0.0" +ts-mocha@^11.1.0: + version "11.1.0" + resolved "https://registry.yarnpkg.com/ts-mocha/-/ts-mocha-11.1.0.tgz#d8336ec0146bd6f36cca2555f4cfc7df85bd1586" + integrity sha512-yT7FfzNRCu8ZKkYvAOiH01xNma/vLq6Vit7yINKYFNVP8e5UyrYXSOMIipERTpzVKJQ4Qcos5bQo1tNERNZevQ== ts-node@^10.1.0: version "10.9.1" @@ -9310,7 +9182,7 @@ ts-node@^10.1.0: v8-compile-cache-lib "^3.0.1" yn "3.1.1" -tsconfig-paths@^3.14.2, tsconfig-paths@^3.5.0: +tsconfig-paths@^3.14.2: version "3.14.2" resolved "https://registry.yarnpkg.com/tsconfig-paths/-/tsconfig-paths-3.14.2.tgz#6e32f1f79412decd261f92d633a9dc1cfa99f088" integrity sha512-o/9iXgCYc5L/JxCHPe3Hvh8Q/2xm5Z+p18PESBU6Ff33695QnCHBEjcytY2q19ua7Mbl/DavtBOLq+oG0RCL+g== @@ -9366,17 +9238,10 @@ type-check@^0.4.0, type-check@~0.4.0: dependencies: prelude-ls "^1.2.1" -type-check@~0.3.2: - version "0.3.2" - resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.3.2.tgz#5884cab512cf1d355e3fb784f30804b2b520db72" - integrity sha512-ZCmOJdvOWDBYJlzAoFkC+Q0+bUyEOS1ltgp1MGU03fqHG+dbi9tBFU2Rd9QKiDZFAYrhPh2JUf7rZRIuHRKtOg== - dependencies: - prelude-ls "~1.1.2" - -type-detect@^4.0.0, type-detect@^4.0.8: - version "4.0.8" - resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-4.0.8.tgz#7646fb5f18871cfbb7749e69bd39a6388eb7450c" - integrity sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g== +type-detect@^4.0.0, type-detect@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-4.1.0.tgz#deb2453e8f08dcae7ae98c626b13dddb0155906c" + integrity sha512-Acylog8/luQ8L7il+geoSxhEkazvkslg7PSNKOX59mbB9cOveP5aq9h74Y7YU8yDpJwetzQQrfIwtf4Wp4LKcw== type-fest@^0.20.2: version "0.20.2" @@ -9528,11 +9393,6 @@ typical@^5.2.0: resolved "https://registry.yarnpkg.com/typical/-/typical-5.2.0.tgz#4daaac4f2b5315460804f0acf6cb69c52bb93066" integrity sha512-dvdQgNDNJo+8B2uBQoqdb11eUCE1JQXhvjC/CZtgvZseVd5TYMXnq0+vuUemXbd/Se29cTaUuPX3YIc2xgbvIg== -uglify-js@^3.1.4: - version "3.17.4" - resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.17.4.tgz#61678cf5fa3f5b7eb789bb345df29afb8257c22c" - integrity sha512-T9q82TJI9e/C1TAxYvfb16xO120tMVFZrGA3f9/P4424DNu6ypK103y0GPFVa17yotwSyZW5iYXgjYHkGrJW/g== - ultron@~1.1.0: version "1.1.1" resolved "https://registry.yarnpkg.com/ultron/-/ultron-1.1.1.tgz#9fe1536a10a664a65266a1e3ccf85fd36302bc9c" @@ -9974,7 +9834,7 @@ web3-utils@1.2.11: underscore "1.9.1" utf8 "3.0.0" -web3-utils@^1.0.0-beta.31, web3-utils@^1.3.6: +web3-utils@^1.0.0-beta.31: version "1.10.3" resolved "https://registry.yarnpkg.com/web3-utils/-/web3-utils-1.10.3.tgz#f1db99c82549c7d9f8348f04ffe4e0188b449714" integrity sha512-OqcUrEE16fDBbGoQtZXWdavsPzbGIDc5v3VrRTZ0XrIpefC/viZ1ZU9bGEemazyS0catk/3rkOOxpzTfY+XsyQ== @@ -10070,7 +9930,7 @@ which-typed-array@^1.1.11: gopd "^1.0.1" has-tostringtag "^1.0.0" -which@^1.1.1, which@^1.2.14, which@^1.2.9, which@^1.3.1: +which@^1.2.14, which@^1.2.9: version "1.3.1" resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a" integrity sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ== @@ -10096,16 +9956,6 @@ window-size@^0.2.0: resolved "https://registry.yarnpkg.com/window-size/-/window-size-0.2.0.tgz#b4315bb4214a3d7058ebeee892e13fa24d98b075" integrity sha512-UD7d8HFA2+PZsbKyaOCEy8gMh1oDtHgJh1LfgjQ4zVXmYjAT/kvz3PueITKuqDiIXQe7yzpPnxX3lNc+AhQMyw== -word-wrap@~1.2.3: - version "1.2.5" - resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.2.5.tgz#d2c45c6dd4fbce621a66f136cbe328afd0410b34" - integrity sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA== - -wordwrap@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-1.0.0.tgz#27584810891456a4171c8d0226441ade90cbcaeb" - integrity sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q== - wordwrapjs@^4.0.0: version "4.0.1" resolved "https://registry.yarnpkg.com/wordwrapjs/-/wordwrapjs-4.0.1.tgz#d9790bccfb110a0fc7836b5ebce0937b37a8b98f" @@ -10119,11 +9969,6 @@ workerpool@6.2.1: resolved "https://registry.yarnpkg.com/workerpool/-/workerpool-6.2.1.tgz#46fc150c17d826b86a008e5a4508656777e9c343" integrity sha512-ILEIE97kDZvF9Wb9f6h5aXK4swSlKGUcOEGiIYb2OOu/IrDU9iwj0fD//SsA6E5ibwJxpEvhullJY4Sl4GcpAw== -workerpool@^6.5.1: - version "6.5.1" - resolved "https://registry.yarnpkg.com/workerpool/-/workerpool-6.5.1.tgz#060f73b39d0caf97c6db64da004cd01b4c099544" - integrity sha512-Fs4dNYcsdpYSAfVxhnl1L5zTksjvOJxtC5hzMNl+1t9B8hTJTdKDyZ5ju7ztgPy+ft9tBFXoOlDNiOT9WUXZlA== - wrap-ansi@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-2.1.0.tgz#d8fc3d284dd05794fe84973caecdd1cf824fdd85" @@ -10264,12 +10109,12 @@ yargs-parser@^2.4.1: camelcase "^3.0.0" lodash.assign "^4.0.6" -yargs-parser@^20.2.2, yargs-parser@^20.2.9: +yargs-parser@^20.2.2: version "20.2.9" resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-20.2.9.tgz#2eb7dc3b0289718fc295f362753845c41a0c94ee" integrity sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w== -yargs-unparser@2.0.0, yargs-unparser@^2.0.0: +yargs-unparser@2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/yargs-unparser/-/yargs-unparser-2.0.0.tgz#f131f9226911ae5d9ad38c432fe809366c2325eb" integrity sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA== @@ -10317,11 +10162,6 @@ yn@3.1.1: resolved "https://registry.yarnpkg.com/yn/-/yn-3.1.1.tgz#1e87401a09d767c1d5eab26a6e4c185182d2eb50" integrity sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q== -yn@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/yn/-/yn-2.0.0.tgz#e5adabc8acf408f6385fc76495684c88e6af689a" - integrity sha512-uTv8J/wiWTgUTg+9vLTi//leUl5vDQS6uii/emeTb2ssY7vl6QWf2fFbIIGjnhjvbdKlU0ed7QPgY1htTC86jQ== - yocto-queue@^0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b" diff --git a/dependencies/forge-std-1.11.0/.github/CODEOWNERS b/dependencies/forge-std-1.11.0/.github/CODEOWNERS deleted file mode 100644 index beae7aa..0000000 --- a/dependencies/forge-std-1.11.0/.github/CODEOWNERS +++ /dev/null @@ -1 +0,0 @@ -* @danipopes @klkvr @mattsse @grandizzy @yash-atreya @zerosnacks @onbjerg @0xrusowsky \ No newline at end of file diff --git a/dependencies/forge-std-1.11.0/.github/dependabot.yml b/dependencies/forge-std-1.11.0/.github/dependabot.yml deleted file mode 100644 index 5ace460..0000000 --- a/dependencies/forge-std-1.11.0/.github/dependabot.yml +++ /dev/null @@ -1,6 +0,0 @@ -version: 2 -updates: - - package-ecosystem: "github-actions" - directory: "/" - schedule: - interval: "weekly" diff --git a/dependencies/forge-std-1.11.0/.github/workflows/ci.yml b/dependencies/forge-std-1.11.0/.github/workflows/ci.yml deleted file mode 100644 index cede018..0000000 --- a/dependencies/forge-std-1.11.0/.github/workflows/ci.yml +++ /dev/null @@ -1,142 +0,0 @@ -name: CI - -permissions: {} - -on: - workflow_dispatch: - pull_request: - push: - branches: - - master - -jobs: - build: - name: build +${{ matrix.toolchain }} ${{ matrix.flags }} - runs-on: ubuntu-latest - timeout-minutes: 10 - permissions: - contents: read - strategy: - fail-fast: false - matrix: - toolchain: [stable, nightly] - flags: - - "" - - --via-ir - - --use solc:0.8.17 --via-ir - - --use solc:0.8.17 - - --use solc:0.8.0 - - --use solc:0.7.6 - - --use solc:0.7.0 - - --use solc:0.6.2 - - --use solc:0.6.12 - steps: - - uses: actions/checkout@v5 - with: - persist-credentials: false - - uses: foundry-rs/foundry-toolchain@v1 - - run: forge --version - - run: | - case "${{ matrix.flags }}" in - *"solc:0.8.0"* | *"solc:0.7"* | *"solc:0.6"*) - forge build --skip test --skip Config --skip StdConfig --skip LibVariable --deny-warnings ${{ matrix.flags }} - ;; - *) - forge build --skip test --deny-warnings ${{ matrix.flags }} - ;; - esac - # via-ir compilation time checks. - - if: contains(matrix.flags, '--via-ir') - run: forge build --skip test --deny-warnings ${{ matrix.flags }} --contracts 'test/compilation/*' - - test: - runs-on: ubuntu-latest - timeout-minutes: 10 - permissions: - contents: read - strategy: - fail-fast: false - matrix: - toolchain: [stable, nightly] - steps: - - uses: actions/checkout@v5 - with: - persist-credentials: false - - uses: foundry-rs/foundry-toolchain@v1 - with: - version: ${{ matrix.toolchain }} - - run: forge --version - - run: | - if [ "${{ matrix.toolchain }}" = "stable" ]; then - forge test -vvv --no-match-path "test/Config.t.sol" - else - forge test -vvv - fi - - fmt: - runs-on: ubuntu-latest - timeout-minutes: 10 - permissions: - contents: read - steps: - - uses: actions/checkout@v5 - with: - persist-credentials: false - - uses: foundry-rs/foundry-toolchain@v1 - - run: forge --version - - run: forge fmt --check - - typos: - runs-on: ubuntu-latest - timeout-minutes: 10 - permissions: - contents: read - steps: - - uses: actions/checkout@v5 - with: - persist-credentials: false - - uses: crate-ci/typos@7436548694def3314aacd93ed06c721b1f91ea04 # v1 - - codeql: - name: Analyze (${{ matrix.language }}) - runs-on: ubuntu-latest - permissions: - security-events: write - actions: read - contents: read - strategy: - fail-fast: false - matrix: - include: - - language: actions - build-mode: none - steps: - - name: Checkout repository - uses: actions/checkout@v5 - with: - persist-credentials: false - - name: Initialize CodeQL - uses: github/codeql-action/init@v3 - with: - languages: ${{ matrix.language }} - build-mode: ${{ matrix.build-mode }} - - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@v3 - with: - category: "/language:${{matrix.language}}" - - ci-success: - runs-on: ubuntu-latest - if: always() - needs: - - build - - test - - fmt - - typos - - codeql - timeout-minutes: 10 - steps: - - name: Decide whether the needed jobs succeeded or failed - uses: re-actors/alls-green@05ac9388f0aebcb5727afa17fcccfecd6f8ec5fe # release/v1 - with: - jobs: ${{ toJSON(needs) }} diff --git a/dependencies/forge-std-1.11.0/src/StdAssertions.sol b/dependencies/forge-std-1.11.0/src/StdAssertions.sol deleted file mode 100644 index 4248170..0000000 --- a/dependencies/forge-std-1.11.0/src/StdAssertions.sol +++ /dev/null @@ -1,764 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity >=0.6.2 <0.9.0; -pragma experimental ABIEncoderV2; - -import {Vm} from "./Vm.sol"; - -abstract contract StdAssertions { - Vm private constant vm = Vm(address(uint160(uint256(keccak256("hevm cheat code"))))); - - event log(string); - event logs(bytes); - - event log_address(address); - event log_bytes32(bytes32); - event log_int(int256); - event log_uint(uint256); - event log_bytes(bytes); - event log_string(string); - - event log_named_address(string key, address val); - event log_named_bytes32(string key, bytes32 val); - event log_named_decimal_int(string key, int256 val, uint256 decimals); - event log_named_decimal_uint(string key, uint256 val, uint256 decimals); - event log_named_int(string key, int256 val); - event log_named_uint(string key, uint256 val); - event log_named_bytes(string key, bytes val); - event log_named_string(string key, string val); - - event log_array(uint256[] val); - event log_array(int256[] val); - event log_array(address[] val); - event log_named_array(string key, uint256[] val); - event log_named_array(string key, int256[] val); - event log_named_array(string key, address[] val); - - bytes32 private constant FAILED_SLOT = bytes32("failed"); - - bool private _failed; - - function failed() public view returns (bool) { - if (_failed) { - return true; - } else { - return vm.load(address(vm), FAILED_SLOT) != bytes32(0); - } - } - - function fail() internal virtual { - vm.store(address(vm), FAILED_SLOT, bytes32(uint256(1))); - _failed = true; - } - - function fail(string memory message) internal virtual { - fail(); - vm.assertTrue(false, message); - } - - function assertTrue(bool data) internal pure virtual { - if (!data) { - vm.assertTrue(data); - } - } - - function assertTrue(bool data, string memory err) internal pure virtual { - if (!data) { - vm.assertTrue(data, err); - } - } - - function assertFalse(bool data) internal pure virtual { - if (data) { - vm.assertFalse(data); - } - } - - function assertFalse(bool data, string memory err) internal pure virtual { - if (data) { - vm.assertFalse(data, err); - } - } - - function assertEq(bool left, bool right) internal pure virtual { - if (left != right) { - vm.assertEq(left, right); - } - } - - function assertEq(bool left, bool right, string memory err) internal pure virtual { - if (left != right) { - vm.assertEq(left, right, err); - } - } - - function assertEq(uint256 left, uint256 right) internal pure virtual { - if (left != right) { - vm.assertEq(left, right); - } - } - - function assertEq(uint256 left, uint256 right, string memory err) internal pure virtual { - if (left != right) { - vm.assertEq(left, right, err); - } - } - - function assertEqDecimal(uint256 left, uint256 right, uint256 decimals) internal pure virtual { - vm.assertEqDecimal(left, right, decimals); - } - - function assertEqDecimal(uint256 left, uint256 right, uint256 decimals, string memory err) internal pure virtual { - vm.assertEqDecimal(left, right, decimals, err); - } - - function assertEq(int256 left, int256 right) internal pure virtual { - if (left != right) { - vm.assertEq(left, right); - } - } - - function assertEq(int256 left, int256 right, string memory err) internal pure virtual { - if (left != right) { - vm.assertEq(left, right, err); - } - } - - function assertEqDecimal(int256 left, int256 right, uint256 decimals) internal pure virtual { - vm.assertEqDecimal(left, right, decimals); - } - - function assertEqDecimal(int256 left, int256 right, uint256 decimals, string memory err) internal pure virtual { - vm.assertEqDecimal(left, right, decimals, err); - } - - function assertEq(address left, address right) internal pure virtual { - if (left != right) { - vm.assertEq(left, right); - } - } - - function assertEq(address left, address right, string memory err) internal pure virtual { - if (left != right) { - vm.assertEq(left, right, err); - } - } - - function assertEq(bytes32 left, bytes32 right) internal pure virtual { - if (left != right) { - vm.assertEq(left, right); - } - } - - function assertEq(bytes32 left, bytes32 right, string memory err) internal pure virtual { - if (left != right) { - vm.assertEq(left, right, err); - } - } - - function assertEq32(bytes32 left, bytes32 right) internal pure virtual { - if (left != right) { - vm.assertEq(left, right); - } - } - - function assertEq32(bytes32 left, bytes32 right, string memory err) internal pure virtual { - if (left != right) { - vm.assertEq(left, right, err); - } - } - - function assertEq(string memory left, string memory right) internal pure virtual { - vm.assertEq(left, right); - } - - function assertEq(string memory left, string memory right, string memory err) internal pure virtual { - vm.assertEq(left, right, err); - } - - function assertEq(bytes memory left, bytes memory right) internal pure virtual { - vm.assertEq(left, right); - } - - function assertEq(bytes memory left, bytes memory right, string memory err) internal pure virtual { - vm.assertEq(left, right, err); - } - - function assertEq(bool[] memory left, bool[] memory right) internal pure virtual { - vm.assertEq(left, right); - } - - function assertEq(bool[] memory left, bool[] memory right, string memory err) internal pure virtual { - vm.assertEq(left, right, err); - } - - function assertEq(uint256[] memory left, uint256[] memory right) internal pure virtual { - vm.assertEq(left, right); - } - - function assertEq(uint256[] memory left, uint256[] memory right, string memory err) internal pure virtual { - vm.assertEq(left, right, err); - } - - function assertEq(int256[] memory left, int256[] memory right) internal pure virtual { - vm.assertEq(left, right); - } - - function assertEq(int256[] memory left, int256[] memory right, string memory err) internal pure virtual { - vm.assertEq(left, right, err); - } - - function assertEq(address[] memory left, address[] memory right) internal pure virtual { - vm.assertEq(left, right); - } - - function assertEq(address[] memory left, address[] memory right, string memory err) internal pure virtual { - vm.assertEq(left, right, err); - } - - function assertEq(bytes32[] memory left, bytes32[] memory right) internal pure virtual { - vm.assertEq(left, right); - } - - function assertEq(bytes32[] memory left, bytes32[] memory right, string memory err) internal pure virtual { - vm.assertEq(left, right, err); - } - - function assertEq(string[] memory left, string[] memory right) internal pure virtual { - vm.assertEq(left, right); - } - - function assertEq(string[] memory left, string[] memory right, string memory err) internal pure virtual { - vm.assertEq(left, right, err); - } - - function assertEq(bytes[] memory left, bytes[] memory right) internal pure virtual { - vm.assertEq(left, right); - } - - function assertEq(bytes[] memory left, bytes[] memory right, string memory err) internal pure virtual { - vm.assertEq(left, right, err); - } - - // Legacy helper - function assertEqUint(uint256 left, uint256 right) internal pure virtual { - assertEq(left, right); - } - - function assertNotEq(bool left, bool right) internal pure virtual { - if (left == right) { - vm.assertNotEq(left, right); - } - } - - function assertNotEq(bool left, bool right, string memory err) internal pure virtual { - if (left == right) { - vm.assertNotEq(left, right, err); - } - } - - function assertNotEq(uint256 left, uint256 right) internal pure virtual { - if (left == right) { - vm.assertNotEq(left, right); - } - } - - function assertNotEq(uint256 left, uint256 right, string memory err) internal pure virtual { - if (left == right) { - vm.assertNotEq(left, right, err); - } - } - - function assertNotEqDecimal(uint256 left, uint256 right, uint256 decimals) internal pure virtual { - vm.assertNotEqDecimal(left, right, decimals); - } - - function assertNotEqDecimal(uint256 left, uint256 right, uint256 decimals, string memory err) - internal - pure - virtual - { - vm.assertNotEqDecimal(left, right, decimals, err); - } - - function assertNotEq(int256 left, int256 right) internal pure virtual { - if (left == right) { - vm.assertNotEq(left, right); - } - } - - function assertNotEq(int256 left, int256 right, string memory err) internal pure virtual { - if (left == right) { - vm.assertNotEq(left, right, err); - } - } - - function assertNotEqDecimal(int256 left, int256 right, uint256 decimals) internal pure virtual { - vm.assertNotEqDecimal(left, right, decimals); - } - - function assertNotEqDecimal(int256 left, int256 right, uint256 decimals, string memory err) internal pure virtual { - vm.assertNotEqDecimal(left, right, decimals, err); - } - - function assertNotEq(address left, address right) internal pure virtual { - if (left == right) { - vm.assertNotEq(left, right); - } - } - - function assertNotEq(address left, address right, string memory err) internal pure virtual { - if (left == right) { - vm.assertNotEq(left, right, err); - } - } - - function assertNotEq(bytes32 left, bytes32 right) internal pure virtual { - if (left == right) { - vm.assertNotEq(left, right); - } - } - - function assertNotEq(bytes32 left, bytes32 right, string memory err) internal pure virtual { - if (left == right) { - vm.assertNotEq(left, right, err); - } - } - - function assertNotEq32(bytes32 left, bytes32 right) internal pure virtual { - if (left == right) { - vm.assertNotEq(left, right); - } - } - - function assertNotEq32(bytes32 left, bytes32 right, string memory err) internal pure virtual { - if (left == right) { - vm.assertNotEq(left, right, err); - } - } - - function assertNotEq(string memory left, string memory right) internal pure virtual { - vm.assertNotEq(left, right); - } - - function assertNotEq(string memory left, string memory right, string memory err) internal pure virtual { - vm.assertNotEq(left, right, err); - } - - function assertNotEq(bytes memory left, bytes memory right) internal pure virtual { - vm.assertNotEq(left, right); - } - - function assertNotEq(bytes memory left, bytes memory right, string memory err) internal pure virtual { - vm.assertNotEq(left, right, err); - } - - function assertNotEq(bool[] memory left, bool[] memory right) internal pure virtual { - vm.assertNotEq(left, right); - } - - function assertNotEq(bool[] memory left, bool[] memory right, string memory err) internal pure virtual { - vm.assertNotEq(left, right, err); - } - - function assertNotEq(uint256[] memory left, uint256[] memory right) internal pure virtual { - vm.assertNotEq(left, right); - } - - function assertNotEq(uint256[] memory left, uint256[] memory right, string memory err) internal pure virtual { - vm.assertNotEq(left, right, err); - } - - function assertNotEq(int256[] memory left, int256[] memory right) internal pure virtual { - vm.assertNotEq(left, right); - } - - function assertNotEq(int256[] memory left, int256[] memory right, string memory err) internal pure virtual { - vm.assertNotEq(left, right, err); - } - - function assertNotEq(address[] memory left, address[] memory right) internal pure virtual { - vm.assertNotEq(left, right); - } - - function assertNotEq(address[] memory left, address[] memory right, string memory err) internal pure virtual { - vm.assertNotEq(left, right, err); - } - - function assertNotEq(bytes32[] memory left, bytes32[] memory right) internal pure virtual { - vm.assertNotEq(left, right); - } - - function assertNotEq(bytes32[] memory left, bytes32[] memory right, string memory err) internal pure virtual { - vm.assertNotEq(left, right, err); - } - - function assertNotEq(string[] memory left, string[] memory right) internal pure virtual { - vm.assertNotEq(left, right); - } - - function assertNotEq(string[] memory left, string[] memory right, string memory err) internal pure virtual { - vm.assertNotEq(left, right, err); - } - - function assertNotEq(bytes[] memory left, bytes[] memory right) internal pure virtual { - vm.assertNotEq(left, right); - } - - function assertNotEq(bytes[] memory left, bytes[] memory right, string memory err) internal pure virtual { - vm.assertNotEq(left, right, err); - } - - function assertLt(uint256 left, uint256 right) internal pure virtual { - if (left >= right) { - vm.assertLt(left, right); - } - } - - function assertLt(uint256 left, uint256 right, string memory err) internal pure virtual { - if (left >= right) { - vm.assertLt(left, right, err); - } - } - - function assertLtDecimal(uint256 left, uint256 right, uint256 decimals) internal pure virtual { - vm.assertLtDecimal(left, right, decimals); - } - - function assertLtDecimal(uint256 left, uint256 right, uint256 decimals, string memory err) internal pure virtual { - vm.assertLtDecimal(left, right, decimals, err); - } - - function assertLt(int256 left, int256 right) internal pure virtual { - if (left >= right) { - vm.assertLt(left, right); - } - } - - function assertLt(int256 left, int256 right, string memory err) internal pure virtual { - if (left >= right) { - vm.assertLt(left, right, err); - } - } - - function assertLtDecimal(int256 left, int256 right, uint256 decimals) internal pure virtual { - vm.assertLtDecimal(left, right, decimals); - } - - function assertLtDecimal(int256 left, int256 right, uint256 decimals, string memory err) internal pure virtual { - vm.assertLtDecimal(left, right, decimals, err); - } - - function assertGt(uint256 left, uint256 right) internal pure virtual { - if (left <= right) { - vm.assertGt(left, right); - } - } - - function assertGt(uint256 left, uint256 right, string memory err) internal pure virtual { - if (left <= right) { - vm.assertGt(left, right, err); - } - } - - function assertGtDecimal(uint256 left, uint256 right, uint256 decimals) internal pure virtual { - vm.assertGtDecimal(left, right, decimals); - } - - function assertGtDecimal(uint256 left, uint256 right, uint256 decimals, string memory err) internal pure virtual { - vm.assertGtDecimal(left, right, decimals, err); - } - - function assertGt(int256 left, int256 right) internal pure virtual { - if (left <= right) { - vm.assertGt(left, right); - } - } - - function assertGt(int256 left, int256 right, string memory err) internal pure virtual { - if (left <= right) { - vm.assertGt(left, right, err); - } - } - - function assertGtDecimal(int256 left, int256 right, uint256 decimals) internal pure virtual { - vm.assertGtDecimal(left, right, decimals); - } - - function assertGtDecimal(int256 left, int256 right, uint256 decimals, string memory err) internal pure virtual { - vm.assertGtDecimal(left, right, decimals, err); - } - - function assertLe(uint256 left, uint256 right) internal pure virtual { - if (left > right) { - vm.assertLe(left, right); - } - } - - function assertLe(uint256 left, uint256 right, string memory err) internal pure virtual { - if (left > right) { - vm.assertLe(left, right, err); - } - } - - function assertLeDecimal(uint256 left, uint256 right, uint256 decimals) internal pure virtual { - vm.assertLeDecimal(left, right, decimals); - } - - function assertLeDecimal(uint256 left, uint256 right, uint256 decimals, string memory err) internal pure virtual { - vm.assertLeDecimal(left, right, decimals, err); - } - - function assertLe(int256 left, int256 right) internal pure virtual { - if (left > right) { - vm.assertLe(left, right); - } - } - - function assertLe(int256 left, int256 right, string memory err) internal pure virtual { - if (left > right) { - vm.assertLe(left, right, err); - } - } - - function assertLeDecimal(int256 left, int256 right, uint256 decimals) internal pure virtual { - vm.assertLeDecimal(left, right, decimals); - } - - function assertLeDecimal(int256 left, int256 right, uint256 decimals, string memory err) internal pure virtual { - vm.assertLeDecimal(left, right, decimals, err); - } - - function assertGe(uint256 left, uint256 right) internal pure virtual { - if (left < right) { - vm.assertGe(left, right); - } - } - - function assertGe(uint256 left, uint256 right, string memory err) internal pure virtual { - if (left < right) { - vm.assertGe(left, right, err); - } - } - - function assertGeDecimal(uint256 left, uint256 right, uint256 decimals) internal pure virtual { - vm.assertGeDecimal(left, right, decimals); - } - - function assertGeDecimal(uint256 left, uint256 right, uint256 decimals, string memory err) internal pure virtual { - vm.assertGeDecimal(left, right, decimals, err); - } - - function assertGe(int256 left, int256 right) internal pure virtual { - if (left < right) { - vm.assertGe(left, right); - } - } - - function assertGe(int256 left, int256 right, string memory err) internal pure virtual { - if (left < right) { - vm.assertGe(left, right, err); - } - } - - function assertGeDecimal(int256 left, int256 right, uint256 decimals) internal pure virtual { - vm.assertGeDecimal(left, right, decimals); - } - - function assertGeDecimal(int256 left, int256 right, uint256 decimals, string memory err) internal pure virtual { - vm.assertGeDecimal(left, right, decimals, err); - } - - function assertApproxEqAbs(uint256 left, uint256 right, uint256 maxDelta) internal pure virtual { - vm.assertApproxEqAbs(left, right, maxDelta); - } - - function assertApproxEqAbs(uint256 left, uint256 right, uint256 maxDelta, string memory err) - internal - pure - virtual - { - vm.assertApproxEqAbs(left, right, maxDelta, err); - } - - function assertApproxEqAbsDecimal(uint256 left, uint256 right, uint256 maxDelta, uint256 decimals) - internal - pure - virtual - { - vm.assertApproxEqAbsDecimal(left, right, maxDelta, decimals); - } - - function assertApproxEqAbsDecimal( - uint256 left, - uint256 right, - uint256 maxDelta, - uint256 decimals, - string memory err - ) internal pure virtual { - vm.assertApproxEqAbsDecimal(left, right, maxDelta, decimals, err); - } - - function assertApproxEqAbs(int256 left, int256 right, uint256 maxDelta) internal pure virtual { - vm.assertApproxEqAbs(left, right, maxDelta); - } - - function assertApproxEqAbs(int256 left, int256 right, uint256 maxDelta, string memory err) internal pure virtual { - vm.assertApproxEqAbs(left, right, maxDelta, err); - } - - function assertApproxEqAbsDecimal(int256 left, int256 right, uint256 maxDelta, uint256 decimals) - internal - pure - virtual - { - vm.assertApproxEqAbsDecimal(left, right, maxDelta, decimals); - } - - function assertApproxEqAbsDecimal(int256 left, int256 right, uint256 maxDelta, uint256 decimals, string memory err) - internal - pure - virtual - { - vm.assertApproxEqAbsDecimal(left, right, maxDelta, decimals, err); - } - - function assertApproxEqRel( - uint256 left, - uint256 right, - uint256 maxPercentDelta // An 18 decimal fixed point number, where 1e18 == 100% - ) internal pure virtual { - vm.assertApproxEqRel(left, right, maxPercentDelta); - } - - function assertApproxEqRel( - uint256 left, - uint256 right, - uint256 maxPercentDelta, // An 18 decimal fixed point number, where 1e18 == 100% - string memory err - ) internal pure virtual { - vm.assertApproxEqRel(left, right, maxPercentDelta, err); - } - - function assertApproxEqRelDecimal( - uint256 left, - uint256 right, - uint256 maxPercentDelta, // An 18 decimal fixed point number, where 1e18 == 100% - uint256 decimals - ) internal pure virtual { - vm.assertApproxEqRelDecimal(left, right, maxPercentDelta, decimals); - } - - function assertApproxEqRelDecimal( - uint256 left, - uint256 right, - uint256 maxPercentDelta, // An 18 decimal fixed point number, where 1e18 == 100% - uint256 decimals, - string memory err - ) internal pure virtual { - vm.assertApproxEqRelDecimal(left, right, maxPercentDelta, decimals, err); - } - - function assertApproxEqRel(int256 left, int256 right, uint256 maxPercentDelta) internal pure virtual { - vm.assertApproxEqRel(left, right, maxPercentDelta); - } - - function assertApproxEqRel( - int256 left, - int256 right, - uint256 maxPercentDelta, // An 18 decimal fixed point number, where 1e18 == 100% - string memory err - ) internal pure virtual { - vm.assertApproxEqRel(left, right, maxPercentDelta, err); - } - - function assertApproxEqRelDecimal( - int256 left, - int256 right, - uint256 maxPercentDelta, // An 18 decimal fixed point number, where 1e18 == 100% - uint256 decimals - ) internal pure virtual { - vm.assertApproxEqRelDecimal(left, right, maxPercentDelta, decimals); - } - - function assertApproxEqRelDecimal( - int256 left, - int256 right, - uint256 maxPercentDelta, // An 18 decimal fixed point number, where 1e18 == 100% - uint256 decimals, - string memory err - ) internal pure virtual { - vm.assertApproxEqRelDecimal(left, right, maxPercentDelta, decimals, err); - } - - // Inherited from DSTest, not used but kept for backwards-compatibility - function checkEq0(bytes memory left, bytes memory right) internal pure returns (bool) { - return keccak256(left) == keccak256(right); - } - - function assertEq0(bytes memory left, bytes memory right) internal pure virtual { - assertEq(left, right); - } - - function assertEq0(bytes memory left, bytes memory right, string memory err) internal pure virtual { - assertEq(left, right, err); - } - - function assertNotEq0(bytes memory left, bytes memory right) internal pure virtual { - assertNotEq(left, right); - } - - function assertNotEq0(bytes memory left, bytes memory right, string memory err) internal pure virtual { - assertNotEq(left, right, err); - } - - function assertEqCall(address target, bytes memory callDataA, bytes memory callDataB) internal virtual { - assertEqCall(target, callDataA, target, callDataB, true); - } - - function assertEqCall(address targetA, bytes memory callDataA, address targetB, bytes memory callDataB) - internal - virtual - { - assertEqCall(targetA, callDataA, targetB, callDataB, true); - } - - function assertEqCall(address target, bytes memory callDataA, bytes memory callDataB, bool strictRevertData) - internal - virtual - { - assertEqCall(target, callDataA, target, callDataB, strictRevertData); - } - - function assertEqCall( - address targetA, - bytes memory callDataA, - address targetB, - bytes memory callDataB, - bool strictRevertData - ) internal virtual { - (bool successA, bytes memory returnDataA) = address(targetA).call(callDataA); - (bool successB, bytes memory returnDataB) = address(targetB).call(callDataB); - - if (successA && successB) { - assertEq(returnDataA, returnDataB, "Call return data does not match"); - } - - if (!successA && !successB && strictRevertData) { - assertEq(returnDataA, returnDataB, "Call revert data does not match"); - } - - if (!successA && successB) { - emit log("Error: Calls were not equal"); - emit log_named_bytes(" Left call revert data", returnDataA); - emit log_named_bytes(" Right call return data", returnDataB); - revert("assertion failed"); - } - - if (successA && !successB) { - emit log("Error: Calls were not equal"); - emit log_named_bytes(" Left call return data", returnDataA); - emit log_named_bytes(" Right call revert data", returnDataB); - revert("assertion failed"); - } - } -} diff --git a/dependencies/forge-std-1.11.0/src/StdError.sol b/dependencies/forge-std-1.11.0/src/StdError.sol deleted file mode 100644 index a302191..0000000 --- a/dependencies/forge-std-1.11.0/src/StdError.sol +++ /dev/null @@ -1,15 +0,0 @@ -// SPDX-License-Identifier: MIT -// Panics work for versions >=0.8.0, but we lowered the pragma to make this compatible with Test -pragma solidity >=0.6.2 <0.9.0; - -library stdError { - bytes public constant assertionError = abi.encodeWithSignature("Panic(uint256)", 0x01); - bytes public constant arithmeticError = abi.encodeWithSignature("Panic(uint256)", 0x11); - bytes public constant divisionError = abi.encodeWithSignature("Panic(uint256)", 0x12); - bytes public constant enumConversionError = abi.encodeWithSignature("Panic(uint256)", 0x21); - bytes public constant encodeStorageError = abi.encodeWithSignature("Panic(uint256)", 0x22); - bytes public constant popError = abi.encodeWithSignature("Panic(uint256)", 0x31); - bytes public constant indexOOBError = abi.encodeWithSignature("Panic(uint256)", 0x32); - bytes public constant memOverflowError = abi.encodeWithSignature("Panic(uint256)", 0x41); - bytes public constant zeroVarError = abi.encodeWithSignature("Panic(uint256)", 0x51); -} diff --git a/dependencies/forge-std-1.11.0/src/StdMath.sol b/dependencies/forge-std-1.11.0/src/StdMath.sol deleted file mode 100644 index 459523b..0000000 --- a/dependencies/forge-std-1.11.0/src/StdMath.sol +++ /dev/null @@ -1,43 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity >=0.6.2 <0.9.0; - -library stdMath { - int256 private constant INT256_MIN = -57896044618658097711785492504343953926634992332820282019728792003956564819968; - - function abs(int256 a) internal pure returns (uint256) { - // Required or it will fail when `a = type(int256).min` - if (a == INT256_MIN) { - return 57896044618658097711785492504343953926634992332820282019728792003956564819968; - } - - return uint256(a > 0 ? a : -a); - } - - function delta(uint256 a, uint256 b) internal pure returns (uint256) { - return a > b ? a - b : b - a; - } - - function delta(int256 a, int256 b) internal pure returns (uint256) { - // a and b are of the same sign - // this works thanks to two's complement, the left-most bit is the sign bit - if ((a ^ b) > -1) { - return delta(abs(a), abs(b)); - } - - // a and b are of opposite signs - return abs(a) + abs(b); - } - - function percentDelta(uint256 a, uint256 b) internal pure returns (uint256) { - uint256 absDelta = delta(a, b); - - return absDelta * 1e18 / b; - } - - function percentDelta(int256 a, int256 b) internal pure returns (uint256) { - uint256 absDelta = delta(a, b); - uint256 absB = abs(b); - - return absDelta * 1e18 / absB; - } -} diff --git a/dependencies/forge-std-1.11.0/src/console2.sol b/dependencies/forge-std-1.11.0/src/console2.sol deleted file mode 100644 index 03531d9..0000000 --- a/dependencies/forge-std-1.11.0/src/console2.sol +++ /dev/null @@ -1,4 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity >=0.4.22 <0.9.0; - -import {console as console2} from "./console.sol"; diff --git a/dependencies/forge-std-1.16.2/.github/CODEOWNERS b/dependencies/forge-std-1.16.2/.github/CODEOWNERS new file mode 100644 index 0000000..1deb6d2 --- /dev/null +++ b/dependencies/forge-std-1.16.2/.github/CODEOWNERS @@ -0,0 +1 @@ +* @danipopes @mattsse @grandizzy @onbjerg @0xrusowsky diff --git a/dependencies/forge-std-1.16.2/.github/dependabot.yml b/dependencies/forge-std-1.16.2/.github/dependabot.yml new file mode 100644 index 0000000..02b248b --- /dev/null +++ b/dependencies/forge-std-1.16.2/.github/dependabot.yml @@ -0,0 +1,15 @@ +version: 2 +updates: + - package-ecosystem: github-actions + directory: / + schedule: + interval: weekly + day: monday + time: "09:00" + timezone: UTC + cooldown: + default-days: 7 + groups: + ci-weekly: + patterns: + - '*' diff --git a/dependencies/forge-std-1.16.2/.github/workflows/ci.yml b/dependencies/forge-std-1.16.2/.github/workflows/ci.yml new file mode 100644 index 0000000..809c51a --- /dev/null +++ b/dependencies/forge-std-1.16.2/.github/workflows/ci.yml @@ -0,0 +1,163 @@ +name: CI + +permissions: {} + +on: + workflow_dispatch: + pull_request: + push: + branches: + - master + +env: + SOLC_MINIMUM: "0.8.13" + SOLC_LATEST: "0.8.35" + SOLC_PRERELEASE: "" + +jobs: + build-matrix: + runs-on: ubuntu-latest + timeout-minutes: 5 + permissions: + contents: read + outputs: + matrix: ${{ steps.generate.outputs.matrix }} + steps: + - id: generate + run: | + MINIMUM="${{ env.SOLC_MINIMUM }}" + LATEST="${{ env.SOLC_LATEST }}" + PRERELEASE="${{ env.SOLC_PRERELEASE }}" + matrix='{"include":[' + for toolchain in stable nightly; do + for flags in \ + "" \ + "--via-ir" \ + "--use solc:${LATEST}" \ + "--use solc:${LATEST} --via-ir" \ + "--use solc:${MINIMUM}" \ + "--use solc:${MINIMUM} --via-ir" + do + matrix+='{"toolchain":"'"$toolchain"'","flags":"'"$flags"'","prerelease":false},' + done + done + # prerelease (nightly only, svm-rs is not up to date on stable) + if [ -n "$PRERELEASE" ]; then + for flags in \ + "--use solc:${PRERELEASE}" \ + "--use solc:${PRERELEASE} --via-ir" + do + matrix+='{"toolchain":"nightly","flags":"'"$flags"'","prerelease":true},' + done + fi + matrix="${matrix%,}]}" + echo "matrix=$matrix" >> "$GITHUB_OUTPUT" + + build: + needs: build-matrix + name: build +${{ matrix.toolchain }} ${{ matrix.flags }} + runs-on: ubuntu-latest + timeout-minutes: 10 + permissions: + contents: read + strategy: + fail-fast: false + matrix: ${{ fromJSON(needs.build-matrix.outputs.matrix) }} + steps: + - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 + with: + persist-credentials: false + - uses: foundry-rs/foundry-toolchain@c7450ba673e133f5ee30098b3b54f444d3a2ca2d # v1.8.0 + with: + version: ${{ matrix.toolchain }} + - run: forge --version + # 3805: "This is a pre-release compiler version, please do not use it in production." + - run: forge build -vvvvv --skip test --deny warnings ${{ matrix.prerelease && '--ignored-error-codes 3805' || '' }} ${{ matrix.flags }} --contracts 'test/compilation/*' + + test: + runs-on: ubuntu-latest + timeout-minutes: 10 + permissions: + contents: read + strategy: + fail-fast: false + matrix: + toolchain: [stable, nightly] + steps: + - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 + with: + persist-credentials: false + - uses: foundry-rs/foundry-toolchain@c7450ba673e133f5ee30098b3b54f444d3a2ca2d # v1.8.0 + with: + version: ${{ matrix.toolchain }} + - run: forge --version + - run: forge test -vvv + + fmt: + runs-on: ubuntu-latest + timeout-minutes: 10 + permissions: + contents: read + steps: + - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 + with: + persist-credentials: false + - uses: foundry-rs/foundry-toolchain@c7450ba673e133f5ee30098b3b54f444d3a2ca2d # v1.8.0 + - run: forge --version + - run: forge fmt --check + + typos: + runs-on: ubuntu-latest + timeout-minutes: 10 + permissions: + contents: read + steps: + - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 + with: + persist-credentials: false + - uses: crate-ci/typos@5374cbf686e897b15713110e233094e2874de7ef # v1.46.1 + + codeql: + name: Analyze (${{ matrix.language }}) + runs-on: ubuntu-latest + permissions: + security-events: write + actions: read + contents: read + strategy: + fail-fast: false + matrix: + include: + - language: actions + build-mode: none + steps: + - name: Checkout repository + uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 + with: + persist-credentials: false + - name: Initialize CodeQL + uses: github/codeql-action/init@8aad20d150bbac5944a9f9d289da16a4b0d87c1e # v4.36.2 + with: + languages: ${{ matrix.language }} + build-mode: ${{ matrix.build-mode }} + - name: Perform CodeQL Analysis + uses: github/codeql-action/analyze@8aad20d150bbac5944a9f9d289da16a4b0d87c1e # v4.36.2 + with: + category: "/language:${{matrix.language}}" + + ci-success: + runs-on: ubuntu-latest + if: always() + needs: + - build-matrix + - build + - test + - fmt + - typos + - codeql + timeout-minutes: 10 + steps: + - name: Decide whether the needed jobs succeeded or failed + uses: re-actors/alls-green@05ac9388f0aebcb5727afa17fcccfecd6f8ec5fe # release/v1 + with: + jobs: ${{ toJSON(needs) }} diff --git a/dependencies/forge-std-1.11.0/.github/workflows/sync.yml b/dependencies/forge-std-1.16.2/.github/workflows/sync.yml similarity index 91% rename from dependencies/forge-std-1.11.0/.github/workflows/sync.yml rename to dependencies/forge-std-1.16.2/.github/workflows/sync.yml index 15731cb..4dc9411 100644 --- a/dependencies/forge-std-1.11.0/.github/workflows/sync.yml +++ b/dependencies/forge-std-1.16.2/.github/workflows/sync.yml @@ -15,7 +15,7 @@ jobs: if: startsWith(github.event.release.tag_name, 'v1') steps: - name: Check out the repo - uses: actions/checkout@v5 + uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 with: persist-credentials: true fetch-depth: 0 diff --git a/dependencies/forge-std-1.11.0/.gitignore b/dependencies/forge-std-1.16.2/.gitignore similarity index 100% rename from dependencies/forge-std-1.11.0/.gitignore rename to dependencies/forge-std-1.16.2/.gitignore diff --git a/dependencies/forge-std-1.11.0/CONTRIBUTING.md b/dependencies/forge-std-1.16.2/CONTRIBUTING.md similarity index 98% rename from dependencies/forge-std-1.11.0/CONTRIBUTING.md rename to dependencies/forge-std-1.16.2/CONTRIBUTING.md index 89b75f3..8f4aa89 100644 --- a/dependencies/forge-std-1.11.0/CONTRIBUTING.md +++ b/dependencies/forge-std-1.16.2/CONTRIBUTING.md @@ -140,13 +140,13 @@ All contributors who choose to review and provide feedback on pull requests have Reviews that are dismissive or disrespectful of the contributor or any other reviewers are strictly counter to the Code of Conduct. -When reviewing a pull request, the primary goals are for the codebase to improve and for the person submitting the request to succeed. **Even if a pull request is not merged, the submitter should come away from the experience feeling like their effort was not unappreciated**. Every PR from a new contributor is an opportunity to grow the community. +When reviewing a pull request, the primary goals are for the codebase to improve and for the person submitting the request to succeed. **Even if a pull request is not merged, the submitter should come away from the experience feeling like their effort was appreciated**. Every PR from a new contributor is an opportunity to grow the community. ##### Review a bit at a time Do not overwhelm new contributors. -It is tempting to micro-optimize and make everything about relative performance, perfect grammar, or exact style matches. Do not succumb to that temptation.. +It is tempting to micro-optimize and make everything about relative performance, perfect grammar, or exact style matches. Do not succumb to that temptation. Focus first on the most significant aspects of the change: @@ -190,4 +190,4 @@ Releases are automatically done by the release workflow when a tag is pushed, ho [foundry-book]: https://github.com/foundry-rs/foundry-book [support-tg]: https://t.me/foundry_support [mcve]: https://stackoverflow.com/help/mcve -[hiding-a-comment]: https://help.github.com/articles/managing-disruptive-comments/#hiding-a-comment \ No newline at end of file +[hiding-a-comment]: https://help.github.com/articles/managing-disruptive-comments/#hiding-a-comment diff --git a/dependencies/forge-std-1.11.0/LICENSE-APACHE b/dependencies/forge-std-1.16.2/LICENSE-APACHE similarity index 100% rename from dependencies/forge-std-1.11.0/LICENSE-APACHE rename to dependencies/forge-std-1.16.2/LICENSE-APACHE diff --git a/dependencies/forge-std-1.11.0/LICENSE-MIT b/dependencies/forge-std-1.16.2/LICENSE-MIT similarity index 100% rename from dependencies/forge-std-1.11.0/LICENSE-MIT rename to dependencies/forge-std-1.16.2/LICENSE-MIT diff --git a/dependencies/forge-std-1.11.0/README.md b/dependencies/forge-std-1.16.2/README.md similarity index 68% rename from dependencies/forge-std-1.11.0/README.md rename to dependencies/forge-std-1.16.2/README.md index 51673e5..13015e4 100644 --- a/dependencies/forge-std-1.11.0/README.md +++ b/dependencies/forge-std-1.16.2/README.md @@ -11,6 +11,7 @@ forge install foundry-rs/forge-std ``` ## Contracts + ### stdError This is a helper contract for errors and reverts. In Forge, this contract is particularly helpful for the `expectRevert` cheatcode, as it provides all compiler built-in errors. @@ -45,11 +46,12 @@ contract ErrorsTest { ### stdStorage -This is a rather large contract due to all of the overloading to make the UX decent. Primarily, it is a wrapper around the `record` and `accesses` cheatcodes. It can *always* find and write the storage slot(s) associated with a particular variable without knowing the storage layout. The one _major_ caveat to this is while a slot can be found for packed storage variables, we can't write to that variable safely. If a user tries to write to a packed slot, the execution throws an error, unless it is uninitialized (`bytes32(0)`). +This is a rather large contract due to all of the overloading to make the UX decent. Primarily, it is a wrapper around the `record` and `accesses` cheatcodes. It can _always_ find and write the storage slot(s) associated with a particular variable without knowing the storage layout. By default, writing to packed storage variables is not supported and will throw an error. However, you can enable packed slot support by calling `enable_packed_slots()` before using `find()` or `checked_write()`. This works by recording all `SLOAD`s and `SSTORE`s during a function call. If there is a single slot read or written to, it immediately returns the slot. Otherwise, behind the scenes, we iterate through and check each one (assuming the user passed in a `depth` parameter). If the variable is a struct, you can pass in a `depth` parameter which is basically the field depth. I.e.: + ```solidity struct T { // depth 0 @@ -74,7 +76,7 @@ contract TestContract is Test { } function testFindExists() public { - // Lets say we want to find the slot for the public + // Let's say we want to find the slot for the public // variable `exists`. We just pass in the function selector // to the `find` command uint256 slot = stdstore.target(address(test)).sig("exists()").find(); @@ -82,16 +84,16 @@ contract TestContract is Test { } function testWriteExists() public { - // Lets say we want to write to the slot for the public + // Let's say we want to write to the slot for the public // variable `exists`. We just pass in the function selector // to the `checked_write` command stdstore.target(address(test)).sig("exists()").checked_write(100); assertEq(test.exists(), 100); } - // It supports arbitrary storage layouts, like assembly based storage locations + // It supports arbitrary storage layouts, like assembly-based storage locations function testFindHidden() public { - // `hidden` is a random hash of a bytes, iteration through slots would + // `hidden` is a random hash of bytes; iterating through slots would // not find it. Our mechanism does // Also, you can use the selector instead of a string uint256 slot = stdstore.target(address(test)).sig(test.hidden.selector).find(); @@ -165,13 +167,13 @@ contract Storage { ### stdCheats -This is a wrapper over miscellaneous cheatcodes that need wrappers to be more dev friendly. Currently there are only functions related to `prank`. In general, users may expect ETH to be put into an address on `prank`, but this is not the case for safety reasons. Explicitly this `hoax` function should only be used for addresses that have expected balances as it will get overwritten. If an address already has ETH, you should just use `prank`. If you want to change that balance explicitly, just use `deal`. If you want to do both, `hoax` is also right for you. - +This is a wrapper around miscellaneous cheatcodes that need wrappers to be more dev-friendly. It includes functions for pranking, dealing with ETH and tokens, deploying contracts, creating test addresses, time manipulation, and fuzzing helpers. In general, users may expect ETH to be put into an address with `prank`, but this is not the case for safety reasons. Explicitly, this `hoax` function should only be used for addresses that have expected balances as it will get overwritten. If an address already has ETH, you should just use `prank`. If you want to change that balance explicitly, just use `deal`. If you want to do both, `hoax` is also right for you. #### Example usage: + ```solidity -// SPDX-License-Identifier: MIT +// SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity ^0.8.0; import "forge-std/Test.sol"; @@ -217,7 +219,53 @@ contract Bar { ### Std Assertions -Contains various assertions. +Provides comprehensive assertion functions for testing, including equality checks (assertEq, assertNotEq), comparisons (assertLt, assertGt, assertLe, assertGe), approximate equality (assertApproxEqAbs, assertApproxEqRel), and boolean assertions (assertTrue, assertFalse). All assertions support multiple data types and optional custom error messages. + +### StdConfig + +This is a contract that parses a TOML configuration file and loads its variables into storage, automatically casting them on deployment. It assumes a TOML structure where top-level keys represent chain IDs or aliases. Under each chain key, variables are organized by type in separate sub-tables like `[.]`, where type must be: `bool`, `address`, `bytes32`, `uint`, `int`, `string`, or `bytes`. + +#### Example usage + +```solidity + +// SPDX-License-Identifier: MIT OR Apache-2.0 +pragma solidity ^0.8.13; + +import "forge-std/Script.sol"; +import "forge-std/StdConfig.sol"; + +contract MyScript is Script { + StdConfig config; + + function run() public { + // Load config (set writeToFile=true only in scripts to persist changes) + config = new StdConfig("config.toml", false); + + // Get values for the current chain + uint256 myNumber = config.get("important_number").toUint256(); + address weth = config.get("weth").toAddress(); + address[] memory admins = config.get("whitelisted_admins").toAddressArray(); + + // Get values for a specific chain + bool isLive = config.get(1, "is_live").toBool(); + + // Check if a key exists + if (config.exists("optional_param")) { + // ... + } + + // Get RPC URL for current or specific chain + string memory rpc = config.getRpcUrl(); + string memory mainnetRpc = config.getRpcUrl(1); + + // Get all configured chain IDs + uint256[] memory chainIds = config.getChainIds(); + } +} +``` + +See the contract itself for supported TOML format and all available methods. ### `console.log` @@ -251,13 +299,13 @@ See our [contributing guidelines](./CONTRIBUTING.md). ## Getting Help -First, see if the answer to your question can be found in [book](https://book.getfoundry.sh). +First, see if the answer to your question can be found in [book](https://getfoundry.sh/). If the answer is not there: -- Join the [support Telegram](https://t.me/foundry_support) to get help, or -- Open a [discussion](https://github.com/foundry-rs/foundry/discussions/new/choose) with your question, or -- Open an issue with [the bug](https://github.com/foundry-rs/foundry/issues/new/choose) +- Join the [support Telegram](https://t.me/foundry_support) to get help, or +- Open a [discussion](https://github.com/foundry-rs/foundry/discussions/new/choose) with your question, or +- Open an issue with [the bug](https://github.com/foundry-rs/foundry/issues/new/choose) If you want to contribute, or follow along with contributor discussion, you can use our [main telegram](https://t.me/foundry_rs) to chat with us about the development of Foundry! diff --git a/dependencies/forge-std-1.11.0/RELEASE_CHECKLIST.md b/dependencies/forge-std-1.16.2/RELEASE_CHECKLIST.md similarity index 90% rename from dependencies/forge-std-1.11.0/RELEASE_CHECKLIST.md rename to dependencies/forge-std-1.16.2/RELEASE_CHECKLIST.md index 4611de4..82b33c2 100644 --- a/dependencies/forge-std-1.11.0/RELEASE_CHECKLIST.md +++ b/dependencies/forge-std-1.16.2/RELEASE_CHECKLIST.md @@ -8,5 +8,5 @@ This checklist is meant to be used as a guide for the `forge-std` release proces - [ ] Open and merge a PR with the version bump - [ ] Tag the merged commit with the version number: `git tag v` - [ ] Push the tag to the repository: `git push --tags` -- [ ] Create a new GitHub release with the automatically generated changelog and with the name set to `v` +- [ ] Create a new GitHub release with the automatically generated changelog and the name set to `v` - [ ] Add `## Featured Changes` section to the top of the release notes diff --git a/dependencies/forge-std-1.11.0/scripts/vm.py b/dependencies/forge-std-1.16.2/scripts/vm.py similarity index 96% rename from dependencies/forge-std-1.11.0/scripts/vm.py rename to dependencies/forge-std-1.16.2/scripts/vm.py index 3cd047d..3d37207 100644 --- a/dependencies/forge-std-1.11.0/scripts/vm.py +++ b/dependencies/forge-std-1.16.2/scripts/vm.py @@ -7,7 +7,7 @@ import subprocess from enum import Enum as PyEnum from pathlib import Path -from typing import Callable +from typing import Callable, Optional, Union from urllib import request VoidFn = Callable[[], None] @@ -59,8 +59,7 @@ def main(): pp = CheatcodesPrinter( spdx_identifier="MIT OR Apache-2.0", - solidity_requirement=">=0.6.2 <0.9.0", - abicoder_pragma=True, + solidity_requirement=">=0.8.13 <0.9.0", ) pp.p_prelude() pp.prelude = False @@ -412,7 +411,6 @@ class CheatcodesPrinter: prelude: bool spdx_identifier: str solidity_requirement: str - abicoder_v2: bool block_doc_style: bool @@ -429,17 +427,15 @@ def __init__( prelude: bool = True, spdx_identifier: str = "UNLICENSED", solidity_requirement: str = "", - abicoder_pragma: bool = False, block_doc_style: bool = False, indent_level: int = 0, - indent_with: int | str = 4, + indent_with: Union[int, str] = 4, nl_str: str = "\n", items_order: ItemOrder = ItemOrder.default(), ): self.prelude = prelude self.spdx_identifier = spdx_identifier self.solidity_requirement = solidity_requirement - self.abicoder_v2 = abicoder_pragma self.block_doc_style = block_doc_style self.buffer = buffer self.indent_level = indent_level @@ -494,23 +490,17 @@ def _p_items(self, contract: Cheatcodes): else: assert False, f"unknown item {item}" - def p_prelude(self, contract: Cheatcodes | None = None): + def p_prelude(self, contract: Optional[Cheatcodes] = None): self._p_str(f"// SPDX-License-Identifier: {self.spdx_identifier}") self._p_nl() if self.solidity_requirement != "": req = self.solidity_requirement - elif contract and len(contract.errors) > 0: - req = ">=0.8.4 <0.9.0" else: - req = ">=0.6.0 <0.9.0" + req = ">=0.8.13 <0.9.0" self._p_str(f"pragma solidity {req};") self._p_nl() - if self.abicoder_v2: - self._p_str("pragma experimental ABIEncoderV2;") - self._p_nl() - self._p_nl() def p_errors(self, errors: list[Error]): diff --git a/dependencies/forge-std-1.11.0/src/Base.sol b/dependencies/forge-std-1.16.2/src/Base.sol similarity index 96% rename from dependencies/forge-std-1.11.0/src/Base.sol rename to dependencies/forge-std-1.16.2/src/Base.sol index 52a5082..d948010 100644 --- a/dependencies/forge-std-1.11.0/src/Base.sol +++ b/dependencies/forge-std-1.16.2/src/Base.sol @@ -1,5 +1,5 @@ -// SPDX-License-Identifier: MIT -pragma solidity >=0.6.2 <0.9.0; +// SPDX-License-Identifier: MIT OR Apache-2.0 +pragma solidity >=0.8.13 <0.9.0; import {StdStorage} from "./StdStorage.sol"; import {Vm, VmSafe} from "./Vm.sol"; diff --git a/dependencies/forge-std-1.11.0/src/Config.sol b/dependencies/forge-std-1.16.2/src/Config.sol similarity index 98% rename from dependencies/forge-std-1.11.0/src/Config.sol rename to dependencies/forge-std-1.16.2/src/Config.sol index 1c63c87..3d35bb5 100644 --- a/dependencies/forge-std-1.11.0/src/Config.sol +++ b/dependencies/forge-std-1.16.2/src/Config.sol @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: MIT +// SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity ^0.8.13; import {console} from "./console.sol"; diff --git a/dependencies/forge-std-1.11.0/src/LibVariable.sol b/dependencies/forge-std-1.16.2/src/LibVariable.sol similarity index 99% rename from dependencies/forge-std-1.11.0/src/LibVariable.sol rename to dependencies/forge-std-1.16.2/src/LibVariable.sol index c46b153..32fe5bf 100644 --- a/dependencies/forge-std-1.11.0/src/LibVariable.sol +++ b/dependencies/forge-std-1.16.2/src/LibVariable.sol @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: MIT +// SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity ^0.8.13; // Enable globally. @@ -48,7 +48,7 @@ enum TypeKind { /// // string memory notANumber = config.get("important_number").toString(); /// /// // Retrieve a address array from the config. -/// string[] memory admins = config.get("whitelisted_admins").toAddressArray(); +/// address[] memory admins = config.get("whitelisted_admins").toAddressArray(); /// } /// } /// ``` diff --git a/dependencies/forge-std-1.11.0/src/Script.sol b/dependencies/forge-std-1.16.2/src/Script.sol similarity index 91% rename from dependencies/forge-std-1.11.0/src/Script.sol rename to dependencies/forge-std-1.16.2/src/Script.sol index a2e2aa1..d43fa8a 100644 --- a/dependencies/forge-std-1.11.0/src/Script.sol +++ b/dependencies/forge-std-1.16.2/src/Script.sol @@ -1,5 +1,5 @@ -// SPDX-License-Identifier: MIT -pragma solidity >=0.6.2 <0.9.0; +// SPDX-License-Identifier: MIT OR Apache-2.0 +pragma solidity >=0.8.13 <0.9.0; // 💬 ABOUT // Forge Std's default Script. diff --git a/dependencies/forge-std-1.16.2/src/StdAssertions.sol b/dependencies/forge-std-1.16.2/src/StdAssertions.sol new file mode 100644 index 0000000..daad7d9 --- /dev/null +++ b/dependencies/forge-std-1.16.2/src/StdAssertions.sol @@ -0,0 +1,1300 @@ +// SPDX-License-Identifier: MIT OR Apache-2.0 +pragma solidity >=0.8.13 <0.9.0; + +import {Vm} from "./Vm.sol"; + +/// @notice Abstract contract providing assertion utilities for Forge tests. +abstract contract StdAssertions { + Vm private constant vm = Vm(address(uint160(uint256(keccak256("hevm cheat code"))))); + + event log(string); + event logs(bytes); + + event log_address(address); + event log_bytes32(bytes32); + event log_int(int256); + event log_uint(uint256); + event log_bytes(bytes); + event log_string(string); + + event log_named_address(string key, address val); + event log_named_bytes32(string key, bytes32 val); + event log_named_decimal_int(string key, int256 val, uint256 decimals); + event log_named_decimal_uint(string key, uint256 val, uint256 decimals); + event log_named_int(string key, int256 val); + event log_named_uint(string key, uint256 val); + event log_named_bytes(string key, bytes val); + event log_named_string(string key, string val); + + event log_array(uint256[] val); + event log_array(int256[] val); + event log_array(address[] val); + event log_named_array(string key, uint256[] val); + event log_named_array(string key, int256[] val); + event log_named_array(string key, address[] val); + + bytes32 private constant _FAILED_SLOT = bytes32("failed"); + + bool private _failed; + + /// @notice Returns true if any test assertion has failed. + /// @return True if any assertion has failed, false otherwise. + function failed() public view returns (bool) { + if (_failed) { + return true; + } else { + return vm.load(address(vm), _FAILED_SLOT) != bytes32(0); + } + } + + /// @notice Marks the test as failed and records the failure in storage. + function fail() internal virtual { + vm.store(address(vm), _FAILED_SLOT, bytes32(uint256(1))); + _failed = true; + } + + /// @notice Marks the test as failed with a custom message. + /// @param message The failure message to display. + function fail(string memory message) internal virtual { + fail(); + vm.assertTrue(false, message); + } + + /// @notice Asserts that `data` is true. + /// @param data The boolean value to assert. + function assertTrue(bool data) internal pure virtual { + if (!data) { + vm.assertTrue(data); + } + } + + /// @notice Asserts that `data` is true with a custom error message. + /// @param data The boolean value to assert. + /// @param err The error message on failure. + function assertTrue(bool data, string memory err) internal pure virtual { + if (!data) { + vm.assertTrue(data, err); + } + } + + /// @notice Asserts that `data` is false. + /// @param data The boolean value to assert. + function assertFalse(bool data) internal pure virtual { + if (data) { + vm.assertFalse(data); + } + } + + /// @notice Asserts that `data` is false with a custom error message. + /// @param data The boolean value to assert. + /// @param err The error message on failure. + function assertFalse(bool data, string memory err) internal pure virtual { + if (data) { + vm.assertFalse(data, err); + } + } + + /// @notice Asserts that `left` is equal to `right`. + /// @param left The left-hand side value. + /// @param right The right-hand side value. + function assertEq(bool left, bool right) internal pure virtual { + if (left != right) { + vm.assertEq(left, right); + } + } + + /// @notice Asserts that `left` is equal to `right` with a custom error message. + /// @param left The left-hand side value. + /// @param right The right-hand side value. + /// @param err The error message on failure. + function assertEq(bool left, bool right, string memory err) internal pure virtual { + if (left != right) { + vm.assertEq(left, right, err); + } + } + + /// @notice Asserts that `left` is equal to `right`. + /// @param left The left-hand side value. + /// @param right The right-hand side value. + function assertEq(uint256 left, uint256 right) internal pure virtual { + if (left != right) { + vm.assertEq(left, right); + } + } + + /// @notice Asserts that `left` is equal to `right` with a custom error message. + /// @param left The left-hand side value. + /// @param right The right-hand side value. + /// @param err The error message on failure. + function assertEq(uint256 left, uint256 right, string memory err) internal pure virtual { + if (left != right) { + vm.assertEq(left, right, err); + } + } + + /// @notice Asserts that `left` is equal to `right`, formatting values with `decimals` decimal places on failure. + /// @param left The left-hand side value. + /// @param right The right-hand side value. + /// @param decimals The number of decimals for formatting. + function assertEqDecimal(uint256 left, uint256 right, uint256 decimals) internal pure virtual { + vm.assertEqDecimal(left, right, decimals); + } + + /// @notice Asserts that `left` is equal to `right`, formatting values with `decimals` decimal places on failure, with a custom error message. + /// @param left The left-hand side value. + /// @param right The right-hand side value. + /// @param decimals The number of decimals for formatting. + /// @param err The error message on failure. + function assertEqDecimal(uint256 left, uint256 right, uint256 decimals, string memory err) internal pure virtual { + vm.assertEqDecimal(left, right, decimals, err); + } + + /// @notice Asserts that `left` is equal to `right`. + /// @param left The left-hand side value. + /// @param right The right-hand side value. + function assertEq(int256 left, int256 right) internal pure virtual { + if (left != right) { + vm.assertEq(left, right); + } + } + + /// @notice Asserts that `left` is equal to `right` with a custom error message. + /// @param left The left-hand side value. + /// @param right The right-hand side value. + /// @param err The error message on failure. + function assertEq(int256 left, int256 right, string memory err) internal pure virtual { + if (left != right) { + vm.assertEq(left, right, err); + } + } + + /// @notice Asserts that `left` is equal to `right`, formatting values with `decimals` decimal places on failure. + /// @param left The left-hand side value. + /// @param right The right-hand side value. + /// @param decimals The number of decimals for formatting. + function assertEqDecimal(int256 left, int256 right, uint256 decimals) internal pure virtual { + vm.assertEqDecimal(left, right, decimals); + } + + /// @notice Asserts that `left` is equal to `right`, formatting values with `decimals` decimal places on failure, with a custom error message. + /// @param left The left-hand side value. + /// @param right The right-hand side value. + /// @param decimals The number of decimals for formatting. + /// @param err The error message on failure. + function assertEqDecimal(int256 left, int256 right, uint256 decimals, string memory err) internal pure virtual { + vm.assertEqDecimal(left, right, decimals, err); + } + + /// @notice Asserts that `left` is equal to `right`. + /// @param left The left-hand side value. + /// @param right The right-hand side value. + function assertEq(address left, address right) internal pure virtual { + if (left != right) { + vm.assertEq(left, right); + } + } + + /// @notice Asserts that `left` is equal to `right` with a custom error message. + /// @param left The left-hand side value. + /// @param right The right-hand side value. + /// @param err The error message on failure. + function assertEq(address left, address right, string memory err) internal pure virtual { + if (left != right) { + vm.assertEq(left, right, err); + } + } + + /// @notice Asserts that `left` is equal to `right`. + /// @param left The left-hand side value. + /// @param right The right-hand side value. + function assertEq(bytes32 left, bytes32 right) internal pure virtual { + if (left != right) { + vm.assertEq(left, right); + } + } + + /// @notice Asserts that `left` is equal to `right` with a custom error message. + /// @param left The left-hand side value. + /// @param right The right-hand side value. + /// @param err The error message on failure. + function assertEq(bytes32 left, bytes32 right, string memory err) internal pure virtual { + if (left != right) { + vm.assertEq(left, right, err); + } + } + + /// @notice Asserts that `left` is equal to `right` (legacy bytes32 variant). + /// @dev Alias for assertEq(bytes32,bytes32) kept for backwards-compatibility. + /// @param left The left-hand side value. + /// @param right The right-hand side value. + function assertEq32(bytes32 left, bytes32 right) internal pure virtual { + if (left != right) { + vm.assertEq(left, right); + } + } + + /// @notice Asserts that `left` is equal to `right` with a custom error message (legacy bytes32 variant). + /// @dev Alias for assertEq(bytes32,bytes32,string) kept for backwards-compatibility. + /// @param left The left-hand side value. + /// @param right The right-hand side value. + /// @param err The error message on failure. + function assertEq32(bytes32 left, bytes32 right, string memory err) internal pure virtual { + if (left != right) { + vm.assertEq(left, right, err); + } + } + + /// @notice Asserts that `left` is equal to `right`. + /// @param left The left-hand side value. + /// @param right The right-hand side value. + function assertEq(string memory left, string memory right) internal pure virtual { + vm.assertEq(left, right); + } + + /// @notice Asserts that `left` is equal to `right` with a custom error message. + /// @param left The left-hand side value. + /// @param right The right-hand side value. + /// @param err The error message on failure. + function assertEq(string memory left, string memory right, string memory err) internal pure virtual { + vm.assertEq(left, right, err); + } + + /// @notice Asserts that `left` is equal to `right`. + /// @param left The left-hand side value. + /// @param right The right-hand side value. + function assertEq(bytes memory left, bytes memory right) internal pure virtual { + vm.assertEq(left, right); + } + + /// @notice Asserts that `left` is equal to `right` with a custom error message. + /// @param left The left-hand side value. + /// @param right The right-hand side value. + /// @param err The error message on failure. + function assertEq(bytes memory left, bytes memory right, string memory err) internal pure virtual { + vm.assertEq(left, right, err); + } + + /// @notice Asserts that `left` is equal to `right`. + /// @param left The left-hand side value. + /// @param right The right-hand side value. + function assertEq(bool[] memory left, bool[] memory right) internal pure virtual { + vm.assertEq(left, right); + } + + /// @notice Asserts that `left` is equal to `right` with a custom error message. + /// @param left The left-hand side value. + /// @param right The right-hand side value. + /// @param err The error message on failure. + function assertEq(bool[] memory left, bool[] memory right, string memory err) internal pure virtual { + vm.assertEq(left, right, err); + } + + /// @notice Asserts that `left` is equal to `right`. + /// @param left The left-hand side value. + /// @param right The right-hand side value. + function assertEq(uint256[] memory left, uint256[] memory right) internal pure virtual { + vm.assertEq(left, right); + } + + /// @notice Asserts that `left` is equal to `right` with a custom error message. + /// @param left The left-hand side value. + /// @param right The right-hand side value. + /// @param err The error message on failure. + function assertEq(uint256[] memory left, uint256[] memory right, string memory err) internal pure virtual { + vm.assertEq(left, right, err); + } + + /// @notice Asserts that `left` is equal to `right`. + /// @param left The left-hand side value. + /// @param right The right-hand side value. + function assertEq(int256[] memory left, int256[] memory right) internal pure virtual { + vm.assertEq(left, right); + } + + /// @notice Asserts that `left` is equal to `right` with a custom error message. + /// @param left The left-hand side value. + /// @param right The right-hand side value. + /// @param err The error message on failure. + function assertEq(int256[] memory left, int256[] memory right, string memory err) internal pure virtual { + vm.assertEq(left, right, err); + } + + /// @notice Asserts that `left` is equal to `right`. + /// @param left The left-hand side value. + /// @param right The right-hand side value. + function assertEq(address[] memory left, address[] memory right) internal pure virtual { + vm.assertEq(left, right); + } + + /// @notice Asserts that `left` is equal to `right` with a custom error message. + /// @param left The left-hand side value. + /// @param right The right-hand side value. + /// @param err The error message on failure. + function assertEq(address[] memory left, address[] memory right, string memory err) internal pure virtual { + vm.assertEq(left, right, err); + } + + /// @notice Asserts that `left` is equal to `right`. + /// @param left The left-hand side value. + /// @param right The right-hand side value. + function assertEq(bytes32[] memory left, bytes32[] memory right) internal pure virtual { + vm.assertEq(left, right); + } + + /// @notice Asserts that `left` is equal to `right` with a custom error message. + /// @param left The left-hand side value. + /// @param right The right-hand side value. + /// @param err The error message on failure. + function assertEq(bytes32[] memory left, bytes32[] memory right, string memory err) internal pure virtual { + vm.assertEq(left, right, err); + } + + /// @notice Asserts that `left` is equal to `right`. + /// @param left The left-hand side value. + /// @param right The right-hand side value. + function assertEq(string[] memory left, string[] memory right) internal pure virtual { + vm.assertEq(left, right); + } + + /// @notice Asserts that `left` is equal to `right` with a custom error message. + /// @param left The left-hand side value. + /// @param right The right-hand side value. + /// @param err The error message on failure. + function assertEq(string[] memory left, string[] memory right, string memory err) internal pure virtual { + vm.assertEq(left, right, err); + } + + /// @notice Asserts that `left` is equal to `right`. + /// @param left The left-hand side value. + /// @param right The right-hand side value. + function assertEq(bytes[] memory left, bytes[] memory right) internal pure virtual { + vm.assertEq(left, right); + } + + /// @notice Asserts that `left` is equal to `right` with a custom error message. + /// @param left The left-hand side value. + /// @param right The right-hand side value. + /// @param err The error message on failure. + function assertEq(bytes[] memory left, bytes[] memory right, string memory err) internal pure virtual { + vm.assertEq(left, right, err); + } + + // Legacy helper + /// @notice Asserts that `left` is equal to `right` (legacy uint256 variant). + /// @dev Legacy helper kept for backwards-compatibility. + /// @param left The left-hand side value. + /// @param right The right-hand side value. + function assertEqUint(uint256 left, uint256 right) internal pure virtual { + assertEq(left, right); + } + + /// @notice Asserts that `left` is not equal to `right`. + /// @param left The left-hand side value. + /// @param right The right-hand side value. + function assertNotEq(bool left, bool right) internal pure virtual { + if (left == right) { + vm.assertNotEq(left, right); + } + } + + /// @notice Asserts that `left` is not equal to `right` with a custom error message. + /// @param left The left-hand side value. + /// @param right The right-hand side value. + /// @param err The error message on failure. + function assertNotEq(bool left, bool right, string memory err) internal pure virtual { + if (left == right) { + vm.assertNotEq(left, right, err); + } + } + + /// @notice Asserts that `left` is not equal to `right`. + /// @param left The left-hand side value. + /// @param right The right-hand side value. + function assertNotEq(uint256 left, uint256 right) internal pure virtual { + if (left == right) { + vm.assertNotEq(left, right); + } + } + + /// @notice Asserts that `left` is not equal to `right` with a custom error message. + /// @param left The left-hand side value. + /// @param right The right-hand side value. + /// @param err The error message on failure. + function assertNotEq(uint256 left, uint256 right, string memory err) internal pure virtual { + if (left == right) { + vm.assertNotEq(left, right, err); + } + } + + /// @notice Asserts that `left` is not equal to `right`, formatting values with `decimals` decimal places on failure. + /// @param left The left-hand side value. + /// @param right The right-hand side value. + /// @param decimals The number of decimals for formatting. + function assertNotEqDecimal(uint256 left, uint256 right, uint256 decimals) internal pure virtual { + vm.assertNotEqDecimal(left, right, decimals); + } + + /// @notice Asserts that `left` is not equal to `right`, formatting values with `decimals` decimal places on failure, with a custom error message. + /// @param left The left-hand side value. + /// @param right The right-hand side value. + /// @param decimals The number of decimals for formatting. + /// @param err The error message on failure. + function assertNotEqDecimal(uint256 left, uint256 right, uint256 decimals, string memory err) + internal + pure + virtual + { + vm.assertNotEqDecimal(left, right, decimals, err); + } + + /// @notice Asserts that `left` is not equal to `right`. + /// @param left The left-hand side value. + /// @param right The right-hand side value. + function assertNotEq(int256 left, int256 right) internal pure virtual { + if (left == right) { + vm.assertNotEq(left, right); + } + } + + /// @notice Asserts that `left` is not equal to `right` with a custom error message. + /// @param left The left-hand side value. + /// @param right The right-hand side value. + /// @param err The error message on failure. + function assertNotEq(int256 left, int256 right, string memory err) internal pure virtual { + if (left == right) { + vm.assertNotEq(left, right, err); + } + } + + /// @notice Asserts that `left` is not equal to `right`, formatting values with `decimals` decimal places on failure. + /// @param left The left-hand side value. + /// @param right The right-hand side value. + /// @param decimals The number of decimals for formatting. + function assertNotEqDecimal(int256 left, int256 right, uint256 decimals) internal pure virtual { + vm.assertNotEqDecimal(left, right, decimals); + } + + /// @notice Asserts that `left` is not equal to `right`, formatting values with `decimals` decimal places on failure, with a custom error message. + /// @param left The left-hand side value. + /// @param right The right-hand side value. + /// @param decimals The number of decimals for formatting. + /// @param err The error message on failure. + function assertNotEqDecimal(int256 left, int256 right, uint256 decimals, string memory err) internal pure virtual { + vm.assertNotEqDecimal(left, right, decimals, err); + } + + /// @notice Asserts that `left` is not equal to `right`. + /// @param left The left-hand side value. + /// @param right The right-hand side value. + function assertNotEq(address left, address right) internal pure virtual { + if (left == right) { + vm.assertNotEq(left, right); + } + } + + /// @notice Asserts that `left` is not equal to `right` with a custom error message. + /// @param left The left-hand side value. + /// @param right The right-hand side value. + /// @param err The error message on failure. + function assertNotEq(address left, address right, string memory err) internal pure virtual { + if (left == right) { + vm.assertNotEq(left, right, err); + } + } + + /// @notice Asserts that `left` is not equal to `right`. + /// @param left The left-hand side value. + /// @param right The right-hand side value. + function assertNotEq(bytes32 left, bytes32 right) internal pure virtual { + if (left == right) { + vm.assertNotEq(left, right); + } + } + + /// @notice Asserts that `left` is not equal to `right` with a custom error message. + /// @param left The left-hand side value. + /// @param right The right-hand side value. + /// @param err The error message on failure. + function assertNotEq(bytes32 left, bytes32 right, string memory err) internal pure virtual { + if (left == right) { + vm.assertNotEq(left, right, err); + } + } + + /// @notice Asserts that `left` is not equal to `right` (legacy bytes32 variant). + /// @dev Alias for assertNotEq(bytes32,bytes32) kept for backwards-compatibility. + /// @param left The left-hand side value. + /// @param right The right-hand side value. + function assertNotEq32(bytes32 left, bytes32 right) internal pure virtual { + if (left == right) { + vm.assertNotEq(left, right); + } + } + + /// @notice Asserts that `left` is not equal to `right` with a custom error message (legacy bytes32 variant). + /// @dev Alias for assertNotEq(bytes32,bytes32,string) kept for backwards-compatibility. + /// @param left The left-hand side value. + /// @param right The right-hand side value. + /// @param err The error message on failure. + function assertNotEq32(bytes32 left, bytes32 right, string memory err) internal pure virtual { + if (left == right) { + vm.assertNotEq(left, right, err); + } + } + + /// @notice Asserts that `left` is not equal to `right`. + /// @param left The left-hand side value. + /// @param right The right-hand side value. + function assertNotEq(string memory left, string memory right) internal pure virtual { + vm.assertNotEq(left, right); + } + + /// @notice Asserts that `left` is not equal to `right` with a custom error message. + /// @param left The left-hand side value. + /// @param right The right-hand side value. + /// @param err The error message on failure. + function assertNotEq(string memory left, string memory right, string memory err) internal pure virtual { + vm.assertNotEq(left, right, err); + } + + /// @notice Asserts that `left` is not equal to `right`. + /// @param left The left-hand side value. + /// @param right The right-hand side value. + function assertNotEq(bytes memory left, bytes memory right) internal pure virtual { + vm.assertNotEq(left, right); + } + + /// @notice Asserts that `left` is not equal to `right` with a custom error message. + /// @param left The left-hand side value. + /// @param right The right-hand side value. + /// @param err The error message on failure. + function assertNotEq(bytes memory left, bytes memory right, string memory err) internal pure virtual { + vm.assertNotEq(left, right, err); + } + + /// @notice Asserts that `left` is not equal to `right`. + /// @param left The left-hand side value. + /// @param right The right-hand side value. + function assertNotEq(bool[] memory left, bool[] memory right) internal pure virtual { + vm.assertNotEq(left, right); + } + + /// @notice Asserts that `left` is not equal to `right` with a custom error message. + /// @param left The left-hand side value. + /// @param right The right-hand side value. + /// @param err The error message on failure. + function assertNotEq(bool[] memory left, bool[] memory right, string memory err) internal pure virtual { + vm.assertNotEq(left, right, err); + } + + /// @notice Asserts that `left` is not equal to `right`. + /// @param left The left-hand side value. + /// @param right The right-hand side value. + function assertNotEq(uint256[] memory left, uint256[] memory right) internal pure virtual { + vm.assertNotEq(left, right); + } + + /// @notice Asserts that `left` is not equal to `right` with a custom error message. + /// @param left The left-hand side value. + /// @param right The right-hand side value. + /// @param err The error message on failure. + function assertNotEq(uint256[] memory left, uint256[] memory right, string memory err) internal pure virtual { + vm.assertNotEq(left, right, err); + } + + /// @notice Asserts that `left` is not equal to `right`. + /// @param left The left-hand side value. + /// @param right The right-hand side value. + function assertNotEq(int256[] memory left, int256[] memory right) internal pure virtual { + vm.assertNotEq(left, right); + } + + /// @notice Asserts that `left` is not equal to `right` with a custom error message. + /// @param left The left-hand side value. + /// @param right The right-hand side value. + /// @param err The error message on failure. + function assertNotEq(int256[] memory left, int256[] memory right, string memory err) internal pure virtual { + vm.assertNotEq(left, right, err); + } + + /// @notice Asserts that `left` is not equal to `right`. + /// @param left The left-hand side value. + /// @param right The right-hand side value. + function assertNotEq(address[] memory left, address[] memory right) internal pure virtual { + vm.assertNotEq(left, right); + } + + /// @notice Asserts that `left` is not equal to `right` with a custom error message. + /// @param left The left-hand side value. + /// @param right The right-hand side value. + /// @param err The error message on failure. + function assertNotEq(address[] memory left, address[] memory right, string memory err) internal pure virtual { + vm.assertNotEq(left, right, err); + } + + /// @notice Asserts that `left` is not equal to `right`. + /// @param left The left-hand side value. + /// @param right The right-hand side value. + function assertNotEq(bytes32[] memory left, bytes32[] memory right) internal pure virtual { + vm.assertNotEq(left, right); + } + + /// @notice Asserts that `left` is not equal to `right` with a custom error message. + /// @param left The left-hand side value. + /// @param right The right-hand side value. + /// @param err The error message on failure. + function assertNotEq(bytes32[] memory left, bytes32[] memory right, string memory err) internal pure virtual { + vm.assertNotEq(left, right, err); + } + + /// @notice Asserts that `left` is not equal to `right`. + /// @param left The left-hand side value. + /// @param right The right-hand side value. + function assertNotEq(string[] memory left, string[] memory right) internal pure virtual { + vm.assertNotEq(left, right); + } + + /// @notice Asserts that `left` is not equal to `right` with a custom error message. + /// @param left The left-hand side value. + /// @param right The right-hand side value. + /// @param err The error message on failure. + function assertNotEq(string[] memory left, string[] memory right, string memory err) internal pure virtual { + vm.assertNotEq(left, right, err); + } + + /// @notice Asserts that `left` is not equal to `right`. + /// @param left The left-hand side value. + /// @param right The right-hand side value. + function assertNotEq(bytes[] memory left, bytes[] memory right) internal pure virtual { + vm.assertNotEq(left, right); + } + + /// @notice Asserts that `left` is not equal to `right` with a custom error message. + /// @param left The left-hand side value. + /// @param right The right-hand side value. + /// @param err The error message on failure. + function assertNotEq(bytes[] memory left, bytes[] memory right, string memory err) internal pure virtual { + vm.assertNotEq(left, right, err); + } + + /// @notice Asserts that `left` is strictly less than `right`. + /// @param left The left-hand side value. + /// @param right The right-hand side value. + function assertLt(uint256 left, uint256 right) internal pure virtual { + if (left >= right) { + vm.assertLt(left, right); + } + } + + /// @notice Asserts that `left` is strictly less than `right` with a custom error message. + /// @param left The left-hand side value. + /// @param right The right-hand side value. + /// @param err The error message on failure. + function assertLt(uint256 left, uint256 right, string memory err) internal pure virtual { + if (left >= right) { + vm.assertLt(left, right, err); + } + } + + /// @notice Asserts that `left` is strictly less than `right`, formatting values with `decimals` decimal places on failure. + /// @param left The left-hand side value. + /// @param right The right-hand side value. + /// @param decimals The number of decimals for formatting. + function assertLtDecimal(uint256 left, uint256 right, uint256 decimals) internal pure virtual { + vm.assertLtDecimal(left, right, decimals); + } + + /// @notice Asserts that `left` is strictly less than `right`, formatting values with `decimals` decimal places on failure, with a custom error message. + /// @param left The left-hand side value. + /// @param right The right-hand side value. + /// @param decimals The number of decimals for formatting. + /// @param err The error message on failure. + function assertLtDecimal(uint256 left, uint256 right, uint256 decimals, string memory err) internal pure virtual { + vm.assertLtDecimal(left, right, decimals, err); + } + + /// @notice Asserts that `left` is strictly less than `right`. + /// @param left The left-hand side value. + /// @param right The right-hand side value. + function assertLt(int256 left, int256 right) internal pure virtual { + if (left >= right) { + vm.assertLt(left, right); + } + } + + /// @notice Asserts that `left` is strictly less than `right` with a custom error message. + /// @param left The left-hand side value. + /// @param right The right-hand side value. + /// @param err The error message on failure. + function assertLt(int256 left, int256 right, string memory err) internal pure virtual { + if (left >= right) { + vm.assertLt(left, right, err); + } + } + + /// @notice Asserts that `left` is strictly less than `right`, formatting values with `decimals` decimal places on failure. + /// @param left The left-hand side value. + /// @param right The right-hand side value. + /// @param decimals The number of decimals for formatting. + function assertLtDecimal(int256 left, int256 right, uint256 decimals) internal pure virtual { + vm.assertLtDecimal(left, right, decimals); + } + + /// @notice Asserts that `left` is strictly less than `right`, formatting values with `decimals` decimal places on failure, with a custom error message. + /// @param left The left-hand side value. + /// @param right The right-hand side value. + /// @param decimals The number of decimals for formatting. + /// @param err The error message on failure. + function assertLtDecimal(int256 left, int256 right, uint256 decimals, string memory err) internal pure virtual { + vm.assertLtDecimal(left, right, decimals, err); + } + + /// @notice Asserts that `left` is strictly greater than `right`. + /// @param left The left-hand side value. + /// @param right The right-hand side value. + function assertGt(uint256 left, uint256 right) internal pure virtual { + if (left <= right) { + vm.assertGt(left, right); + } + } + + /// @notice Asserts that `left` is strictly greater than `right` with a custom error message. + /// @param left The left-hand side value. + /// @param right The right-hand side value. + /// @param err The error message on failure. + function assertGt(uint256 left, uint256 right, string memory err) internal pure virtual { + if (left <= right) { + vm.assertGt(left, right, err); + } + } + + /// @notice Asserts that `left` is strictly greater than `right`, formatting values with `decimals` decimal places on failure. + /// @param left The left-hand side value. + /// @param right The right-hand side value. + /// @param decimals The number of decimals for formatting. + function assertGtDecimal(uint256 left, uint256 right, uint256 decimals) internal pure virtual { + vm.assertGtDecimal(left, right, decimals); + } + + /// @notice Asserts that `left` is strictly greater than `right`, formatting values with `decimals` decimal places on failure, with a custom error message. + /// @param left The left-hand side value. + /// @param right The right-hand side value. + /// @param decimals The number of decimals for formatting. + /// @param err The error message on failure. + function assertGtDecimal(uint256 left, uint256 right, uint256 decimals, string memory err) internal pure virtual { + vm.assertGtDecimal(left, right, decimals, err); + } + + /// @notice Asserts that `left` is strictly greater than `right`. + /// @param left The left-hand side value. + /// @param right The right-hand side value. + function assertGt(int256 left, int256 right) internal pure virtual { + if (left <= right) { + vm.assertGt(left, right); + } + } + + /// @notice Asserts that `left` is strictly greater than `right` with a custom error message. + /// @param left The left-hand side value. + /// @param right The right-hand side value. + /// @param err The error message on failure. + function assertGt(int256 left, int256 right, string memory err) internal pure virtual { + if (left <= right) { + vm.assertGt(left, right, err); + } + } + + /// @notice Asserts that `left` is strictly greater than `right`, formatting values with `decimals` decimal places on failure. + /// @param left The left-hand side value. + /// @param right The right-hand side value. + /// @param decimals The number of decimals for formatting. + function assertGtDecimal(int256 left, int256 right, uint256 decimals) internal pure virtual { + vm.assertGtDecimal(left, right, decimals); + } + + /// @notice Asserts that `left` is strictly greater than `right`, formatting values with `decimals` decimal places on failure, with a custom error message. + /// @param left The left-hand side value. + /// @param right The right-hand side value. + /// @param decimals The number of decimals for formatting. + /// @param err The error message on failure. + function assertGtDecimal(int256 left, int256 right, uint256 decimals, string memory err) internal pure virtual { + vm.assertGtDecimal(left, right, decimals, err); + } + + /// @notice Asserts that `left` is less than or equal to `right`. + /// @param left The left-hand side value. + /// @param right The right-hand side value. + function assertLe(uint256 left, uint256 right) internal pure virtual { + if (left > right) { + vm.assertLe(left, right); + } + } + + /// @notice Asserts that `left` is less than or equal to `right` with a custom error message. + /// @param left The left-hand side value. + /// @param right The right-hand side value. + /// @param err The error message on failure. + function assertLe(uint256 left, uint256 right, string memory err) internal pure virtual { + if (left > right) { + vm.assertLe(left, right, err); + } + } + + /// @notice Asserts that `left` is less than or equal to `right`, formatting values with `decimals` decimal places on failure. + /// @param left The left-hand side value. + /// @param right The right-hand side value. + /// @param decimals The number of decimals for formatting. + function assertLeDecimal(uint256 left, uint256 right, uint256 decimals) internal pure virtual { + vm.assertLeDecimal(left, right, decimals); + } + + /// @notice Asserts that `left` is less than or equal to `right`, formatting values with `decimals` decimal places on failure, with a custom error message. + /// @param left The left-hand side value. + /// @param right The right-hand side value. + /// @param decimals The number of decimals for formatting. + /// @param err The error message on failure. + function assertLeDecimal(uint256 left, uint256 right, uint256 decimals, string memory err) internal pure virtual { + vm.assertLeDecimal(left, right, decimals, err); + } + + /// @notice Asserts that `left` is less than or equal to `right`. + /// @param left The left-hand side value. + /// @param right The right-hand side value. + function assertLe(int256 left, int256 right) internal pure virtual { + if (left > right) { + vm.assertLe(left, right); + } + } + + /// @notice Asserts that `left` is less than or equal to `right` with a custom error message. + /// @param left The left-hand side value. + /// @param right The right-hand side value. + /// @param err The error message on failure. + function assertLe(int256 left, int256 right, string memory err) internal pure virtual { + if (left > right) { + vm.assertLe(left, right, err); + } + } + + /// @notice Asserts that `left` is less than or equal to `right`, formatting values with `decimals` decimal places on failure. + /// @param left The left-hand side value. + /// @param right The right-hand side value. + /// @param decimals The number of decimals for formatting. + function assertLeDecimal(int256 left, int256 right, uint256 decimals) internal pure virtual { + vm.assertLeDecimal(left, right, decimals); + } + + /// @notice Asserts that `left` is less than or equal to `right`, formatting values with `decimals` decimal places on failure, with a custom error message. + /// @param left The left-hand side value. + /// @param right The right-hand side value. + /// @param decimals The number of decimals for formatting. + /// @param err The error message on failure. + function assertLeDecimal(int256 left, int256 right, uint256 decimals, string memory err) internal pure virtual { + vm.assertLeDecimal(left, right, decimals, err); + } + + /// @notice Asserts that `left` is greater than or equal to `right`. + /// @param left The left-hand side value. + /// @param right The right-hand side value. + function assertGe(uint256 left, uint256 right) internal pure virtual { + if (left < right) { + vm.assertGe(left, right); + } + } + + /// @notice Asserts that `left` is greater than or equal to `right` with a custom error message. + /// @param left The left-hand side value. + /// @param right The right-hand side value. + /// @param err The error message on failure. + function assertGe(uint256 left, uint256 right, string memory err) internal pure virtual { + if (left < right) { + vm.assertGe(left, right, err); + } + } + + /// @notice Asserts that `left` is greater than or equal to `right`, formatting values with `decimals` decimal places on failure. + /// @param left The left-hand side value. + /// @param right The right-hand side value. + /// @param decimals The number of decimals for formatting. + function assertGeDecimal(uint256 left, uint256 right, uint256 decimals) internal pure virtual { + vm.assertGeDecimal(left, right, decimals); + } + + /// @notice Asserts that `left` is greater than or equal to `right`, formatting values with `decimals` decimal places on failure, with a custom error message. + /// @param left The left-hand side value. + /// @param right The right-hand side value. + /// @param decimals The number of decimals for formatting. + /// @param err The error message on failure. + function assertGeDecimal(uint256 left, uint256 right, uint256 decimals, string memory err) internal pure virtual { + vm.assertGeDecimal(left, right, decimals, err); + } + + /// @notice Asserts that `left` is greater than or equal to `right`. + /// @param left The left-hand side value. + /// @param right The right-hand side value. + function assertGe(int256 left, int256 right) internal pure virtual { + if (left < right) { + vm.assertGe(left, right); + } + } + + /// @notice Asserts that `left` is greater than or equal to `right` with a custom error message. + /// @param left The left-hand side value. + /// @param right The right-hand side value. + /// @param err The error message on failure. + function assertGe(int256 left, int256 right, string memory err) internal pure virtual { + if (left < right) { + vm.assertGe(left, right, err); + } + } + + /// @notice Asserts that `left` is greater than or equal to `right`, formatting values with `decimals` decimal places on failure. + /// @param left The left-hand side value. + /// @param right The right-hand side value. + /// @param decimals The number of decimals for formatting. + function assertGeDecimal(int256 left, int256 right, uint256 decimals) internal pure virtual { + vm.assertGeDecimal(left, right, decimals); + } + + /// @notice Asserts that `left` is greater than or equal to `right`, formatting values with `decimals` decimal places on failure, with a custom error message. + /// @param left The left-hand side value. + /// @param right The right-hand side value. + /// @param decimals The number of decimals for formatting. + /// @param err The error message on failure. + function assertGeDecimal(int256 left, int256 right, uint256 decimals, string memory err) internal pure virtual { + vm.assertGeDecimal(left, right, decimals, err); + } + + /// @notice Asserts that the absolute difference between `left` and `right` is at most `maxDelta`. + /// @param left The left-hand side value. + /// @param right The right-hand side value. + /// @param maxDelta The maximum absolute difference allowed. + function assertApproxEqAbs(uint256 left, uint256 right, uint256 maxDelta) internal pure virtual { + vm.assertApproxEqAbs(left, right, maxDelta); + } + + /// @notice Asserts that the absolute difference between `left` and `right` is at most `maxDelta` with a custom error message. + /// @param left The left-hand side value. + /// @param right The right-hand side value. + /// @param maxDelta The maximum absolute difference allowed. + /// @param err The error message on failure. + function assertApproxEqAbs(uint256 left, uint256 right, uint256 maxDelta, string memory err) internal pure virtual { + vm.assertApproxEqAbs(left, right, maxDelta, err); + } + + /// @notice Asserts that the absolute difference between `left` and `right` is at most `maxDelta`, formatting values with `decimals` decimal places on failure. + /// @param left The left-hand side value. + /// @param right The right-hand side value. + /// @param maxDelta The maximum absolute difference allowed. + /// @param decimals The number of decimals for formatting. + function assertApproxEqAbsDecimal(uint256 left, uint256 right, uint256 maxDelta, uint256 decimals) + internal + pure + virtual + { + vm.assertApproxEqAbsDecimal(left, right, maxDelta, decimals); + } + + /// @notice Asserts that the absolute difference between `left` and `right` is at most `maxDelta`, formatting values with `decimals` decimal places on failure, with a custom error message. + /// @param left The left-hand side value. + /// @param right The right-hand side value. + /// @param maxDelta The maximum absolute difference allowed. + /// @param decimals The number of decimals for formatting. + /// @param err The error message on failure. + function assertApproxEqAbsDecimal( + uint256 left, + uint256 right, + uint256 maxDelta, + uint256 decimals, + string memory err + ) internal pure virtual { + vm.assertApproxEqAbsDecimal(left, right, maxDelta, decimals, err); + } + + /// @notice Asserts that the absolute difference between `left` and `right` is at most `maxDelta`. + /// @param left The left-hand side value. + /// @param right The right-hand side value. + /// @param maxDelta The maximum absolute difference allowed. + function assertApproxEqAbs(int256 left, int256 right, uint256 maxDelta) internal pure virtual { + vm.assertApproxEqAbs(left, right, maxDelta); + } + + /// @notice Asserts that the absolute difference between `left` and `right` is at most `maxDelta` with a custom error message. + /// @param left The left-hand side value. + /// @param right The right-hand side value. + /// @param maxDelta The maximum absolute difference allowed. + /// @param err The error message on failure. + function assertApproxEqAbs(int256 left, int256 right, uint256 maxDelta, string memory err) internal pure virtual { + vm.assertApproxEqAbs(left, right, maxDelta, err); + } + + /// @notice Asserts that the absolute difference between `left` and `right` is at most `maxDelta`, formatting values with `decimals` decimal places on failure. + /// @param left The left-hand side value. + /// @param right The right-hand side value. + /// @param maxDelta The maximum absolute difference allowed. + /// @param decimals The number of decimals for formatting. + function assertApproxEqAbsDecimal(int256 left, int256 right, uint256 maxDelta, uint256 decimals) + internal + pure + virtual + { + vm.assertApproxEqAbsDecimal(left, right, maxDelta, decimals); + } + + /// @notice Asserts that the absolute difference between `left` and `right` is at most `maxDelta`, formatting values with `decimals` decimal places on failure, with a custom error message. + /// @param left The left-hand side value. + /// @param right The right-hand side value. + /// @param maxDelta The maximum absolute difference allowed. + /// @param decimals The number of decimals for formatting. + /// @param err The error message on failure. + function assertApproxEqAbsDecimal(int256 left, int256 right, uint256 maxDelta, uint256 decimals, string memory err) + internal + pure + virtual + { + vm.assertApproxEqAbsDecimal(left, right, maxDelta, decimals, err); + } + + /// @notice Asserts that the relative difference between `left` and `right` is at most `maxPercentDelta`. + /// @param left The left-hand side value. + /// @param right The right-hand side value. + /// @param maxPercentDelta The maximum relative delta allowed, as an 18 decimal fixed point number where 1e18 == 100%. + function assertApproxEqRel( + uint256 left, + uint256 right, + uint256 maxPercentDelta // An 18 decimal fixed point number, where 1e18 == 100% + ) + internal + pure + virtual + { + vm.assertApproxEqRel(left, right, maxPercentDelta); + } + + /// @notice Asserts that the relative difference between `left` and `right` is at most `maxPercentDelta` with a custom error message. + /// @param left The left-hand side value. + /// @param right The right-hand side value. + /// @param maxPercentDelta The maximum relative delta allowed, as an 18 decimal fixed point number where 1e18 == 100%. + /// @param err The error message on failure. + function assertApproxEqRel( + uint256 left, + uint256 right, + uint256 maxPercentDelta, // An 18 decimal fixed point number, where 1e18 == 100% + string memory err + ) + internal + pure + virtual + { + vm.assertApproxEqRel(left, right, maxPercentDelta, err); + } + + /// @notice Asserts that the relative difference between `left` and `right` is at most `maxPercentDelta`, formatting values with `decimals` decimal places on failure. + /// @param left The left-hand side value. + /// @param right The right-hand side value. + /// @param maxPercentDelta The maximum relative delta allowed, as an 18 decimal fixed point number where 1e18 == 100%. + /// @param decimals The number of decimals for formatting. + function assertApproxEqRelDecimal( + uint256 left, + uint256 right, + uint256 maxPercentDelta, // An 18 decimal fixed point number, where 1e18 == 100% + uint256 decimals + ) + internal + pure + virtual + { + vm.assertApproxEqRelDecimal(left, right, maxPercentDelta, decimals); + } + + /// @notice Asserts that the relative difference between `left` and `right` is at most `maxPercentDelta`, formatting values with `decimals` decimal places on failure, with a custom error message. + /// @param left The left-hand side value. + /// @param right The right-hand side value. + /// @param maxPercentDelta The maximum relative delta allowed, as an 18 decimal fixed point number where 1e18 == 100%. + /// @param decimals The number of decimals for formatting. + /// @param err The error message on failure. + function assertApproxEqRelDecimal( + uint256 left, + uint256 right, + uint256 maxPercentDelta, // An 18 decimal fixed point number, where 1e18 == 100% + uint256 decimals, + string memory err + ) internal pure virtual { + vm.assertApproxEqRelDecimal(left, right, maxPercentDelta, decimals, err); + } + + /// @notice Asserts that the relative difference between `left` and `right` is at most `maxPercentDelta`. + /// @param left The left-hand side value. + /// @param right The right-hand side value. + /// @param maxPercentDelta The maximum relative delta allowed, as an 18 decimal fixed point number where 1e18 == 100%. + function assertApproxEqRel(int256 left, int256 right, uint256 maxPercentDelta) internal pure virtual { + vm.assertApproxEqRel(left, right, maxPercentDelta); + } + + /// @notice Asserts that the relative difference between `left` and `right` is at most `maxPercentDelta` with a custom error message. + /// @param left The left-hand side value. + /// @param right The right-hand side value. + /// @param maxPercentDelta The maximum relative delta allowed, as an 18 decimal fixed point number where 1e18 == 100%. + /// @param err The error message on failure. + function assertApproxEqRel( + int256 left, + int256 right, + uint256 maxPercentDelta, // An 18 decimal fixed point number, where 1e18 == 100% + string memory err + ) + internal + pure + virtual + { + vm.assertApproxEqRel(left, right, maxPercentDelta, err); + } + + /// @notice Asserts that the relative difference between `left` and `right` is at most `maxPercentDelta`, formatting values with `decimals` decimal places on failure. + /// @param left The left-hand side value. + /// @param right The right-hand side value. + /// @param maxPercentDelta The maximum relative delta allowed, as an 18 decimal fixed point number where 1e18 == 100%. + /// @param decimals The number of decimals for formatting. + function assertApproxEqRelDecimal( + int256 left, + int256 right, + uint256 maxPercentDelta, // An 18 decimal fixed point number, where 1e18 == 100% + uint256 decimals + ) + internal + pure + virtual + { + vm.assertApproxEqRelDecimal(left, right, maxPercentDelta, decimals); + } + + /// @notice Asserts that the relative difference between `left` and `right` is at most `maxPercentDelta`, formatting values with `decimals` decimal places on failure, with a custom error message. + /// @param left The left-hand side value. + /// @param right The right-hand side value. + /// @param maxPercentDelta The maximum relative delta allowed, as an 18 decimal fixed point number where 1e18 == 100%. + /// @param decimals The number of decimals for formatting. + /// @param err The error message on failure. + function assertApproxEqRelDecimal( + int256 left, + int256 right, + uint256 maxPercentDelta, // An 18 decimal fixed point number, where 1e18 == 100% + uint256 decimals, + string memory err + ) internal pure virtual { + vm.assertApproxEqRelDecimal(left, right, maxPercentDelta, decimals, err); + } + + // Inherited from DSTest, not used but kept for backwards-compatibility + /// @notice Returns true if `left` and `right` have equal content. + /// @dev Inherited from DSTest, kept for backwards-compatibility. + /// @param left The left-hand side bytes. + /// @param right The right-hand side bytes. + /// @return True if the byte content is equal, false otherwise. + function checkEq0(bytes memory left, bytes memory right) internal pure returns (bool) { + return keccak256(left) == keccak256(right); + } + + /// @notice Asserts that `left` is equal to `right` (legacy bytes variant). + /// @dev Alias for assertEq(bytes,bytes) kept for backwards-compatibility. + /// @param left The left-hand side bytes. + /// @param right The right-hand side bytes. + function assertEq0(bytes memory left, bytes memory right) internal pure virtual { + assertEq(left, right); + } + + /// @notice Asserts that `left` is equal to `right` with a custom error message (legacy bytes variant). + /// @dev Alias for assertEq(bytes,bytes,string) kept for backwards-compatibility. + /// @param left The left-hand side bytes. + /// @param right The right-hand side bytes. + /// @param err The error message on failure. + function assertEq0(bytes memory left, bytes memory right, string memory err) internal pure virtual { + assertEq(left, right, err); + } + + /// @notice Asserts that `left` is not equal to `right` (legacy bytes variant). + /// @dev Alias for assertNotEq(bytes,bytes) kept for backwards-compatibility. + /// @param left The left-hand side bytes. + /// @param right The right-hand side bytes. + function assertNotEq0(bytes memory left, bytes memory right) internal pure virtual { + assertNotEq(left, right); + } + + /// @notice Asserts that `left` is not equal to `right` with a custom error message (legacy bytes variant). + /// @dev Alias for assertNotEq(bytes,bytes,string) kept for backwards-compatibility. + /// @param left The left-hand side bytes. + /// @param right The right-hand side bytes. + /// @param err The error message on failure. + function assertNotEq0(bytes memory left, bytes memory right, string memory err) internal pure virtual { + assertNotEq(left, right, err); + } + + /// @notice Asserts that two calls to the same target with different calldata produce equal return or revert data. + /// @param target The contract address to call. + /// @param callDataA The calldata for the first call. + /// @param callDataB The calldata for the second call. + function assertEqCall(address target, bytes memory callDataA, bytes memory callDataB) internal virtual { + assertEqCall(target, callDataA, target, callDataB, true); + } + + /// @notice Asserts that calls to two different targets produce equal return or revert data. + /// @param targetA The first contract address. + /// @param callDataA The calldata for the first call. + /// @param targetB The second contract address. + /// @param callDataB The calldata for the second call. + function assertEqCall(address targetA, bytes memory callDataA, address targetB, bytes memory callDataB) + internal + virtual + { + assertEqCall(targetA, callDataA, targetB, callDataB, true); + } + + /// @notice Asserts that two calls to the same target with different calldata produce equal return or revert data. + /// @param target The contract address to call. + /// @param callDataA The calldata for the first call. + /// @param callDataB The calldata for the second call. + /// @param strictRevertData If true, also asserts that revert data matches when both calls revert. + function assertEqCall(address target, bytes memory callDataA, bytes memory callDataB, bool strictRevertData) + internal + virtual + { + assertEqCall(target, callDataA, target, callDataB, strictRevertData); + } + + /// @notice Asserts that calls to two targets produce equal return or revert data. + /// @param targetA The first contract address. + /// @param callDataA The calldata for the first call. + /// @param targetB The second contract address. + /// @param callDataB The calldata for the second call. + /// @param strictRevertData If true, also asserts that revert data matches when both calls revert. + function assertEqCall( + address targetA, + bytes memory callDataA, + address targetB, + bytes memory callDataB, + bool strictRevertData + ) internal virtual { + (bool successA, bytes memory returnDataA) = address(targetA).call(callDataA); + (bool successB, bytes memory returnDataB) = address(targetB).call(callDataB); + + if (successA && successB) { + assertEq(returnDataA, returnDataB, "Call return data does not match"); + } + + if (!successA && !successB && strictRevertData) { + assertEq(returnDataA, returnDataB, "Call revert data does not match"); + } + + if (!successA && successB) { + emit log("Error: Calls were not equal"); + emit log_named_bytes(" Left call revert data", returnDataA); + emit log_named_bytes(" Right call return data", returnDataB); + revert("assertion failed"); + } + + if (successA && !successB) { + emit log("Error: Calls were not equal"); + emit log_named_bytes(" Left call return data", returnDataA); + emit log_named_bytes(" Right call revert data", returnDataB); + revert("assertion failed"); + } + } +} diff --git a/dependencies/forge-std-1.11.0/src/StdChains.sol b/dependencies/forge-std-1.16.2/src/StdChains.sol similarity index 52% rename from dependencies/forge-std-1.11.0/src/StdChains.sol rename to dependencies/forge-std-1.16.2/src/StdChains.sol index 3bc5f43..4fed0b5 100644 --- a/dependencies/forge-std-1.11.0/src/StdChains.sol +++ b/dependencies/forge-std-1.16.2/src/StdChains.sol @@ -1,6 +1,5 @@ -// SPDX-License-Identifier: MIT -pragma solidity >=0.6.2 <0.9.0; -pragma experimental ABIEncoderV2; +// SPDX-License-Identifier: MIT OR Apache-2.0 +pragma solidity >=0.8.13 <0.9.0; import {VmSafe} from "./Vm.sol"; @@ -8,9 +7,9 @@ import {VmSafe} from "./Vm.sol"; * StdChains provides information about EVM compatible chains that can be used in scripts/tests. * For each chain, the chain's name, chain ID, and a default RPC URL are provided. Chains are * identified by their alias, which is the same as the alias in the `[rpc_endpoints]` section of - * the `foundry.toml` file. For best UX, ensure the alias in the `foundry.toml` file match the + * the `foundry.toml` file. For best UX, ensure the alias in the `foundry.toml` file matches the * alias used in this contract, which can be found as the first argument to the - * `setChainWithDefaultRpcUrl` call in the `initializeStdChains` function. + * `_setChainWithDefaultRpcUrl` call in the `_initializeStdChains` function. * * There are two main ways to use this contract: * 1. Set a chain with `setChain(string memory chainAlias, ChainData memory chain)` or @@ -18,12 +17,12 @@ import {VmSafe} from "./Vm.sol"; * 2. Get a chain with `getChain(string memory chainAlias)` or `getChain(uint256 chainId)`. * * The first time either of those are used, chains are initialized with the default set of RPC URLs. - * This is done in `initializeStdChains`, which uses `setChainWithDefaultRpcUrl`. Defaults are recorded in - * `defaultRpcUrls`. + * This is done in `_initializeStdChains`, which uses `_setChainWithDefaultRpcUrl`. Defaults are recorded in + * `_defaultRpcUrls`. * * The `setChain` function is straightforward, and it simply saves off the given chain data. * - * The `getChain` methods use `getChainWithUpdatedRpcUrl` to return a chain. For example, let's say + * The `getChain` methods use `_getChainWithUpdatedRpcUrl` to return a chain. For example, let's say * we want to retrieve the RPC URL for `mainnet`: * - If you have specified data with `setChain`, it will return that. * - If you have configured a mainnet RPC URL in `foundry.toml`, it will return the URL, provided it @@ -35,7 +34,7 @@ import {VmSafe} from "./Vm.sol"; abstract contract StdChains { VmSafe private constant vm = VmSafe(address(uint160(uint256(keccak256("hevm cheat code"))))); - bool private stdChainsInitialized; + bool private _stdChainsInitialized; struct ChainData { string name; @@ -58,44 +57,47 @@ abstract contract StdChains { } // Maps from the chain's alias (matching the alias in the `foundry.toml` file) to chain data. - mapping(string => Chain) private chains; - // Maps from the chain's alias to it's default RPC URL. - mapping(string => string) private defaultRpcUrls; - // Maps from a chain ID to it's alias. - mapping(uint256 => string) private idToAlias; + mapping(string => Chain) private _chains; + // Maps from the chain's alias to its default RPC URL. + mapping(string => string) private _defaultRpcUrls; + // Maps from a chain ID to its alias. + mapping(uint256 => string) private _idToAlias; - bool private fallbackToDefaultRpcUrls = true; + bool private _fallbackToDefaultRpcUrls = true; - // The RPC URL will be fetched from config or defaultRpcUrls if possible. + /// @notice Returns chain data for the given alias, with the RPC URL resolved from config or defaults. + /// @dev Reverts if `chainAlias` is empty or has not been registered. function getChain(string memory chainAlias) internal virtual returns (Chain memory chain) { require(bytes(chainAlias).length != 0, "StdChains getChain(string): Chain alias cannot be the empty string."); - initializeStdChains(); - chain = chains[chainAlias]; + _initializeStdChains(); + chain = _chains[chainAlias]; require( chain.chainId != 0, string(abi.encodePacked("StdChains getChain(string): Chain with alias \"", chainAlias, "\" not found.")) ); - chain = getChainWithUpdatedRpcUrl(chainAlias, chain); + chain = _getChainWithUpdatedRpcUrl(chainAlias, chain); } + /// @notice Returns chain data for the given chain ID, with the RPC URL resolved from config or defaults. + /// @dev Reverts if `chainId` is `0` or has not been registered. function getChain(uint256 chainId) internal virtual returns (Chain memory chain) { require(chainId != 0, "StdChains getChain(uint256): Chain ID cannot be 0."); - initializeStdChains(); - string memory chainAlias = idToAlias[chainId]; + _initializeStdChains(); + string memory chainAlias = _idToAlias[chainId]; - chain = chains[chainAlias]; + chain = _chains[chainAlias]; require( chain.chainId != 0, string(abi.encodePacked("StdChains getChain(uint256): Chain with ID ", vm.toString(chainId), " not found.")) ); - chain = getChainWithUpdatedRpcUrl(chainAlias, chain); + chain = _getChainWithUpdatedRpcUrl(chainAlias, chain); } - // set chain info, with priority to argument's rpcUrl field. + /// @notice Registers chain data under `chainAlias`, with priority given to the argument's `rpcUrl` field. function setChain(string memory chainAlias, ChainData memory chain) internal virtual { require( bytes(chainAlias).length != 0, @@ -104,8 +106,8 @@ abstract contract StdChains { require(chain.chainId != 0, "StdChains setChain(string,ChainData): Chain ID cannot be 0."); - initializeStdChains(); - string memory foundAlias = idToAlias[chain.chainId]; + _initializeStdChains(); + string memory foundAlias = _idToAlias[chain.chainId]; require( bytes(foundAlias).length == 0 || keccak256(bytes(foundAlias)) == keccak256(bytes(chainAlias)), @@ -120,15 +122,15 @@ abstract contract StdChains { ) ); - uint256 oldChainId = chains[chainAlias].chainId; - delete idToAlias[oldChainId]; + uint256 oldChainId = _chains[chainAlias].chainId; + delete _idToAlias[oldChainId]; - chains[chainAlias] = + _chains[chainAlias] = Chain({name: chain.name, chainId: chain.chainId, chainAlias: chainAlias, rpcUrl: chain.rpcUrl}); - idToAlias[chain.chainId] = chainAlias; + _idToAlias[chain.chainId] = chainAlias; } - // set chain info, with priority to argument's rpcUrl field. + /// @notice Registers chain data under `chainAlias`, with priority given to the argument's `rpcUrl` field. function setChain(string memory chainAlias, Chain memory chain) internal virtual { setChain(chainAlias, ChainData({name: chain.name, chainId: chain.chainId, rpcUrl: chain.rpcUrl})); } @@ -149,7 +151,7 @@ abstract contract StdChains { // lookup rpcUrl, in descending order of priority: // current -> config (foundry.toml) -> environment variable -> default - function getChainWithUpdatedRpcUrl(string memory chainAlias, Chain memory chain) + function _getChainWithUpdatedRpcUrl(string memory chainAlias, Chain memory chain) private view returns (Chain memory) @@ -159,8 +161,8 @@ abstract contract StdChains { chain.rpcUrl = configRpcUrl; } catch (bytes memory err) { string memory envName = string(abi.encodePacked(_toUpper(chainAlias), "_RPC_URL")); - if (fallbackToDefaultRpcUrls) { - chain.rpcUrl = vm.envOr(envName, defaultRpcUrls[chainAlias]); + if (_fallbackToDefaultRpcUrls) { + chain.rpcUrl = vm.envOr(envName, _defaultRpcUrls[chainAlias]); } else { chain.rpcUrl = vm.envString(envName); } @@ -176,8 +178,7 @@ abstract contract StdChains { (errHash != keccak256(oldNotFoundError) && errHash != keccak256(newNotFoundError)) || bytes(chain.rpcUrl).length == 0 ) { - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { revert(add(32, err), mload(err)) } } @@ -186,100 +187,128 @@ abstract contract StdChains { return chain; } + /// @notice Sets whether to fall back to default RPC URLs when no URL is configured for a chain. function setFallbackToDefaultRpcUrls(bool useDefault) internal { - fallbackToDefaultRpcUrls = useDefault; + _fallbackToDefaultRpcUrls = useDefault; } - function initializeStdChains() private { - if (stdChainsInitialized) return; + function _initializeStdChains() private { + if (_stdChainsInitialized) return; - stdChainsInitialized = true; + _stdChainsInitialized = true; // If adding an RPC here, make sure to test the default RPC URL in `test_Rpcs` in `StdChains.t.sol` - setChainWithDefaultRpcUrl("anvil", ChainData("Anvil", 31337, "http://127.0.0.1:8545")); - setChainWithDefaultRpcUrl("mainnet", ChainData("Mainnet", 1, "https://eth.llamarpc.com")); - setChainWithDefaultRpcUrl( + _setChainWithDefaultRpcUrl("anvil", ChainData("Anvil", 31337, "http://127.0.0.1:8545")); + _setChainWithDefaultRpcUrl("mainnet", ChainData("Mainnet", 1, "https://eth.llamarpc.com")); + _setChainWithDefaultRpcUrl( "sepolia", ChainData("Sepolia", 11155111, "https://sepolia.infura.io/v3/b9794ad1ddf84dfb8c34d6bb5dca2001") ); - setChainWithDefaultRpcUrl("holesky", ChainData("Holesky", 17000, "https://rpc.holesky.ethpandaops.io")); - setChainWithDefaultRpcUrl("hoodi", ChainData("Hoodi", 560048, "https://rpc.hoodi.ethpandaops.io")); - setChainWithDefaultRpcUrl("optimism", ChainData("Optimism", 10, "https://mainnet.optimism.io")); - setChainWithDefaultRpcUrl( + _setChainWithDefaultRpcUrl("holesky", ChainData("Holesky", 17000, "https://rpc.holesky.ethpandaops.io")); + _setChainWithDefaultRpcUrl("hoodi", ChainData("Hoodi", 560048, "https://rpc.hoodi.ethpandaops.io")); + _setChainWithDefaultRpcUrl("optimism", ChainData("Optimism", 10, "https://mainnet.optimism.io")); + _setChainWithDefaultRpcUrl( "optimism_sepolia", ChainData("Optimism Sepolia", 11155420, "https://sepolia.optimism.io") ); - setChainWithDefaultRpcUrl("arbitrum_one", ChainData("Arbitrum One", 42161, "https://arb1.arbitrum.io/rpc")); - setChainWithDefaultRpcUrl( + _setChainWithDefaultRpcUrl("arbitrum_one", ChainData("Arbitrum One", 42161, "https://arb1.arbitrum.io/rpc")); + _setChainWithDefaultRpcUrl( "arbitrum_one_sepolia", ChainData("Arbitrum One Sepolia", 421614, "https://sepolia-rollup.arbitrum.io/rpc") ); - setChainWithDefaultRpcUrl("arbitrum_nova", ChainData("Arbitrum Nova", 42170, "https://nova.arbitrum.io/rpc")); - setChainWithDefaultRpcUrl("polygon", ChainData("Polygon", 137, "https://polygon-rpc.com")); - setChainWithDefaultRpcUrl( + _setChainWithDefaultRpcUrl("arbitrum_nova", ChainData("Arbitrum Nova", 42170, "https://nova.arbitrum.io/rpc")); + _setChainWithDefaultRpcUrl("polygon", ChainData("Polygon", 137, "https://polygon-rpc.com")); + _setChainWithDefaultRpcUrl( "polygon_amoy", ChainData("Polygon Amoy", 80002, "https://rpc-amoy.polygon.technology") ); - setChainWithDefaultRpcUrl("avalanche", ChainData("Avalanche", 43114, "https://api.avax.network/ext/bc/C/rpc")); - setChainWithDefaultRpcUrl( + _setChainWithDefaultRpcUrl("avalanche", ChainData("Avalanche", 43114, "https://api.avax.network/ext/bc/C/rpc")); + _setChainWithDefaultRpcUrl( "avalanche_fuji", ChainData("Avalanche Fuji", 43113, "https://api.avax-test.network/ext/bc/C/rpc") ); - setChainWithDefaultRpcUrl( + _setChainWithDefaultRpcUrl( "bnb_smart_chain", ChainData("BNB Smart Chain", 56, "https://bsc-dataseed1.binance.org") ); - setChainWithDefaultRpcUrl( + _setChainWithDefaultRpcUrl( "bnb_smart_chain_testnet", ChainData("BNB Smart Chain Testnet", 97, "https://rpc.ankr.com/bsc_testnet_chapel") ); - setChainWithDefaultRpcUrl("gnosis_chain", ChainData("Gnosis Chain", 100, "https://rpc.gnosischain.com")); - setChainWithDefaultRpcUrl("moonbeam", ChainData("Moonbeam", 1284, "https://rpc.api.moonbeam.network")); - setChainWithDefaultRpcUrl( + _setChainWithDefaultRpcUrl("gnosis_chain", ChainData("Gnosis Chain", 100, "https://rpc.gnosischain.com")); + _setChainWithDefaultRpcUrl("moonbeam", ChainData("Moonbeam", 1284, "https://rpc.api.moonbeam.network")); + _setChainWithDefaultRpcUrl( "moonriver", ChainData("Moonriver", 1285, "https://rpc.api.moonriver.moonbeam.network") ); - setChainWithDefaultRpcUrl("moonbase", ChainData("Moonbase", 1287, "https://rpc.testnet.moonbeam.network")); - setChainWithDefaultRpcUrl("base_sepolia", ChainData("Base Sepolia", 84532, "https://sepolia.base.org")); - setChainWithDefaultRpcUrl("base", ChainData("Base", 8453, "https://mainnet.base.org")); - setChainWithDefaultRpcUrl("blast_sepolia", ChainData("Blast Sepolia", 168587773, "https://sepolia.blast.io")); - setChainWithDefaultRpcUrl("blast", ChainData("Blast", 81457, "https://rpc.blast.io")); - setChainWithDefaultRpcUrl("fantom_opera", ChainData("Fantom Opera", 250, "https://rpc.ankr.com/fantom/")); - setChainWithDefaultRpcUrl( + _setChainWithDefaultRpcUrl("moonbase", ChainData("Moonbase", 1287, "https://rpc.testnet.moonbeam.network")); + _setChainWithDefaultRpcUrl("base_sepolia", ChainData("Base Sepolia", 84532, "https://sepolia.base.org")); + _setChainWithDefaultRpcUrl("base", ChainData("Base", 8453, "https://mainnet.base.org")); + _setChainWithDefaultRpcUrl("blast_sepolia", ChainData("Blast Sepolia", 168587773, "https://sepolia.blast.io")); + _setChainWithDefaultRpcUrl("blast", ChainData("Blast", 81457, "https://rpc.blast.io")); + _setChainWithDefaultRpcUrl("fantom_opera", ChainData("Fantom Opera", 250, "https://rpc.ankr.com/fantom/")); + _setChainWithDefaultRpcUrl( "fantom_opera_testnet", ChainData("Fantom Opera Testnet", 4002, "https://rpc.ankr.com/fantom_testnet/") ); - setChainWithDefaultRpcUrl("fraxtal", ChainData("Fraxtal", 252, "https://rpc.frax.com")); - setChainWithDefaultRpcUrl("fraxtal_testnet", ChainData("Fraxtal Testnet", 2522, "https://rpc.testnet.frax.com")); - setChainWithDefaultRpcUrl( + _setChainWithDefaultRpcUrl("fraxtal", ChainData("Fraxtal", 252, "https://rpc.frax.com")); + _setChainWithDefaultRpcUrl( + "fraxtal_testnet", ChainData("Fraxtal Testnet", 2522, "https://rpc.testnet.frax.com") + ); + _setChainWithDefaultRpcUrl( "berachain_bartio_testnet", ChainData("Berachain bArtio Testnet", 80084, "https://bartio.rpc.berachain.com") ); - setChainWithDefaultRpcUrl("flare", ChainData("Flare", 14, "https://flare-api.flare.network/ext/C/rpc")); - setChainWithDefaultRpcUrl( + _setChainWithDefaultRpcUrl("flare", ChainData("Flare", 14, "https://flare-api.flare.network/ext/C/rpc")); + _setChainWithDefaultRpcUrl( "flare_coston2", ChainData("Flare Coston2", 114, "https://coston2-api.flare.network/ext/C/rpc") ); - setChainWithDefaultRpcUrl("mode", ChainData("Mode", 34443, "https://mode.drpc.org")); - setChainWithDefaultRpcUrl("mode_sepolia", ChainData("Mode Sepolia", 919, "https://sepolia.mode.network")); + _setChainWithDefaultRpcUrl("ink", ChainData("Ink", 57073, "https://rpc-gel.inkonchain.com")); + _setChainWithDefaultRpcUrl( + "ink_sepolia", ChainData("Ink Sepolia", 763373, "https://rpc-gel-sepolia.inkonchain.com") + ); + + _setChainWithDefaultRpcUrl("mode", ChainData("Mode", 34443, "https://mode.drpc.org")); + _setChainWithDefaultRpcUrl("mode_sepolia", ChainData("Mode Sepolia", 919, "https://sepolia.mode.network")); - setChainWithDefaultRpcUrl("zora", ChainData("Zora", 7777777, "https://zora.drpc.org")); - setChainWithDefaultRpcUrl( + _setChainWithDefaultRpcUrl("zora", ChainData("Zora", 7777777, "https://zora.drpc.org")); + _setChainWithDefaultRpcUrl( "zora_sepolia", ChainData("Zora Sepolia", 999999999, "https://sepolia.rpc.zora.energy") ); - setChainWithDefaultRpcUrl("race", ChainData("Race", 6805, "https://racemainnet.io")); - setChainWithDefaultRpcUrl("race_sepolia", ChainData("Race Sepolia", 6806, "https://racemainnet.io")); + _setChainWithDefaultRpcUrl("race", ChainData("Race", 6805, "https://racemainnet.io")); + _setChainWithDefaultRpcUrl("race_sepolia", ChainData("Race Sepolia", 6806, "https://racemainnet.io")); - setChainWithDefaultRpcUrl("metal", ChainData("Metal", 1750, "https://metall2.drpc.org")); - setChainWithDefaultRpcUrl("metal_sepolia", ChainData("Metal Sepolia", 1740, "https://testnet.rpc.metall2.com")); + _setChainWithDefaultRpcUrl("radius", ChainData("Radius", 723487, "https://rpc.radiustech.xyz")); + _setChainWithDefaultRpcUrl( + "radius_testnet", ChainData("Radius Testnet", 72344, "https://rpc.testnet.radiustech.xyz") + ); + + _setChainWithDefaultRpcUrl("metal", ChainData("Metal", 1750, "https://metall2.drpc.org")); + _setChainWithDefaultRpcUrl("metal_sepolia", ChainData("Metal Sepolia", 1740, "https://testnet.rpc.metall2.com")); - setChainWithDefaultRpcUrl("binary", ChainData("Binary", 624, "https://rpc.zero.thebinaryholdings.com")); - setChainWithDefaultRpcUrl( + _setChainWithDefaultRpcUrl("binary", ChainData("Binary", 624, "https://rpc.zero.thebinaryholdings.com")); + _setChainWithDefaultRpcUrl( "binary_sepolia", ChainData("Binary Sepolia", 625, "https://rpc.zero.thebinaryholdings.com") ); - setChainWithDefaultRpcUrl("orderly", ChainData("Orderly", 291, "https://rpc.orderly.network")); - setChainWithDefaultRpcUrl( + _setChainWithDefaultRpcUrl("orderly", ChainData("Orderly", 291, "https://rpc.orderly.network")); + _setChainWithDefaultRpcUrl( "orderly_sepolia", ChainData("Orderly Sepolia", 4460, "https://testnet-rpc.orderly.org") ); + + _setChainWithDefaultRpcUrl("unichain", ChainData("Unichain", 130, "https://mainnet.unichain.org")); + _setChainWithDefaultRpcUrl( + "unichain_sepolia", ChainData("Unichain Sepolia", 1301, "https://sepolia.unichain.org") + ); + + _setChainWithDefaultRpcUrl("tempo", ChainData("Tempo", 4217, "https://rpc.mainnet.tempo.xyz")); + _setChainWithDefaultRpcUrl( + "tempo_moderato", ChainData("Tempo Moderato", 42431, "https://rpc.moderato.tempo.xyz") + ); + _setChainWithDefaultRpcUrl( + "tempo_andantino", ChainData("Tempo Andantino", 42429, "https://rpc.testnet.tempo.xyz") + ); + + _setChainWithDefaultRpcUrl("grav", ChainData("Gravity", 127001, "https://mainnet-rpc.gravity.xyz")); } // set chain info, with priority to chainAlias' rpc url in foundry.toml - function setChainWithDefaultRpcUrl(string memory chainAlias, ChainData memory chain) private { + function _setChainWithDefaultRpcUrl(string memory chainAlias, ChainData memory chain) private { string memory rpcUrl = chain.rpcUrl; - defaultRpcUrls[chainAlias] = rpcUrl; + _defaultRpcUrls[chainAlias] = rpcUrl; chain.rpcUrl = ""; setChain(chainAlias, chain); chain.rpcUrl = rpcUrl; // restore argument diff --git a/dependencies/forge-std-1.11.0/src/StdCheats.sol b/dependencies/forge-std-1.16.2/src/StdCheats.sol similarity index 70% rename from dependencies/forge-std-1.11.0/src/StdCheats.sol rename to dependencies/forge-std-1.16.2/src/StdCheats.sol index 9f360de..95a5bf9 100644 --- a/dependencies/forge-std-1.11.0/src/StdCheats.sol +++ b/dependencies/forge-std-1.16.2/src/StdCheats.sol @@ -1,7 +1,5 @@ -// SPDX-License-Identifier: MIT -pragma solidity >=0.6.2 <0.9.0; - -pragma experimental ABIEncoderV2; +// SPDX-License-Identifier: MIT OR Apache-2.0 +pragma solidity >=0.8.13 <0.9.0; import {StdStorage, stdStorage} from "./StdStorage.sol"; import {console2} from "./console2.sol"; @@ -10,13 +8,13 @@ import {Vm} from "./Vm.sol"; abstract contract StdCheatsSafe { Vm private constant vm = Vm(address(uint160(uint256(keccak256("hevm cheat code"))))); - uint256 private constant UINT256_MAX = + uint256 private constant _UINT256_MAX = 115792089237316195423570985008687907853269984665640564039457584007913129639935; - bool private gasMeteringOff; + bool private _gasMeteringOff; // Data structures to parse Transaction objects from the broadcast artifact - // that conform to EIP1559. The Raw structs is what is parsed from the JSON + // that conform to EIP1559. The Raw structs are what are parsed from the JSON // and then converted to the one that is used by the user for better UX. struct RawTx1559 { @@ -65,7 +63,7 @@ abstract contract StdCheatsSafe { } // Data structures to parse Transaction objects from the broadcast artifact - // that DO NOT conform to EIP1559. The Raw structs is what is parsed from the JSON + // that DO NOT conform to EIP1559. The Raw structs are what are parsed from the JSON // and then converted to the one that is used by the user for better UX. struct TxLegacy { @@ -205,7 +203,7 @@ abstract contract StdCheatsSafe { ForgeAddress } - // Checks that `addr` is not blacklisted by token contracts that have a blacklist. + /// @notice Assumes `addr` is not blacklisted by `token`, skipping the fuzz run if it is. function assumeNotBlacklisted(address token, address addr) internal view virtual { // Nothing to check if `token` is not a contract. uint256 tokenCodeSize; @@ -226,14 +224,13 @@ abstract contract StdCheatsSafe { vm.assume(!success || abi.decode(returnData, (bool)) == false); } - // Checks that `addr` is not blacklisted by token contracts that have a blacklist. - // This is identical to `assumeNotBlacklisted(address,address)` but with a different name, for - // backwards compatibility, since this name was used in the original PR which already has - // a release. This function can be removed in a future release once we want a breaking change. + /// @notice Assumes `addr` is not blacklisted by `token`, skipping the fuzz run if it is. + /// @dev Deprecated alias for `assumeNotBlacklisted`. Will be removed in a future breaking release. function assumeNoBlacklisted(address token, address addr) internal view virtual { assumeNotBlacklisted(token, addr); } + /// @notice Assumes `addr` does not match `addressType`, skipping the fuzz run if it does. function assumeAddressIsNot(address addr, AddressType addressType) internal virtual { if (addressType == AddressType.Payable) { assumeNotPayable(addr); @@ -248,11 +245,13 @@ abstract contract StdCheatsSafe { } } + /// @notice Assumes `addr` does not match `addressType1` or `addressType2`, skipping the fuzz run if it does. function assumeAddressIsNot(address addr, AddressType addressType1, AddressType addressType2) internal virtual { assumeAddressIsNot(addr, addressType1); assumeAddressIsNot(addr, addressType2); } + /// @notice Assumes `addr` does not match any of the three given address types, skipping the fuzz run if it does. function assumeAddressIsNot( address addr, AddressType addressType1, @@ -264,6 +263,7 @@ abstract contract StdCheatsSafe { assumeAddressIsNot(addr, addressType3); } + /// @notice Assumes `addr` does not match any of the four given address types, skipping the fuzz run if it does. function assumeAddressIsNot( address addr, AddressType addressType1, @@ -283,7 +283,7 @@ abstract contract StdCheatsSafe { // implemented by `addr`, which should be taken into account when this function is used. function _isPayable(address addr) private returns (bool) { require( - addr.balance < UINT256_MAX, + addr.balance < _UINT256_MAX, "StdCheats _isPayable(address): Balance equals max uint256, so it cannot receive any more funds" ); uint256 origBalanceTest = address(this).balance; @@ -299,25 +299,29 @@ abstract contract StdCheatsSafe { return success; } - // NOTE: This function may result in state changes depending on the fallback/receive logic - // implemented by `addr`, which should be taken into account when this function is used. See the - // `_isPayable` method for more information. + /// @notice Assumes `addr` is a payable address, skipping the fuzz run if it is not. + /// @dev May cause state changes depending on `addr`'s fallback or receive logic. function assumePayable(address addr) internal virtual { vm.assume(_isPayable(addr)); } + /// @notice Assumes `addr` is not a payable address, skipping the fuzz run if it is. + /// @dev May cause state changes depending on `addr`'s fallback or receive logic. function assumeNotPayable(address addr) internal virtual { vm.assume(!_isPayable(addr)); } + /// @notice Assumes `addr` is not the zero address, skipping the fuzz run if it is. function assumeNotZeroAddress(address addr) internal pure virtual { vm.assume(addr != address(0)); } + /// @notice Assumes `addr` is not a precompile on the current chain, skipping the fuzz run if it is. function assumeNotPrecompile(address addr) internal pure virtual { assumeNotPrecompile(addr, _pureChainId()); } + /// @notice Assumes `addr` is not a precompile on `chainId`, skipping the fuzz run if it is. function assumeNotPrecompile(address addr, uint256 chainId) internal pure virtual { // Note: For some chains like Optimism these are technically predeploys (i.e. bytecode placed at a specific // address), but the same rationale for excluding them applies so we include those too. @@ -326,7 +330,7 @@ abstract contract StdCheatsSafe { vm.assume(addr < address(0x1) || addr > address(0xff)); // forgefmt: disable-start - if (chainId == 10 || chainId == 420) { + if (chainId == 10 || chainId == 420 || chainId == 11155420) { // https://github.com/ethereum-optimism/optimism/blob/eaa371a0184b56b7ca6d9eb9cb0a2b78b2ccd864/op-bindings/predeploys/addresses.go#L6-L21 vm.assume(addr < address(0x4200000000000000000000000000000000000000) || addr > address(0x4200000000000000000000000000000000000800)); } else if (chainId == 42161 || chainId == 421613) { @@ -341,6 +345,7 @@ abstract contract StdCheatsSafe { // forgefmt: disable-end } + /// @notice Assumes `addr` is not a Forge-reserved address (vm, console, Create2Deployer), skipping the fuzz run if it is. function assumeNotForgeAddress(address addr) internal pure virtual { // vm, console, and Create2Deployer addresses vm.assume( @@ -349,6 +354,7 @@ abstract contract StdCheatsSafe { ); } + /// @notice Assumes `addr` has no code and is not a precompile, zero, or Forge-reserved address. function assumeUnusedAddress(address addr) internal view virtual { uint256 size; assembly { @@ -361,6 +367,7 @@ abstract contract StdCheatsSafe { assumeNotForgeAddress(addr); } + /// @notice Reads and parses an EIP-1559 broadcast artifact from `path`. function readEIP1559ScriptArtifact(string memory path) internal view @@ -381,6 +388,7 @@ abstract contract StdCheatsSafe { return artifact; } + /// @notice Converts an array of raw EIP-1559 transactions to the user-friendly `Tx1559` format. function rawToConvertedEIPTx1559s(RawTx1559[] memory rawTxs) internal pure virtual returns (Tx1559[] memory) { Tx1559[] memory txs = new Tx1559[](rawTxs.length); for (uint256 i; i < rawTxs.length; i++) { @@ -389,9 +397,11 @@ abstract contract StdCheatsSafe { return txs; } + /// @notice Converts a single raw EIP-1559 transaction to the user-friendly `Tx1559` format. function rawToConvertedEIPTx1559(RawTx1559 memory rawTx) internal pure virtual returns (Tx1559 memory) { Tx1559 memory transaction; transaction.arguments = rawTx.arguments; + transaction.contractAddress = rawTx.contractAddress; transaction.contractName = rawTx.contractName; transaction.functionSig = rawTx.functionSig; transaction.hash = rawTx.hash; @@ -400,6 +410,7 @@ abstract contract StdCheatsSafe { return transaction; } + /// @notice Converts raw EIP-1559 transaction detail fields to the user-friendly `Tx1559Detail` format. function rawToConvertedEIP1559Detail(RawTx1559Detail memory rawDetail) internal pure @@ -418,6 +429,7 @@ abstract contract StdCheatsSafe { return txDetail; } + /// @notice Reads all EIP-1559 transactions from the broadcast artifact at `path`. function readTx1559s(string memory path) internal view virtual returns (Tx1559[] memory) { string memory deployData = vm.readFile(path); bytes memory parsedDeployData = vm.parseJson(deployData, ".transactions"); @@ -425,6 +437,7 @@ abstract contract StdCheatsSafe { return rawToConvertedEIPTx1559s(rawTxs); } + /// @notice Reads the EIP-1559 transaction at `index` from the broadcast artifact at `path`. function readTx1559(string memory path, uint256 index) internal view virtual returns (Tx1559 memory) { string memory deployData = vm.readFile(path); string memory key = string(abi.encodePacked(".transactions[", vm.toString(index), "]")); @@ -433,7 +446,7 @@ abstract contract StdCheatsSafe { return rawToConvertedEIPTx1559(rawTx); } - // Analogous to readTransactions, but for receipts. + /// @notice Reads all transaction receipts from the broadcast artifact at `path`. function readReceipts(string memory path) internal view virtual returns (Receipt[] memory) { string memory deployData = vm.readFile(path); bytes memory parsedDeployData = vm.parseJson(deployData, ".receipts"); @@ -441,6 +454,7 @@ abstract contract StdCheatsSafe { return rawToConvertedReceipts(rawReceipts); } + /// @notice Reads the transaction receipt at `index` from the broadcast artifact at `path`. function readReceipt(string memory path, uint256 index) internal view virtual returns (Receipt memory) { string memory deployData = vm.readFile(path); string memory key = string(abi.encodePacked(".receipts[", vm.toString(index), "]")); @@ -449,6 +463,7 @@ abstract contract StdCheatsSafe { return rawToConvertedReceipt(rawReceipt); } + /// @notice Converts an array of raw receipts to the user-friendly `Receipt` format. function rawToConvertedReceipts(RawReceipt[] memory rawReceipts) internal pure virtual returns (Receipt[] memory) { Receipt[] memory receipts = new Receipt[](rawReceipts.length); for (uint256 i; i < rawReceipts.length; i++) { @@ -457,6 +472,7 @@ abstract contract StdCheatsSafe { return receipts; } + /// @notice Converts a single raw receipt to the user-friendly `Receipt` format. function rawToConvertedReceipt(RawReceipt memory rawReceipt) internal pure virtual returns (Receipt memory) { Receipt memory receipt; receipt.blockHash = rawReceipt.blockHash; @@ -475,6 +491,7 @@ abstract contract StdCheatsSafe { return receipt; } + /// @notice Converts an array of raw receipt logs to the user-friendly `ReceiptLog` format. function rawToConvertedReceiptLogs(RawReceiptLog[] memory rawLogs) internal pure @@ -496,66 +513,60 @@ abstract contract StdCheatsSafe { return logs; } - // Deploy a contract by fetching the contract bytecode from - // the artifacts directory - // e.g. `deployCode(code, abi.encode(arg1,arg2,arg3))` + /// @notice Deploys a contract from the artifacts directory with ABI-encoded constructor arguments. function deployCode(string memory what, bytes memory args) internal virtual returns (address addr) { bytes memory bytecode = abi.encodePacked(vm.getCode(what), args); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { addr := create(0, add(bytecode, 0x20), mload(bytecode)) } require(addr != address(0), "StdCheats deployCode(string,bytes): Deployment failed."); } + /// @notice Deploys a contract from the artifacts directory. function deployCode(string memory what) internal virtual returns (address addr) { bytes memory bytecode = vm.getCode(what); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { addr := create(0, add(bytecode, 0x20), mload(bytecode)) } require(addr != address(0), "StdCheats deployCode(string): Deployment failed."); } - /// @dev deploy contract with value on construction + /// @notice Deploys a contract from the artifacts directory with ABI-encoded constructor arguments, sending `val` wei on construction. function deployCode(string memory what, bytes memory args, uint256 val) internal virtual returns (address addr) { bytes memory bytecode = abi.encodePacked(vm.getCode(what), args); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { addr := create(val, add(bytecode, 0x20), mload(bytecode)) } require(addr != address(0), "StdCheats deployCode(string,bytes,uint256): Deployment failed."); } + /// @notice Deploys a contract from the artifacts directory, sending `val` wei on construction. function deployCode(string memory what, uint256 val) internal virtual returns (address addr) { bytes memory bytecode = vm.getCode(what); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { addr := create(val, add(bytecode, 0x20), mload(bytecode)) } require(addr != address(0), "StdCheats deployCode(string,uint256): Deployment failed."); } - // creates a labeled address and the corresponding private key + /// @notice Creates a labeled address and the corresponding private key derived from `name`. function makeAddrAndKey(string memory name) internal virtual returns (address addr, uint256 privateKey) { privateKey = uint256(keccak256(abi.encodePacked(name))); addr = vm.addr(privateKey); vm.label(addr, name); } - // creates a labeled address + /// @notice Creates a labeled address derived from `name`. function makeAddr(string memory name) internal virtual returns (address addr) { (addr,) = makeAddrAndKey(name); } - // Destroys an account immediately, sending the balance to beneficiary. - // Destroying means: balance will be zero, code will be empty, and nonce will be 0 - // This is similar to selfdestruct but not identical: selfdestruct destroys code and nonce - // only after tx ends, this will run immediately. + /// @notice Immediately destroys `who`, zeroing its balance, code, and nonce, and sending its balance to `beneficiary`. + /// @dev Unlike `selfdestruct`, this takes effect immediately within the same transaction. function destroyAccount(address who, address beneficiary) internal virtual { uint256 currBalance = who.balance; vm.etch(who, abi.encode()); @@ -566,11 +577,12 @@ abstract contract StdCheatsSafe { vm.deal(beneficiary, currBalance + beneficiaryBalance); } - // creates a struct containing both a labeled address and the corresponding private key + /// @notice Creates an `Account` struct with a labeled address and private key derived from `name`. function makeAccount(string memory name) internal virtual returns (Account memory account) { (account.addr, account.key) = makeAddrAndKey(name); } + /// @notice Derives a private key from `mnemonic` at `index`, stores it in the local wallet, and returns the address and key. function deriveRememberKey(string memory mnemonic, uint32 index) internal virtual @@ -585,24 +597,29 @@ abstract contract StdCheatsSafe { return abi.decode(abi.encodePacked(new bytes(32 - b.length), b), (uint256)); } + /// @notice Returns whether the current test environment is running against a forked network. function isFork() internal view virtual returns (bool status) { try vm.activeFork() { status = true; } catch (bytes memory) {} } + /// @notice Skips the test body when running against a forked network. modifier skipWhenForking() { if (!isFork()) { _; } } + /// @notice Skips the test body when not running against a forked network. modifier skipWhenNotForking() { if (isFork()) { _; } } + /// @notice Disables gas metering for the duration of the function, re-enabling it on exit. + /// @dev When nested, gas metering is only resumed at the end of the outermost function that uses this modifier. modifier noGasMetering() { vm.pauseGasMetering(); // To prevent turning gas monitoring back on with nested functions that use this modifier, @@ -612,14 +629,14 @@ abstract contract StdCheatsSafe { // i.e. funcA() noGasMetering { funcB() }, where funcB has noGasMetering as well. // funcA will have `gasStartedOff` as false, funcB will have it as true, // so we only turn metering back on at the end of the funcA - bool gasStartedOff = gasMeteringOff; - gasMeteringOff = true; + bool gasStartedOff = _gasMeteringOff; + _gasMeteringOff = true; _; // if gas metering was on when this modifier was called, turn it back on at the end if (!gasStartedOff) { - gasMeteringOff = false; + _gasMeteringOff = false; vm.resumeGasMetering(); } } @@ -651,99 +668,167 @@ abstract contract StdCheatsSafe { abstract contract StdCheats is StdCheatsSafe { using stdStorage for StdStorage; - StdStorage private stdstore; + StdStorage private _stdstore; Vm private constant vm = Vm(address(uint160(uint256(keccak256("hevm cheat code"))))); - address private constant CONSOLE2_ADDRESS = 0x000000000000000000636F6e736F6c652e6c6f67; + address private constant _CONSOLE2_ADDRESS = 0x000000000000000000636F6e736F6c652e6c6f67; - // Skip forward or rewind time by the specified number of seconds + /// @notice Advances the block timestamp forward by `time` seconds. function skip(uint256 time) internal virtual { vm.warp(vm.getBlockTimestamp() + time); } + /// @notice Rewinds the block timestamp backward by `time` seconds. function rewind(uint256 time) internal virtual { vm.warp(vm.getBlockTimestamp() - time); } - // Setup a prank from an address that has some ether + /// @notice Sets up a single-call prank from `msgSender`, giving it `2**128` wei. function hoax(address msgSender) internal virtual { vm.deal(msgSender, 1 << 128); vm.prank(msgSender); } + /// @notice Sets up a single-call prank from `msgSender`, giving it `give` wei. function hoax(address msgSender, uint256 give) internal virtual { vm.deal(msgSender, give); vm.prank(msgSender); } + /// @notice Sets up a single-call prank from `msgSender` with `origin` as `tx.origin`, giving `msgSender` `2**128` wei. function hoax(address msgSender, address origin) internal virtual { vm.deal(msgSender, 1 << 128); vm.prank(msgSender, origin); } + /// @notice Sets up a single-call prank from `msgSender` with `origin` as `tx.origin`, giving `msgSender` `give` wei. function hoax(address msgSender, address origin, uint256 give) internal virtual { vm.deal(msgSender, give); vm.prank(msgSender, origin); } - // Start perpetual prank from an address that has some ether + /// @notice Starts a persistent prank from `msgSender`, giving it `2**128` wei. function startHoax(address msgSender) internal virtual { vm.deal(msgSender, 1 << 128); vm.startPrank(msgSender); } + /// @notice Starts a persistent prank from `msgSender`, giving it `give` wei. function startHoax(address msgSender, uint256 give) internal virtual { vm.deal(msgSender, give); vm.startPrank(msgSender); } - // Start perpetual prank from an address that has some ether - // tx.origin is set to the origin parameter + /// @notice Starts a persistent prank from `msgSender` with `origin` as `tx.origin`, giving `msgSender` `2**128` wei. function startHoax(address msgSender, address origin) internal virtual { vm.deal(msgSender, 1 << 128); vm.startPrank(msgSender, origin); } + /// @notice Starts a persistent prank from `msgSender` with `origin` as `tx.origin`, giving `msgSender` `give` wei. function startHoax(address msgSender, address origin, uint256 give) internal virtual { vm.deal(msgSender, give); vm.startPrank(msgSender, origin); } + /// @notice Changes the active prank to `msgSender`. + /// @dev Deprecated. Use `vm.startPrank` instead. function changePrank(address msgSender) internal virtual { - console2_log_StdCheats("changePrank is deprecated. Please use vm.startPrank instead."); + _console2_log_StdCheats("changePrank is deprecated. Please use vm.startPrank instead."); vm.stopPrank(); vm.startPrank(msgSender); } + /// @notice Changes the active prank to `msgSender` with `txOrigin` as `tx.origin`. + /// @dev Deprecated. Use `vm.startPrank` instead. function changePrank(address msgSender, address txOrigin) internal virtual { + _console2_log_StdCheats("changePrank is deprecated. Please use vm.startPrank instead."); vm.stopPrank(); vm.startPrank(msgSender, txOrigin); } - // The same as Vm's `deal` - // Use the alternative signature for ERC20 tokens + /// @notice Expects a call to `callee` with `data` and mocks it to return `returnData`. + function expectAndMockCall(address callee, bytes memory data, bytes memory returnData) internal virtual { + vm.expectCall(callee, data); + vm.mockCall(callee, data, returnData); + } + + /// @notice Expects exactly `count` calls to `callee` with `data` and mocks them to return `returnData`. + function expectAndMockCall(address callee, bytes memory data, uint64 count, bytes memory returnData) + internal + virtual + { + vm.expectCall(callee, data, count); + vm.mockCall(callee, data, returnData); + } + + /// @notice Expects a call to `callee` with `msgValue` and `data` and mocks it to return `returnData`. + function expectAndMockCall(address callee, uint256 msgValue, bytes memory data, bytes memory returnData) + internal + virtual + { + vm.expectCall(callee, msgValue, data); + vm.mockCall(callee, msgValue, data, returnData); + } + + /// @notice Expects exactly `count` calls to `callee` with `msgValue` and `data` and mocks them to return `returnData`. + function expectAndMockCall( + address callee, + uint256 msgValue, + bytes memory data, + uint64 count, + bytes memory returnData + ) internal virtual { + vm.expectCall(callee, msgValue, data, count); + vm.mockCall(callee, msgValue, data, returnData); + } + + /// @notice Expects a call to `callee` with `msgValue` and `data` forwarding `gas`, and mocks it to return `returnData`. + /// @dev `gas` only applies to the call expectation; the mock call ignores `gas`. + function expectAndMockCall(address callee, uint256 msgValue, uint64 gas, bytes memory data, bytes memory returnData) + internal + virtual + { + vm.expectCall(callee, msgValue, gas, data); + vm.mockCall(callee, msgValue, data, returnData); + } + + /// @notice Expects exactly `count` calls to `callee` with `msgValue` and `data` forwarding `gas`, and mocks them to return `returnData`. + /// @dev `gas` only applies to the call expectation; the mock call ignores `gas`. + function expectAndMockCall( + address callee, + uint256 msgValue, + uint64 gas, + bytes memory data, + uint64 count, + bytes memory returnData + ) internal virtual { + vm.expectCall(callee, msgValue, gas, data, count); + vm.mockCall(callee, msgValue, data, returnData); + } + + /// @notice Sets the ETH balance of `to` to `give`. function deal(address to, uint256 give) internal virtual { vm.deal(to, give); } - // Set the balance of an account for any ERC20 token - // Use the alternative signature to update `totalSupply` + /// @notice Sets the ERC20 `token` balance of `to` to `give`. function deal(address token, address to, uint256 give) internal virtual { deal(token, to, give, false); } - // Set the balance of an account for any ERC1155 token - // Use the alternative signature to update `totalSupply` + /// @notice Sets the ERC1155 `token` balance of `to` for token `id` to `give`. function dealERC1155(address token, address to, uint256 id, uint256 give) internal virtual { dealERC1155(token, to, id, give, false); } + /// @notice Sets the ERC20 `token` balance of `to` to `give`, optionally adjusting the total supply. function deal(address token, address to, uint256 give, bool adjust) internal virtual { // get current balance (, bytes memory balData) = token.staticcall(abi.encodeWithSelector(0x70a08231, to)); uint256 prevBal = abi.decode(balData, (uint256)); // update balance - stdstore.target(token).sig(0x70a08231).with_key(to).checked_write(give); + _stdstore.target(token).sig(0x70a08231).with_key(to).checked_write(give); // update total supply if (adjust) { @@ -754,24 +839,25 @@ abstract contract StdCheats is StdCheatsSafe { } else { totSup += (give - prevBal); } - stdstore.target(token).sig(0x18160ddd).checked_write(totSup); + _stdstore.target(token).sig(0x18160ddd).checked_write(totSup); } } + /// @notice Sets the ERC1155 `token` balance of `to` for token `id` to `give`, optionally adjusting the total supply. function dealERC1155(address token, address to, uint256 id, uint256 give, bool adjust) internal virtual { // get current balance (, bytes memory balData) = token.staticcall(abi.encodeWithSelector(0x00fdd58e, to, id)); uint256 prevBal = abi.decode(balData, (uint256)); // update balance - stdstore.target(token).sig(0x00fdd58e).with_key(to).with_key(id).checked_write(give); + _stdstore.target(token).sig(0x00fdd58e).with_key(to).with_key(id).checked_write(give); // update total supply if (adjust) { (, bytes memory totSupData) = token.staticcall(abi.encodeWithSelector(0xbd85b039, id)); require( totSupData.length != 0, - "StdCheats deal(address,address,uint,uint,bool): target contract is not ERC1155Supply." + "StdCheats dealERC1155(address,address,uint256,uint256,bool): target contract is not ERC1155Supply." ); uint256 totSup = abi.decode(totSupData, (uint256)); if (give < prevBal) { @@ -779,14 +865,15 @@ abstract contract StdCheats is StdCheatsSafe { } else { totSup += (give - prevBal); } - stdstore.target(token).sig(0xbd85b039).with_key(id).checked_write(totSup); + _stdstore.target(token).sig(0xbd85b039).with_key(id).checked_write(totSup); } } + /// @notice Transfers ownership of ERC721 `token` with `id` to `to`, updating balances accordingly. function dealERC721(address token, address to, uint256 id) internal virtual { // check if token id is already minted and the actual owner. (bool successMinted, bytes memory ownerData) = token.staticcall(abi.encodeWithSelector(0x6352211e, id)); - require(successMinted, "StdCheats deal(address,address,uint,bool): id not minted."); + require(successMinted, "StdCheats dealERC721(address,address,uint256): id not minted."); // get owner current balance (, bytes memory fromBalData) = @@ -798,21 +885,27 @@ abstract contract StdCheats is StdCheatsSafe { uint256 toPrevBal = abi.decode(toBalData, (uint256)); // update balances - stdstore.target(token).sig(0x70a08231).with_key(abi.decode(ownerData, (address))).checked_write(--fromPrevBal); - stdstore.target(token).sig(0x70a08231).with_key(to).checked_write(++toPrevBal); + _stdstore.target(token).sig(0x70a08231).with_key(abi.decode(ownerData, (address))).checked_write(--fromPrevBal); + _stdstore.target(token).sig(0x70a08231).with_key(to).checked_write(++toPrevBal); // update owner - stdstore.target(token).sig(0x6352211e).with_key(id).checked_write(to); + _stdstore.target(token).sig(0x6352211e).with_key(id).checked_write(to); } + /// @notice Etches the runtime bytecode of `what` (from the artifacts directory) at `where`. + /// @dev Runs the contract's creation code via `vm.etch` + a self-call, then etches the resulting runtime code at `where`. Constructor side-effects on other contracts are not preserved. function deployCodeTo(string memory what, address where) internal virtual { deployCodeTo(what, "", 0, where); } + /// @notice Etches the runtime bytecode of `what` (from the artifacts directory) at `where`, using `args` as ABI-encoded constructor arguments. + /// @dev Runs the contract's creation code via `vm.etch` + a self-call, then etches the resulting runtime code at `where`. Constructor side-effects on other contracts are not preserved. function deployCodeTo(string memory what, bytes memory args, address where) internal virtual { deployCodeTo(what, args, 0, where); } + /// @notice Etches the runtime bytecode of `what` (from the artifacts directory) at `where`, using `args` as ABI-encoded constructor arguments and sending `value` wei to the constructor. + /// @dev Runs the contract's creation code via `vm.etch` + a self-call, then etches the resulting runtime code at `where`. Constructor side-effects on other contracts are not preserved. function deployCodeTo(string memory what, bytes memory args, uint256 value, address where) internal virtual { bytes memory creationCode = vm.getCode(what); vm.etch(where, abi.encodePacked(creationCode, args)); @@ -822,8 +915,8 @@ abstract contract StdCheats is StdCheatsSafe { } // Used to prevent the compilation of console, which shortens the compilation time when console is not used elsewhere. - function console2_log_StdCheats(string memory p0) private view { - (bool status,) = address(CONSOLE2_ADDRESS).staticcall(abi.encodeWithSignature("log(string)", p0)); + function _console2_log_StdCheats(string memory p0) private view { + (bool status,) = address(_CONSOLE2_ADDRESS).staticcall(abi.encodeWithSignature("log(string)", p0)); status; } } diff --git a/dependencies/forge-std-1.11.0/src/StdConfig.sol b/dependencies/forge-std-1.16.2/src/StdConfig.sol similarity index 95% rename from dependencies/forge-std-1.11.0/src/StdConfig.sol rename to dependencies/forge-std-1.16.2/src/StdConfig.sol index 506ac34..1675230 100644 --- a/dependencies/forge-std-1.11.0/src/StdConfig.sol +++ b/dependencies/forge-std-1.16.2/src/StdConfig.sol @@ -1,16 +1,16 @@ -// SPDX-License-Identifier: MIT +// SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity ^0.8.13; import {VmSafe} from "./Vm.sol"; import {Variable, Type, TypeKind, LibVariable} from "./LibVariable.sol"; -/// @notice A contract that parses a toml configuration file and load its +/// @notice A contract that parses a toml configuration file and loads its /// variables into storage, automatically casting them, on deployment. /// /// @dev This contract assumes a toml structure where top-level keys /// represent chain ids or aliases. Under each chain key, variables are /// organized by type in separate sub-tables like `[.]`, where -/// type must be: `bool`, `address`, `bytes32`, `uint`, `ìnt`, `string`, or `bytes`. +/// type must be: `bool`, `address`, `bytes32`, `uint`, `int`, `string`, or `bytes`. /// /// Supported format: /// ``` @@ -37,8 +37,8 @@ contract StdConfig { VmSafe private constant vm = VmSafe(address(uint160(uint256(keccak256("hevm cheat code"))))); - /// @dev Types: `bool`, `address`, `bytes32`, `uint`, `ìnt`, `string`, `bytes`. - uint8 private constant NUM_TYPES = 7; + /// @dev Types: `bool`, `address`, `bytes32`, `uint`, `int`, `string`, `bytes`. + uint8 private constant _NUM_TYPES = 7; // -- ERRORS --------------------------------------------------------------- @@ -75,7 +75,7 @@ contract StdConfig { /// @notice Reads the TOML file and iterates through each top-level key, which is /// assumed to be a chain name or ID. For each chain, it caches its RPC /// endpoint and all variables defined in typed sub-tables like `[.]`, - /// where type must be: `bool`, `address`, `uint`, `bytes32`, `string`, or `bytes`. + /// where type must be: `bool`, `address`, `bytes32`, `uint`, `int`, `string`, or `bytes`. /// /// The constructor attempts to parse each variable first as a single value, /// and if that fails, as an array of that type. If a variable cannot be @@ -103,17 +103,18 @@ contract StdConfig { uint256 chainId = resolveChainId(chain_key); _chainKeys.push(chain_key); - // Cache the configure rpc endpoint for that chain. + // Cache the configured RPC endpoint for that chain. // Falls back to `[rpc_endpoints]`. Panics if no rpc endpoint is configured. - try vm.parseTomlString(content, string.concat("$.", chain_key, ".endpoint_url")) returns (string memory url) - { + try vm.parseTomlString(content, string.concat("$.", chain_key, ".endpoint_url")) returns ( + string memory url + ) { _rpcOf[chainId] = vm.resolveEnv(url); } catch { _rpcOf[chainId] = vm.resolveEnv(vm.rpcUrl(chain_key)); } // Iterate through all the available `TypeKind`s (except `None`) to create the sub-section paths - for (uint8 t = 1; t <= NUM_TYPES; t++) { + for (uint8 t = 1; t <= _NUM_TYPES; t++) { TypeKind ty = TypeKind(t); string memory typePath = string.concat("$.", chain_key, ".", ty.toTomlKey()); @@ -126,7 +127,7 @@ contract StdConfig { revert AlreadyInitialized(key); } } - } catch {} // Section does not exist, ignore. + } catch {} } } } @@ -320,6 +321,25 @@ contract StdConfig { return get(vm.getChainId(), key); } + /// @dev Checks the existence of a variable for a given chain ID and key, and returns a boolean. + /// Example: `bool hasKey = config.exists(1, "my_key");` + /// + /// @param chain_id The chain ID to check. + /// @param key The variable key name. + /// @return `bool` indicating whether a variable with the given key exists. + function exists(uint256 chain_id, string memory key) public view returns (bool) { + return _dataOf[chain_id][key].length > 0; + } + + /// @dev Checks the existence of a variable for the current chain id and a given key, and returns a boolean. + /// Example: `bool hasKey = config.exists("my_key");` + /// + /// @param key The variable key name. + /// @return `bool` indicating whether a variable with the given key exists. + function exists(string memory key) public view returns (bool) { + return exists(vm.getChainId(), key); + } + /// @notice Returns the numerical chain ids for all configured chains. function getChainIds() public view returns (uint256[] memory) { string[] memory keys = _chainKeys; diff --git a/dependencies/forge-std-1.11.0/src/StdConstants.sol b/dependencies/forge-std-1.16.2/src/StdConstants.sol similarity index 95% rename from dependencies/forge-std-1.11.0/src/StdConstants.sol rename to dependencies/forge-std-1.16.2/src/StdConstants.sol index 2047d2b..9f069ef 100644 --- a/dependencies/forge-std-1.11.0/src/StdConstants.sol +++ b/dependencies/forge-std-1.16.2/src/StdConstants.sol @@ -1,5 +1,5 @@ -// SPDX-License-Identifier: MIT -pragma solidity >=0.6.2 <0.9.0; +// SPDX-License-Identifier: MIT OR Apache-2.0 +pragma solidity >=0.8.13 <0.9.0; import {IMulticall3} from "./interfaces/IMulticall3.sol"; import {Vm} from "./Vm.sol"; diff --git a/dependencies/forge-std-1.16.2/src/StdError.sol b/dependencies/forge-std-1.16.2/src/StdError.sol new file mode 100644 index 0000000..94df159 --- /dev/null +++ b/dependencies/forge-std-1.16.2/src/StdError.sol @@ -0,0 +1,33 @@ +// SPDX-License-Identifier: MIT OR Apache-2.0 +// Panics work for versions >=0.8.0, but we lowered the pragma to make this compatible with Test +pragma solidity >=0.8.13 <0.9.0; + +/// @notice Pre-encoded Solidity panic error selectors for use in test assertions. +library stdError { + /// @notice Panic caused by `assert(false)` or an assertion failure (0x01). + bytes public constant assertionError = abi.encodeWithSignature("Panic(uint256)", 0x01); + + /// @notice Panic caused by arithmetic overflow or underflow (0x11). + bytes public constant arithmeticError = abi.encodeWithSignature("Panic(uint256)", 0x11); + + /// @notice Panic caused by division or modulo by zero (0x12). + bytes public constant divisionError = abi.encodeWithSignature("Panic(uint256)", 0x12); + + /// @notice Panic caused by converting a value that is too large or negative into an enum type (0x21). + bytes public constant enumConversionError = abi.encodeWithSignature("Panic(uint256)", 0x21); + + /// @notice Panic caused by accessing incorrectly encoded storage data (0x22). + bytes public constant encodeStorageError = abi.encodeWithSignature("Panic(uint256)", 0x22); + + /// @notice Panic caused by calling `.pop()` on an empty array (0x31). + bytes public constant popError = abi.encodeWithSignature("Panic(uint256)", 0x31); + + /// @notice Panic caused by accessing an array, bytesN, or slice at an out-of-bounds index (0x32). + bytes public constant indexOOBError = abi.encodeWithSignature("Panic(uint256)", 0x32); + + /// @notice Panic caused by allocating too much memory or creating an array that is too large (0x41). + bytes public constant memOverflowError = abi.encodeWithSignature("Panic(uint256)", 0x41); + + /// @notice Panic caused by calling a zero-initialized variable of internal function type (0x51). + bytes public constant zeroVarError = abi.encodeWithSignature("Panic(uint256)", 0x51); +} diff --git a/dependencies/forge-std-1.11.0/src/StdInvariant.sol b/dependencies/forge-std-1.16.2/src/StdInvariant.sol similarity index 53% rename from dependencies/forge-std-1.11.0/src/StdInvariant.sol rename to dependencies/forge-std-1.16.2/src/StdInvariant.sol index 056db98..2c79b6e 100644 --- a/dependencies/forge-std-1.11.0/src/StdInvariant.sol +++ b/dependencies/forge-std-1.16.2/src/StdInvariant.sol @@ -1,8 +1,7 @@ -// SPDX-License-Identifier: MIT -pragma solidity >=0.6.2 <0.9.0; - -pragma experimental ABIEncoderV2; +// SPDX-License-Identifier: MIT OR Apache-2.0 +pragma solidity >=0.8.13 <0.9.0; +/// @notice Abstract contract providing configuration utilities for Forge invariant tests. abstract contract StdInvariant { struct FuzzSelector { address addr; @@ -37,42 +36,62 @@ abstract contract StdInvariant { // Functions for users: // These are intended to be called in tests. + /// @notice Excludes a contract address from invariant target selection. + /// @param newExcludedContract_ The contract address to exclude. function excludeContract(address newExcludedContract_) internal { _excludedContracts.push(newExcludedContract_); } + /// @notice Excludes specific selectors on a contract from invariant fuzzing. + /// @param newExcludedSelector_ The selector configuration to exclude. function excludeSelector(FuzzSelector memory newExcludedSelector_) internal { _excludedSelectors.push(newExcludedSelector_); } + /// @notice Excludes a sender from invariant fuzzing; exclusion takes precedence over targeted senders. + /// @param newExcludedSender_ The sender address to exclude. function excludeSender(address newExcludedSender_) internal { _excludedSenders.push(newExcludedSender_); } + /// @notice Excludes an artifact identifier from invariant target selection. + /// @param newExcludedArtifact_ The artifact identifier to exclude. function excludeArtifact(string memory newExcludedArtifact_) internal { _excludedArtifacts.push(newExcludedArtifact_); } + /// @notice Targets an artifact identifier for invariant fuzzing. + /// @param newTargetedArtifact_ The artifact identifier to target. function targetArtifact(string memory newTargetedArtifact_) internal { _targetedArtifacts.push(newTargetedArtifact_); } + /// @notice Targets specific selectors for an artifact identifier during invariant fuzzing. + /// @param newTargetedArtifactSelector_ The artifact-selector configuration to target. function targetArtifactSelector(FuzzArtifactSelector memory newTargetedArtifactSelector_) internal { _targetedArtifactSelectors.push(newTargetedArtifactSelector_); } + /// @notice Targets a contract address for invariant fuzzing. + /// @param newTargetedContract_ The contract address to target. function targetContract(address newTargetedContract_) internal { _targetedContracts.push(newTargetedContract_); } + /// @notice Targets specific selectors on a contract for invariant fuzzing. + /// @param newTargetedSelector_ The selector configuration to target. function targetSelector(FuzzSelector memory newTargetedSelector_) internal { _targetedSelectors.push(newTargetedSelector_); } + /// @notice Adds a sender to the invariant sender allowlist; when non-empty, fuzzing uses only targeted non-excluded senders. + /// @param newTargetedSender_ The sender address to target. function targetSender(address newTargetedSender_) internal { _targetedSenders.push(newTargetedSender_); } + /// @notice Targets an address plus artifact interfaces for invariant fuzzing. + /// @param newTargetedInterface_ The address-interface configuration to target. function targetInterface(FuzzInterface memory newTargetedInterface_) internal { _targetedInterfaces.push(newTargetedInterface_); } @@ -80,42 +99,62 @@ abstract contract StdInvariant { // Functions for forge: // These are called by forge to run invariant tests and don't need to be called in tests. + /// @notice Returns artifact identifiers configured via `excludeArtifact`. + /// @return excludedArtifacts_ The list of excluded artifact identifiers. function excludeArtifacts() public view returns (string[] memory excludedArtifacts_) { excludedArtifacts_ = _excludedArtifacts; } + /// @notice Returns contract addresses configured via `excludeContract`. + /// @return excludedContracts_ The list of excluded contract addresses. function excludeContracts() public view returns (address[] memory excludedContracts_) { excludedContracts_ = _excludedContracts; } + /// @notice Returns selector exclusions configured via `excludeSelector`. + /// @return excludedSelectors_ The list of excluded selector configurations. function excludeSelectors() public view returns (FuzzSelector[] memory excludedSelectors_) { excludedSelectors_ = _excludedSelectors; } + /// @notice Returns senders configured via `excludeSender`. + /// @return excludedSenders_ The list of excluded sender addresses. function excludeSenders() public view returns (address[] memory excludedSenders_) { excludedSenders_ = _excludedSenders; } + /// @notice Returns artifact identifiers configured via `targetArtifact`. + /// @return targetedArtifacts_ The list of targeted artifact identifiers. function targetArtifacts() public view returns (string[] memory targetedArtifacts_) { targetedArtifacts_ = _targetedArtifacts; } + /// @notice Returns artifact-selector targets configured via `targetArtifactSelector`. + /// @return targetedArtifactSelectors_ The list of targeted artifact-selector configurations. function targetArtifactSelectors() public view returns (FuzzArtifactSelector[] memory targetedArtifactSelectors_) { targetedArtifactSelectors_ = _targetedArtifactSelectors; } + /// @notice Returns contract addresses configured via `targetContract`. + /// @return targetedContracts_ The list of targeted contract addresses. function targetContracts() public view returns (address[] memory targetedContracts_) { targetedContracts_ = _targetedContracts; } + /// @notice Returns selector targets configured via `targetSelector`. + /// @return targetedSelectors_ The list of targeted selector configurations. function targetSelectors() public view returns (FuzzSelector[] memory targetedSelectors_) { targetedSelectors_ = _targetedSelectors; } + /// @notice Returns sender allowlist configured via `targetSender` (empty means no sender allowlist). + /// @return targetedSenders_ The list of targeted sender addresses. function targetSenders() public view returns (address[] memory targetedSenders_) { targetedSenders_ = _targetedSenders; } + /// @notice Returns address-interface targets configured via `targetInterface`. + /// @return targetedInterfaces_ The list of targeted address-interface configurations. function targetInterfaces() public view returns (FuzzInterface[] memory targetedInterfaces_) { targetedInterfaces_ = _targetedInterfaces; } diff --git a/dependencies/forge-std-1.11.0/src/StdJson.sol b/dependencies/forge-std-1.16.2/src/StdJson.sol similarity index 64% rename from dependencies/forge-std-1.11.0/src/StdJson.sol rename to dependencies/forge-std-1.16.2/src/StdJson.sol index 2a033c0..2c89442 100644 --- a/dependencies/forge-std-1.11.0/src/StdJson.sol +++ b/dependencies/forge-std-1.16.2/src/StdJson.sol @@ -1,16 +1,17 @@ -// SPDX-License-Identifier: MIT -pragma solidity >=0.6.0 <0.9.0; - -pragma experimental ABIEncoderV2; +// SPDX-License-Identifier: MIT OR Apache-2.0 +pragma solidity >=0.8.13 <0.9.0; import {VmSafe} from "./Vm.sol"; -// Helpers for parsing and writing JSON files +// Helpers for parsing and writing JSON files. +// `key` parameters use the same selector syntax as the `vm.parseJson*` cheatcodes, +// for example `.a` for a nested field or `$` for the root object. // To parse: // ``` // using stdJson for string; // string memory json = vm.readFile(""); -// json.readUint(""); +// uint256 value = json.readUint(".a"); +// bytes memory encoded = json.parseRaw("$"); // ``` // To write: // ``` @@ -25,74 +26,94 @@ import {VmSafe} from "./Vm.sol"; library stdJson { VmSafe private constant vm = VmSafe(address(uint160(uint256(keccak256("hevm cheat code"))))); + /// @notice Returns whether `key` exists in `json`. + /// @dev `key` uses the same selector syntax as `vm.parseJson*`, such as `.a` or `$`. function keyExists(string memory json, string memory key) internal view returns (bool) { return vm.keyExistsJson(json, key); } + /// @notice ABI-encodes the JSON value selected by `key`. + /// @dev `key` uses the same selector syntax as `vm.parseJson*`, such as `.a` or `$`. function parseRaw(string memory json, string memory key) internal pure returns (bytes memory) { return vm.parseJson(json, key); } + /// @notice Reads a uint256 value at `key` from `json`. function readUint(string memory json, string memory key) internal pure returns (uint256) { return vm.parseJsonUint(json, key); } + /// @notice Reads a uint256 array at `key` from `json`. function readUintArray(string memory json, string memory key) internal pure returns (uint256[] memory) { return vm.parseJsonUintArray(json, key); } + /// @notice Reads an int256 value at `key` from `json`. function readInt(string memory json, string memory key) internal pure returns (int256) { return vm.parseJsonInt(json, key); } + /// @notice Reads an int256 array at `key` from `json`. function readIntArray(string memory json, string memory key) internal pure returns (int256[] memory) { return vm.parseJsonIntArray(json, key); } + /// @notice Reads a bytes32 value at `key` from `json`. function readBytes32(string memory json, string memory key) internal pure returns (bytes32) { return vm.parseJsonBytes32(json, key); } + /// @notice Reads a bytes32 array at `key` from `json`. function readBytes32Array(string memory json, string memory key) internal pure returns (bytes32[] memory) { return vm.parseJsonBytes32Array(json, key); } + /// @notice Reads a string value at `key` from `json`. function readString(string memory json, string memory key) internal pure returns (string memory) { return vm.parseJsonString(json, key); } + /// @notice Reads a string array at `key` from `json`. function readStringArray(string memory json, string memory key) internal pure returns (string[] memory) { return vm.parseJsonStringArray(json, key); } + /// @notice Reads an address value at `key` from `json`. function readAddress(string memory json, string memory key) internal pure returns (address) { return vm.parseJsonAddress(json, key); } + /// @notice Reads an address array at `key` from `json`. function readAddressArray(string memory json, string memory key) internal pure returns (address[] memory) { return vm.parseJsonAddressArray(json, key); } + /// @notice Reads a bool value at `key` from `json`. function readBool(string memory json, string memory key) internal pure returns (bool) { return vm.parseJsonBool(json, key); } + /// @notice Reads a bool array at `key` from `json`. function readBoolArray(string memory json, string memory key) internal pure returns (bool[] memory) { return vm.parseJsonBoolArray(json, key); } + /// @notice Reads a bytes value at `key` from `json`. function readBytes(string memory json, string memory key) internal pure returns (bytes memory) { return vm.parseJsonBytes(json, key); } + /// @notice Reads a bytes array at `key` from `json`. function readBytesArray(string memory json, string memory key) internal pure returns (bytes[] memory) { return vm.parseJsonBytesArray(json, key); } + /// @notice Reads a uint256 value at `key` from `json`, returning `defaultValue` if the key does not exist. function readUintOr(string memory json, string memory key, uint256 defaultValue) internal view returns (uint256) { return keyExists(json, key) ? readUint(json, key) : defaultValue; } + /// @notice Reads a uint256 array at `key` from `json`, returning `defaultValue` if the key does not exist. function readUintArrayOr(string memory json, string memory key, uint256[] memory defaultValue) internal view @@ -101,10 +122,12 @@ library stdJson { return keyExists(json, key) ? readUintArray(json, key) : defaultValue; } + /// @notice Reads an int256 value at `key` from `json`, returning `defaultValue` if the key does not exist. function readIntOr(string memory json, string memory key, int256 defaultValue) internal view returns (int256) { return keyExists(json, key) ? readInt(json, key) : defaultValue; } + /// @notice Reads an int256 array at `key` from `json`, returning `defaultValue` if the key does not exist. function readIntArrayOr(string memory json, string memory key, int256[] memory defaultValue) internal view @@ -113,6 +136,7 @@ library stdJson { return keyExists(json, key) ? readIntArray(json, key) : defaultValue; } + /// @notice Reads a bytes32 value at `key` from `json`, returning `defaultValue` if the key does not exist. function readBytes32Or(string memory json, string memory key, bytes32 defaultValue) internal view @@ -121,6 +145,7 @@ library stdJson { return keyExists(json, key) ? readBytes32(json, key) : defaultValue; } + /// @notice Reads a bytes32 array at `key` from `json`, returning `defaultValue` if the key does not exist. function readBytes32ArrayOr(string memory json, string memory key, bytes32[] memory defaultValue) internal view @@ -129,6 +154,7 @@ library stdJson { return keyExists(json, key) ? readBytes32Array(json, key) : defaultValue; } + /// @notice Reads a string value at `key` from `json`, returning `defaultValue` if the key does not exist. function readStringOr(string memory json, string memory key, string memory defaultValue) internal view @@ -137,6 +163,7 @@ library stdJson { return keyExists(json, key) ? readString(json, key) : defaultValue; } + /// @notice Reads a string array at `key` from `json`, returning `defaultValue` if the key does not exist. function readStringArrayOr(string memory json, string memory key, string[] memory defaultValue) internal view @@ -145,6 +172,7 @@ library stdJson { return keyExists(json, key) ? readStringArray(json, key) : defaultValue; } + /// @notice Reads an address value at `key` from `json`, returning `defaultValue` if the key does not exist. function readAddressOr(string memory json, string memory key, address defaultValue) internal view @@ -153,6 +181,7 @@ library stdJson { return keyExists(json, key) ? readAddress(json, key) : defaultValue; } + /// @notice Reads an address array at `key` from `json`, returning `defaultValue` if the key does not exist. function readAddressArrayOr(string memory json, string memory key, address[] memory defaultValue) internal view @@ -161,10 +190,12 @@ library stdJson { return keyExists(json, key) ? readAddressArray(json, key) : defaultValue; } + /// @notice Reads a bool value at `key` from `json`, returning `defaultValue` if the key does not exist. function readBoolOr(string memory json, string memory key, bool defaultValue) internal view returns (bool) { return keyExists(json, key) ? readBool(json, key) : defaultValue; } + /// @notice Reads a bool array at `key` from `json`, returning `defaultValue` if the key does not exist. function readBoolArrayOr(string memory json, string memory key, bool[] memory defaultValue) internal view @@ -173,6 +204,7 @@ library stdJson { return keyExists(json, key) ? readBoolArray(json, key) : defaultValue; } + /// @notice Reads a bytes value at `key` from `json`, returning `defaultValue` if the key does not exist. function readBytesOr(string memory json, string memory key, bytes memory defaultValue) internal view @@ -181,6 +213,7 @@ library stdJson { return keyExists(json, key) ? readBytes(json, key) : defaultValue; } + /// @notice Reads a bytes array at `key` from `json`, returning `defaultValue` if the key does not exist. function readBytesArrayOr(string memory json, string memory key, bytes[] memory defaultValue) internal view @@ -189,25 +222,27 @@ library stdJson { return keyExists(json, key) ? readBytesArray(json, key) : defaultValue; } + /// @notice Serializes a JSON object `rootObject` under `jsonKey` and returns the serialized JSON string. function serialize(string memory jsonKey, string memory rootObject) internal returns (string memory) { return vm.serializeJson(jsonKey, rootObject); } + /// @notice Serializes a bool `value` under `key` within `jsonKey` and returns the serialized JSON string. function serialize(string memory jsonKey, string memory key, bool value) internal returns (string memory) { return vm.serializeBool(jsonKey, key, value); } - function serialize(string memory jsonKey, string memory key, bool[] memory value) - internal - returns (string memory) - { + /// @notice Serializes a bool array `value` under `key` within `jsonKey` and returns the serialized JSON string. + function serialize(string memory jsonKey, string memory key, bool[] memory value) internal returns (string memory) { return vm.serializeBool(jsonKey, key, value); } + /// @notice Serializes a uint256 `value` under `key` within `jsonKey` and returns the serialized JSON string. function serialize(string memory jsonKey, string memory key, uint256 value) internal returns (string memory) { return vm.serializeUint(jsonKey, key, value); } + /// @notice Serializes a uint256 array `value` under `key` within `jsonKey` and returns the serialized JSON string. function serialize(string memory jsonKey, string memory key, uint256[] memory value) internal returns (string memory) @@ -215,10 +250,12 @@ library stdJson { return vm.serializeUint(jsonKey, key, value); } + /// @notice Serializes an int256 `value` under `key` within `jsonKey` and returns the serialized JSON string. function serialize(string memory jsonKey, string memory key, int256 value) internal returns (string memory) { return vm.serializeInt(jsonKey, key, value); } + /// @notice Serializes an int256 array `value` under `key` within `jsonKey` and returns the serialized JSON string. function serialize(string memory jsonKey, string memory key, int256[] memory value) internal returns (string memory) @@ -226,10 +263,12 @@ library stdJson { return vm.serializeInt(jsonKey, key, value); } + /// @notice Serializes an address `value` under `key` within `jsonKey` and returns the serialized JSON string. function serialize(string memory jsonKey, string memory key, address value) internal returns (string memory) { return vm.serializeAddress(jsonKey, key, value); } + /// @notice Serializes an address array `value` under `key` within `jsonKey` and returns the serialized JSON string. function serialize(string memory jsonKey, string memory key, address[] memory value) internal returns (string memory) @@ -237,10 +276,12 @@ library stdJson { return vm.serializeAddress(jsonKey, key, value); } + /// @notice Serializes a bytes32 `value` under `key` within `jsonKey` and returns the serialized JSON string. function serialize(string memory jsonKey, string memory key, bytes32 value) internal returns (string memory) { return vm.serializeBytes32(jsonKey, key, value); } + /// @notice Serializes a bytes32 array `value` under `key` within `jsonKey` and returns the serialized JSON string. function serialize(string memory jsonKey, string memory key, bytes32[] memory value) internal returns (string memory) @@ -248,10 +289,12 @@ library stdJson { return vm.serializeBytes32(jsonKey, key, value); } + /// @notice Serializes a bytes `value` under `key` within `jsonKey` and returns the serialized JSON string. function serialize(string memory jsonKey, string memory key, bytes memory value) internal returns (string memory) { return vm.serializeBytes(jsonKey, key, value); } + /// @notice Serializes a bytes array `value` under `key` within `jsonKey` and returns the serialized JSON string. function serialize(string memory jsonKey, string memory key, bytes[] memory value) internal returns (string memory) @@ -259,13 +302,12 @@ library stdJson { return vm.serializeBytes(jsonKey, key, value); } - function serialize(string memory jsonKey, string memory key, string memory value) - internal - returns (string memory) - { + /// @notice Serializes a string `value` under `key` within `jsonKey` and returns the serialized JSON string. + function serialize(string memory jsonKey, string memory key, string memory value) internal returns (string memory) { return vm.serializeString(jsonKey, key, value); } + /// @notice Serializes a string array `value` under `key` within `jsonKey` and returns the serialized JSON string. function serialize(string memory jsonKey, string memory key, string[] memory value) internal returns (string memory) @@ -273,10 +315,12 @@ library stdJson { return vm.serializeString(jsonKey, key, value); } + /// @notice Writes the serialized JSON object `jsonKey` to `path`. function write(string memory jsonKey, string memory path) internal { vm.writeJson(jsonKey, path); } + /// @notice Writes the value at `valueKey` from the serialized JSON object `jsonKey` to `path`. function write(string memory jsonKey, string memory path, string memory valueKey) internal { vm.writeJson(jsonKey, path, valueKey); } diff --git a/dependencies/forge-std-1.16.2/src/StdMath.sol b/dependencies/forge-std-1.16.2/src/StdMath.sol new file mode 100644 index 0000000..19942f7 --- /dev/null +++ b/dependencies/forge-std-1.16.2/src/StdMath.sol @@ -0,0 +1,68 @@ +// SPDX-License-Identifier: MIT OR Apache-2.0 +pragma solidity >=0.8.13 <0.9.0; + +/// @notice Mathematical utility functions for unsigned and signed integers. +library stdMath { + int256 private constant _INT256_MIN = + -57896044618658097711785492504343953926634992332820282019728792003956564819968; + + /// @notice Computes the absolute value of a signed integer. + /// @param a The signed integer to compute the absolute value of. + /// @return The absolute value as an unsigned integer. + function abs(int256 a) internal pure returns (uint256) { + // Required or it will fail when `a = type(int256).min` + if (a == _INT256_MIN) { + return 57896044618658097711785492504343953926634992332820282019728792003956564819968; + } + + return uint256(a > 0 ? a : -a); + } + + /// @notice Computes the absolute difference between two unsigned integers. + /// @param a The first unsigned integer. + /// @param b The second unsigned integer. + /// @return The absolute difference between `a` and `b`. + function delta(uint256 a, uint256 b) internal pure returns (uint256) { + return a > b ? a - b : b - a; + } + + /// @notice Computes the absolute difference between two signed integers. + /// @param a The first signed integer. + /// @param b The second signed integer. + /// @return The absolute difference between `a` and `b`. + function delta(int256 a, int256 b) internal pure returns (uint256) { + // a and b are of the same sign + // this works thanks to two's complement, the left-most bit is the sign bit + if ((a ^ b) > -1) { + return delta(abs(a), abs(b)); + } + + // a and b are of opposite signs + return abs(a) + abs(b); + } + + /// @notice Computes the percentage difference between two unsigned integers, scaled by 1e18. + /// @param a The value to compare. + /// @param b The reference value (divisor). Must not be zero. + /// @return The percentage difference scaled by 1e18 (1e18 represents 100%). + function percentDelta(uint256 a, uint256 b) internal pure returns (uint256) { + // Prevent division by zero + require(b != 0, "stdMath percentDelta(uint256,uint256): Divisor is zero"); + uint256 absDelta = delta(a, b); + + return absDelta * 1e18 / b; + } + + /// @notice Computes the percentage difference between two signed integers, scaled by 1e18. + /// @param a The value to compare. + /// @param b The reference value (divisor). Its absolute value must not be zero. + /// @return The percentage difference scaled by 1e18 (1e18 represents 100%). + function percentDelta(int256 a, int256 b) internal pure returns (uint256) { + uint256 absDelta = delta(a, b); + uint256 absB = abs(b); + // Prevent division by zero + require(absB != 0, "stdMath percentDelta(int256,int256): Divisor is zero"); + + return absDelta * 1e18 / absB; + } +} diff --git a/dependencies/forge-std-1.11.0/src/StdStorage.sol b/dependencies/forge-std-1.16.2/src/StdStorage.sol similarity index 72% rename from dependencies/forge-std-1.11.0/src/StdStorage.sol rename to dependencies/forge-std-1.16.2/src/StdStorage.sol index 1627af7..3035880 100644 --- a/dependencies/forge-std-1.11.0/src/StdStorage.sol +++ b/dependencies/forge-std-1.16.2/src/StdStorage.sol @@ -1,5 +1,5 @@ -// SPDX-License-Identifier: MIT -pragma solidity >=0.6.2 <0.9.0; +// SPDX-License-Identifier: MIT OR Apache-2.0 +pragma solidity >=0.8.13 <0.9.0; import {Vm} from "./Vm.sol"; @@ -28,30 +28,31 @@ library stdStorageSafe { Vm private constant vm = Vm(address(uint160(uint256(keccak256("hevm cheat code"))))); uint256 constant UINT256_MAX = 115792089237316195423570985008687907853269984665640564039457584007913129639935; + /// @notice Returns the 4-byte function selector for `sigStr`. function sigs(string memory sigStr) internal pure returns (bytes4) { return bytes4(keccak256(bytes(sigStr))); } + /// @notice Returns the encoded call parameters (keys or raw calldata) for the configured target function. function getCallParams(StdStorage storage self) internal view returns (bytes memory) { if (self._calldata.length == 0) { - return flatten(self._keys); + return _flatten(self._keys); } else { return self._calldata; } } - // Calls target contract with configured parameters + /// @notice Calls the target contract with the configured parameters and returns the success flag and return value. function callTarget(StdStorage storage self) internal view returns (bool, bytes32) { bytes memory cd = abi.encodePacked(self._sig, getCallParams(self)); (bool success, bytes memory rdat) = self._target.staticcall(cd); - bytes32 result = bytesToBytes32(rdat, 32 * self._depth); + bytes32 result = _bytesToBytes32(rdat, 32 * self._depth); return (success, result); } - // Tries mutating slot value to determine if the targeted value is stored in it. - // If current value is 0, then we are setting slot value to type(uint256).max - // Otherwise, we set it to 0. That way, return value should always be affected. + /// @notice Returns whether mutating `slot` changes the return value of the configured target call. + /// @dev Temporarily writes either `type(uint256).max` or `0` to the slot to detect sensitivity. function checkSlotMutatesCall(StdStorage storage self, bytes32 slot) internal returns (bool) { bytes32 prevSlotValue = vm.load(self._target, slot); (bool success, bytes32 prevReturnValue) = callTarget(self); @@ -66,8 +67,7 @@ library stdStorageSafe { return (success && (prevReturnValue != newReturnValue)); } - // Tries setting one of the bits in slot to 1 until return value changes. - // Index of resulted bit is an offset packed slot has from left/right side + /// @notice Searches for the bit offset of the packed variable within `slot` from the left or right side. function findOffset(StdStorage storage self, bytes32 slot, bool left) internal returns (bool, uint256) { for (uint256 offset = 0; offset < 256; offset++) { uint256 valueToPut = left ? (1 << (255 - offset)) : (1 << offset); @@ -82,6 +82,7 @@ library stdStorageSafe { return (false, 0); } + /// @notice Returns whether both offsets were found, along with the left and right bit offsets of the packed variable within `slot`. function findOffsets(StdStorage storage self, bytes32 slot) internal returns (bool, uint256, uint256) { bytes32 prevSlotValue = vm.load(self._target, slot); @@ -93,6 +94,7 @@ library stdStorageSafe { return (foundLeft && foundRight, offsetLeft, offsetRight); } + /// @notice Finds the storage slot for the configured target and returns its data, clearing the configuration. function find(StdStorage storage self) internal returns (FindData storage) { return find(self, true); } @@ -123,7 +125,8 @@ library stdStorageSafe { if (reads.length == 0) { revert("stdStorage find(StdStorage): No storage use detected for target."); } else { - for (uint256 i = reads.length; --i >= 0;) { + for (uint256 i = reads.length; i > 0;) { + --i; bytes32 prev = vm.load(who, reads[i]); if (prev == bytes32(0)) { emit WARNING_UninitedSlot(who, uint256(reads[i])); @@ -168,52 +171,61 @@ library stdStorageSafe { return self.finds[who][fsig][keccak256(abi.encodePacked(params, field_depth))]; } + /// @notice Sets the target contract address for the storage lookup. function target(StdStorage storage self, address _target) internal returns (StdStorage storage) { self._target = _target; return self; } + /// @notice Sets the target function selector for the storage lookup. function sig(StdStorage storage self, bytes4 _sig) internal returns (StdStorage storage) { self._sig = _sig; return self; } + /// @notice Sets the target function selector from a signature string for the storage lookup. function sig(StdStorage storage self, string memory _sig) internal returns (StdStorage storage) { self._sig = sigs(_sig); return self; } + /// @notice Sets raw calldata to use instead of ABI-encoded keys for the target call. function with_calldata(StdStorage storage self, bytes memory _calldata) internal returns (StdStorage storage) { self._calldata = _calldata; return self; } + /// @notice Adds an address mapping key to the storage lookup path. function with_key(StdStorage storage self, address who) internal returns (StdStorage storage) { self._keys.push(bytes32(uint256(uint160(who)))); return self; } + /// @notice Adds a uint256 mapping key to the storage lookup path. function with_key(StdStorage storage self, uint256 amt) internal returns (StdStorage storage) { self._keys.push(bytes32(amt)); return self; } + /// @notice Adds a bytes32 mapping key to the storage lookup path. function with_key(StdStorage storage self, bytes32 key) internal returns (StdStorage storage) { self._keys.push(key); return self; } + /// @notice Enables detection and handling of values packed into shared storage slots. function enable_packed_slots(StdStorage storage self) internal returns (StdStorage storage) { self._enable_packed_slots = true; return self; } + /// @notice Sets the struct field depth for storage lookups into nested structs. function depth(StdStorage storage self, uint256 _depth) internal returns (StdStorage storage) { self._depth = _depth; return self; } - function read(StdStorage storage self) private returns (bytes memory) { + function _read(StdStorage storage self) private returns (bytes memory) { FindData storage data = find(self, false); uint256 mask = getMaskByOffsets(data.offsetLeft, data.offsetRight); uint256 value = (uint256(vm.load(self._target, bytes32(data.slot))) & mask) >> data.offsetRight; @@ -221,10 +233,13 @@ library stdStorageSafe { return abi.encode(value); } + /// @notice Reads the found storage slot value as bytes32. function read_bytes32(StdStorage storage self) internal returns (bytes32) { - return abi.decode(read(self), (bytes32)); + return abi.decode(_read(self), (bytes32)); } + /// @notice Reads the found storage slot value as bool. + /// @dev Reverts if the stored value is neither `0` nor `1`. function read_bool(StdStorage storage self) internal returns (bool) { int256 v = read_int(self); if (v == 0) return false; @@ -232,18 +247,22 @@ library stdStorageSafe { revert("stdStorage read_bool(StdStorage): Cannot decode. Make sure you are reading a bool."); } + /// @notice Reads the found storage slot value as address. function read_address(StdStorage storage self) internal returns (address) { - return abi.decode(read(self), (address)); + return abi.decode(_read(self), (address)); } + /// @notice Reads the found storage slot value as uint256. function read_uint(StdStorage storage self) internal returns (uint256) { - return abi.decode(read(self), (uint256)); + return abi.decode(_read(self), (uint256)); } + /// @notice Reads the found storage slot value as int256. function read_int(StdStorage storage self) internal returns (int256) { - return abi.decode(read(self), (int256)); + return abi.decode(_read(self), (int256)); } + /// @notice Returns the parent mapping slot index and the key used to reach the found slot. function parent(StdStorage storage self) internal returns (uint256, bytes32) { address who = self._target; uint256 field_depth = self._depth; @@ -252,12 +271,13 @@ library stdStorageSafe { (bool found, bytes32 key, bytes32 parent_slot) = vm.getMappingKeyAndParentOf(who, bytes32(child)); if (!found) { revert( - "stdStorage read_bool(StdStorage): Cannot find parent. Make sure you give a slot and startMappingRecording() has been called." + "stdStorage parent(StdStorage): Cannot find parent. Make sure you give a slot and startMappingRecording() has been called." ); } return (uint256(parent_slot), key); } + /// @notice Returns the root mapping slot index by traversing the mapping parent chain. function root(StdStorage storage self) internal returns (uint256) { address who = self._target; uint256 field_depth = self._depth; @@ -269,7 +289,7 @@ library stdStorageSafe { (found,, parent_slot) = vm.getMappingKeyAndParentOf(who, bytes32(child)); if (!found) { revert( - "stdStorage read_bool(StdStorage): Cannot find parent. Make sure you give a slot and startMappingRecording() has been called." + "stdStorage root(StdStorage): Cannot find parent. Make sure you give a slot and startMappingRecording() has been called." ); } while (found) { @@ -279,22 +299,25 @@ library stdStorageSafe { return uint256(root_slot); } - function bytesToBytes32(bytes memory b, uint256 offset) private pure returns (bytes32) { + function _bytesToBytes32(bytes memory b, uint256 offset) private pure returns (bytes32) { bytes32 out; - uint256 max = b.length > 32 ? 32 : b.length; + // Cap read length by remaining bytes from `offset`, and at most 32 bytes to avoid out-of-bounds + uint256 max = b.length > offset ? b.length - offset : 0; + if (max > 32) { + max = 32; + } for (uint256 i = 0; i < max; i++) { out |= bytes32(b[offset + i] & 0xFF) >> (i * 8); } return out; } - function flatten(bytes32[] memory b) private pure returns (bytes memory) { + function _flatten(bytes32[] memory b) private pure returns (bytes memory) { bytes memory result = new bytes(b.length * 32); for (uint256 i = 0; i < b.length; i++) { bytes32 k = b[i]; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(add(result, add(32, mul(32, i))), k) } } @@ -302,6 +325,7 @@ library stdStorageSafe { return result; } + /// @notice Resets all configured parameters on `self`. function clear(StdStorage storage self) internal { delete self._target; delete self._sig; @@ -311,8 +335,8 @@ library stdStorageSafe { delete self._calldata; } - // Returns mask which contains non-zero bits for values between `offsetLeft` and `offsetRight` - // (slotValue & mask) >> offsetRight will be the value of the given packed variable + /// @notice Returns a bitmask with ones in the bit range `[offsetRight, 255 - offsetLeft]`. + /// @dev `(slotValue & mask) >> offsetRight` extracts the packed variable's value. function getMaskByOffsets(uint256 offsetLeft, uint256 offsetRight) internal pure returns (uint256 mask) { // mask = ((1 << (256 - (offsetRight + offsetLeft))) - 1) << offsetRight; // using assembly because (1 << 256) causes overflow @@ -321,7 +345,7 @@ library stdStorageSafe { } } - // Returns slot value with updated packed variable. + /// @notice Returns `curValue` with the packed variable at `[offsetRight, 255 - offsetLeft]` replaced by `varValue`. function getUpdatedSlotValue(bytes32 curValue, uint256 varValue, uint256 offsetLeft, uint256 offsetRight) internal pure @@ -334,79 +358,96 @@ library stdStorageSafe { library stdStorage { Vm private constant vm = Vm(address(uint160(uint256(keccak256("hevm cheat code"))))); + /// @notice Returns the 4-byte function selector for `sigStr`. function sigs(string memory sigStr) internal pure returns (bytes4) { return stdStorageSafe.sigs(sigStr); } + /// @notice Finds the storage slot index for the configured target, clearing the configuration. function find(StdStorage storage self) internal returns (uint256) { return find(self, true); } + /// @notice Finds the storage slot index for the configured target, optionally clearing the configuration. function find(StdStorage storage self, bool _clear) internal returns (uint256) { return stdStorageSafe.find(self, _clear).slot; } + /// @notice Sets the target contract address for the storage lookup. function target(StdStorage storage self, address _target) internal returns (StdStorage storage) { return stdStorageSafe.target(self, _target); } + /// @notice Sets the target function selector for the storage lookup. function sig(StdStorage storage self, bytes4 _sig) internal returns (StdStorage storage) { return stdStorageSafe.sig(self, _sig); } + /// @notice Sets the target function selector from a signature string for the storage lookup. function sig(StdStorage storage self, string memory _sig) internal returns (StdStorage storage) { return stdStorageSafe.sig(self, _sig); } + /// @notice Adds an address mapping key to the storage lookup path. function with_key(StdStorage storage self, address who) internal returns (StdStorage storage) { return stdStorageSafe.with_key(self, who); } + /// @notice Adds a uint256 mapping key to the storage lookup path. function with_key(StdStorage storage self, uint256 amt) internal returns (StdStorage storage) { return stdStorageSafe.with_key(self, amt); } + /// @notice Adds a bytes32 mapping key to the storage lookup path. function with_key(StdStorage storage self, bytes32 key) internal returns (StdStorage storage) { return stdStorageSafe.with_key(self, key); } + /// @notice Sets raw calldata to use instead of ABI-encoded keys for the target call. function with_calldata(StdStorage storage self, bytes memory _calldata) internal returns (StdStorage storage) { return stdStorageSafe.with_calldata(self, _calldata); } + /// @notice Enables detection and handling of values packed into shared storage slots. function enable_packed_slots(StdStorage storage self) internal returns (StdStorage storage) { return stdStorageSafe.enable_packed_slots(self); } + /// @notice Sets the struct field depth for storage lookups into nested structs. function depth(StdStorage storage self, uint256 _depth) internal returns (StdStorage storage) { return stdStorageSafe.depth(self, _depth); } + /// @notice Resets all configured parameters on `self`. function clear(StdStorage storage self) internal { stdStorageSafe.clear(self); } + /// @notice Writes `who` to the found storage slot and verifies the value was applied correctly. function checked_write(StdStorage storage self, address who) internal { checked_write(self, bytes32(uint256(uint160(who)))); } + /// @notice Writes `amt` to the found storage slot and verifies the value was applied correctly. function checked_write(StdStorage storage self, uint256 amt) internal { checked_write(self, bytes32(amt)); } + /// @notice Writes `val` to the found storage slot and verifies the value was applied correctly. function checked_write_int(StdStorage storage self, int256 val) internal { checked_write(self, bytes32(uint256(val))); } + /// @notice Writes `write` to the found storage slot and verifies the value was applied correctly. function checked_write(StdStorage storage self, bool write) internal { bytes32 t; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { t := write } checked_write(self, t); } + /// @notice Writes `set` to the found storage slot and verifies the value was applied correctly. function checked_write(StdStorage storage self, bytes32 set) internal { address who = self._target; bytes4 fsig = self._sig; @@ -423,7 +464,7 @@ library stdStorage { uint256(set) < maxVal, string( abi.encodePacked( - "stdStorage find(StdStorage): Packed slot. We can't fit value greater than ", + "stdStorage checked_write(StdStorage): Packed slot. We can't fit value greater than ", vm.toString(maxVal) ) ) @@ -438,35 +479,42 @@ library stdStorage { if (!success || callResult != set) { vm.store(who, bytes32(data.slot), curVal); - revert("stdStorage find(StdStorage): Failed to write value."); + revert("stdStorage checked_write(StdStorage): Failed to write value."); } clear(self); } + /// @notice Reads the found storage slot value as bytes32. function read_bytes32(StdStorage storage self) internal returns (bytes32) { return stdStorageSafe.read_bytes32(self); } + /// @notice Reads the found storage slot value as bool. function read_bool(StdStorage storage self) internal returns (bool) { return stdStorageSafe.read_bool(self); } + /// @notice Reads the found storage slot value as address. function read_address(StdStorage storage self) internal returns (address) { return stdStorageSafe.read_address(self); } + /// @notice Reads the found storage slot value as uint256. function read_uint(StdStorage storage self) internal returns (uint256) { return stdStorageSafe.read_uint(self); } + /// @notice Reads the found storage slot value as int256. function read_int(StdStorage storage self) internal returns (int256) { return stdStorageSafe.read_int(self); } + /// @notice Returns the parent mapping slot index and the key used to reach the found slot. function parent(StdStorage storage self) internal returns (uint256, bytes32) { return stdStorageSafe.parent(self); } + /// @notice Returns the root mapping slot index by traversing the mapping parent chain. function root(StdStorage storage self) internal returns (uint256) { return stdStorageSafe.root(self); } diff --git a/dependencies/forge-std-1.11.0/src/StdStyle.sol b/dependencies/forge-std-1.16.2/src/StdStyle.sol similarity index 56% rename from dependencies/forge-std-1.11.0/src/StdStyle.sol rename to dependencies/forge-std-1.16.2/src/StdStyle.sol index d371e0c..33b815f 100644 --- a/dependencies/forge-std-1.11.0/src/StdStyle.sol +++ b/dependencies/forge-std-1.16.2/src/StdStyle.sol @@ -1,5 +1,5 @@ -// SPDX-License-Identifier: MIT -pragma solidity >=0.4.22 <0.9.0; +// SPDX-License-Identifier: MIT OR Apache-2.0 +pragma solidity >=0.8.13 <0.9.0; import {VmSafe} from "./Vm.sol"; @@ -19,314 +19,391 @@ library StdStyle { string constant INVERSE = "\u001b[7m"; string constant RESET = "\u001b[0m"; - function styleConcat(string memory style, string memory self) private pure returns (string memory) { + function _styleConcat(string memory style, string memory self) private pure returns (string memory) { return string(abi.encodePacked(style, self, RESET)); } + /// @notice Returns `self` wrapped in red ANSI color codes. function red(string memory self) internal pure returns (string memory) { - return styleConcat(RED, self); + return _styleConcat(RED, self); } + /// @notice Returns the string representation of `self` wrapped in red ANSI color codes. function red(uint256 self) internal pure returns (string memory) { return red(vm.toString(self)); } + /// @notice Returns the string representation of `self` wrapped in red ANSI color codes. function red(int256 self) internal pure returns (string memory) { return red(vm.toString(self)); } + /// @notice Returns the string representation of `self` wrapped in red ANSI color codes. function red(address self) internal pure returns (string memory) { return red(vm.toString(self)); } + /// @notice Returns the string representation of `self` wrapped in red ANSI color codes. function red(bool self) internal pure returns (string memory) { return red(vm.toString(self)); } + /// @notice Returns the string representation of `self` wrapped in red ANSI color codes. function redBytes(bytes memory self) internal pure returns (string memory) { return red(vm.toString(self)); } + /// @notice Returns the string representation of `self` wrapped in red ANSI color codes. function redBytes32(bytes32 self) internal pure returns (string memory) { return red(vm.toString(self)); } + /// @notice Returns `self` wrapped in green ANSI color codes. function green(string memory self) internal pure returns (string memory) { - return styleConcat(GREEN, self); + return _styleConcat(GREEN, self); } + /// @notice Returns the string representation of `self` wrapped in green ANSI color codes. function green(uint256 self) internal pure returns (string memory) { return green(vm.toString(self)); } + /// @notice Returns the string representation of `self` wrapped in green ANSI color codes. function green(int256 self) internal pure returns (string memory) { return green(vm.toString(self)); } + /// @notice Returns the string representation of `self` wrapped in green ANSI color codes. function green(address self) internal pure returns (string memory) { return green(vm.toString(self)); } + /// @notice Returns the string representation of `self` wrapped in green ANSI color codes. function green(bool self) internal pure returns (string memory) { return green(vm.toString(self)); } + /// @notice Returns the string representation of `self` wrapped in green ANSI color codes. function greenBytes(bytes memory self) internal pure returns (string memory) { return green(vm.toString(self)); } + /// @notice Returns the string representation of `self` wrapped in green ANSI color codes. function greenBytes32(bytes32 self) internal pure returns (string memory) { return green(vm.toString(self)); } + /// @notice Returns `self` wrapped in yellow ANSI color codes. function yellow(string memory self) internal pure returns (string memory) { - return styleConcat(YELLOW, self); + return _styleConcat(YELLOW, self); } + /// @notice Returns the string representation of `self` wrapped in yellow ANSI color codes. function yellow(uint256 self) internal pure returns (string memory) { return yellow(vm.toString(self)); } + /// @notice Returns the string representation of `self` wrapped in yellow ANSI color codes. function yellow(int256 self) internal pure returns (string memory) { return yellow(vm.toString(self)); } + /// @notice Returns the string representation of `self` wrapped in yellow ANSI color codes. function yellow(address self) internal pure returns (string memory) { return yellow(vm.toString(self)); } + /// @notice Returns the string representation of `self` wrapped in yellow ANSI color codes. function yellow(bool self) internal pure returns (string memory) { return yellow(vm.toString(self)); } + /// @notice Returns the string representation of `self` wrapped in yellow ANSI color codes. function yellowBytes(bytes memory self) internal pure returns (string memory) { return yellow(vm.toString(self)); } + /// @notice Returns the string representation of `self` wrapped in yellow ANSI color codes. function yellowBytes32(bytes32 self) internal pure returns (string memory) { return yellow(vm.toString(self)); } + /// @notice Returns `self` wrapped in blue ANSI color codes. function blue(string memory self) internal pure returns (string memory) { - return styleConcat(BLUE, self); + return _styleConcat(BLUE, self); } + /// @notice Returns the string representation of `self` wrapped in blue ANSI color codes. function blue(uint256 self) internal pure returns (string memory) { return blue(vm.toString(self)); } + /// @notice Returns the string representation of `self` wrapped in blue ANSI color codes. function blue(int256 self) internal pure returns (string memory) { return blue(vm.toString(self)); } + /// @notice Returns the string representation of `self` wrapped in blue ANSI color codes. function blue(address self) internal pure returns (string memory) { return blue(vm.toString(self)); } + /// @notice Returns the string representation of `self` wrapped in blue ANSI color codes. function blue(bool self) internal pure returns (string memory) { return blue(vm.toString(self)); } + /// @notice Returns the string representation of `self` wrapped in blue ANSI color codes. function blueBytes(bytes memory self) internal pure returns (string memory) { return blue(vm.toString(self)); } + /// @notice Returns the string representation of `self` wrapped in blue ANSI color codes. function blueBytes32(bytes32 self) internal pure returns (string memory) { return blue(vm.toString(self)); } + /// @notice Returns `self` wrapped in magenta ANSI color codes. function magenta(string memory self) internal pure returns (string memory) { - return styleConcat(MAGENTA, self); + return _styleConcat(MAGENTA, self); } + /// @notice Returns the string representation of `self` wrapped in magenta ANSI color codes. function magenta(uint256 self) internal pure returns (string memory) { return magenta(vm.toString(self)); } + /// @notice Returns the string representation of `self` wrapped in magenta ANSI color codes. function magenta(int256 self) internal pure returns (string memory) { return magenta(vm.toString(self)); } + /// @notice Returns the string representation of `self` wrapped in magenta ANSI color codes. function magenta(address self) internal pure returns (string memory) { return magenta(vm.toString(self)); } + /// @notice Returns the string representation of `self` wrapped in magenta ANSI color codes. function magenta(bool self) internal pure returns (string memory) { return magenta(vm.toString(self)); } + /// @notice Returns the string representation of `self` wrapped in magenta ANSI color codes. function magentaBytes(bytes memory self) internal pure returns (string memory) { return magenta(vm.toString(self)); } + /// @notice Returns the string representation of `self` wrapped in magenta ANSI color codes. function magentaBytes32(bytes32 self) internal pure returns (string memory) { return magenta(vm.toString(self)); } + /// @notice Returns `self` wrapped in cyan ANSI color codes. function cyan(string memory self) internal pure returns (string memory) { - return styleConcat(CYAN, self); + return _styleConcat(CYAN, self); } + /// @notice Returns the string representation of `self` wrapped in cyan ANSI color codes. function cyan(uint256 self) internal pure returns (string memory) { return cyan(vm.toString(self)); } + /// @notice Returns the string representation of `self` wrapped in cyan ANSI color codes. function cyan(int256 self) internal pure returns (string memory) { return cyan(vm.toString(self)); } + /// @notice Returns the string representation of `self` wrapped in cyan ANSI color codes. function cyan(address self) internal pure returns (string memory) { return cyan(vm.toString(self)); } + /// @notice Returns the string representation of `self` wrapped in cyan ANSI color codes. function cyan(bool self) internal pure returns (string memory) { return cyan(vm.toString(self)); } + /// @notice Returns the string representation of `self` wrapped in cyan ANSI color codes. function cyanBytes(bytes memory self) internal pure returns (string memory) { return cyan(vm.toString(self)); } + /// @notice Returns the string representation of `self` wrapped in cyan ANSI color codes. function cyanBytes32(bytes32 self) internal pure returns (string memory) { return cyan(vm.toString(self)); } + /// @notice Returns `self` wrapped in bold ANSI style codes. function bold(string memory self) internal pure returns (string memory) { - return styleConcat(BOLD, self); + return _styleConcat(BOLD, self); } + /// @notice Returns the string representation of `self` wrapped in bold ANSI style codes. function bold(uint256 self) internal pure returns (string memory) { return bold(vm.toString(self)); } + /// @notice Returns the string representation of `self` wrapped in bold ANSI style codes. function bold(int256 self) internal pure returns (string memory) { return bold(vm.toString(self)); } + /// @notice Returns the string representation of `self` wrapped in bold ANSI style codes. function bold(address self) internal pure returns (string memory) { return bold(vm.toString(self)); } + /// @notice Returns the string representation of `self` wrapped in bold ANSI style codes. function bold(bool self) internal pure returns (string memory) { return bold(vm.toString(self)); } + /// @notice Returns the string representation of `self` wrapped in bold ANSI style codes. function boldBytes(bytes memory self) internal pure returns (string memory) { return bold(vm.toString(self)); } + /// @notice Returns the string representation of `self` wrapped in bold ANSI style codes. function boldBytes32(bytes32 self) internal pure returns (string memory) { return bold(vm.toString(self)); } + /// @notice Returns `self` wrapped in dim ANSI style codes. function dim(string memory self) internal pure returns (string memory) { - return styleConcat(DIM, self); + return _styleConcat(DIM, self); } + /// @notice Returns the string representation of `self` wrapped in dim ANSI style codes. function dim(uint256 self) internal pure returns (string memory) { return dim(vm.toString(self)); } + /// @notice Returns the string representation of `self` wrapped in dim ANSI style codes. function dim(int256 self) internal pure returns (string memory) { return dim(vm.toString(self)); } + /// @notice Returns the string representation of `self` wrapped in dim ANSI style codes. function dim(address self) internal pure returns (string memory) { return dim(vm.toString(self)); } + /// @notice Returns the string representation of `self` wrapped in dim ANSI style codes. function dim(bool self) internal pure returns (string memory) { return dim(vm.toString(self)); } + /// @notice Returns the string representation of `self` wrapped in dim ANSI style codes. function dimBytes(bytes memory self) internal pure returns (string memory) { return dim(vm.toString(self)); } + /// @notice Returns the string representation of `self` wrapped in dim ANSI style codes. function dimBytes32(bytes32 self) internal pure returns (string memory) { return dim(vm.toString(self)); } + /// @notice Returns `self` wrapped in italic ANSI style codes. function italic(string memory self) internal pure returns (string memory) { - return styleConcat(ITALIC, self); + return _styleConcat(ITALIC, self); } + /// @notice Returns the string representation of `self` wrapped in italic ANSI style codes. function italic(uint256 self) internal pure returns (string memory) { return italic(vm.toString(self)); } + /// @notice Returns the string representation of `self` wrapped in italic ANSI style codes. function italic(int256 self) internal pure returns (string memory) { return italic(vm.toString(self)); } + /// @notice Returns the string representation of `self` wrapped in italic ANSI style codes. function italic(address self) internal pure returns (string memory) { return italic(vm.toString(self)); } + /// @notice Returns the string representation of `self` wrapped in italic ANSI style codes. function italic(bool self) internal pure returns (string memory) { return italic(vm.toString(self)); } + /// @notice Returns the string representation of `self` wrapped in italic ANSI style codes. function italicBytes(bytes memory self) internal pure returns (string memory) { return italic(vm.toString(self)); } + /// @notice Returns the string representation of `self` wrapped in italic ANSI style codes. function italicBytes32(bytes32 self) internal pure returns (string memory) { return italic(vm.toString(self)); } + /// @notice Returns `self` wrapped in underline ANSI style codes. function underline(string memory self) internal pure returns (string memory) { - return styleConcat(UNDERLINE, self); + return _styleConcat(UNDERLINE, self); } + /// @notice Returns the string representation of `self` wrapped in underline ANSI style codes. function underline(uint256 self) internal pure returns (string memory) { return underline(vm.toString(self)); } + /// @notice Returns the string representation of `self` wrapped in underline ANSI style codes. function underline(int256 self) internal pure returns (string memory) { return underline(vm.toString(self)); } + /// @notice Returns the string representation of `self` wrapped in underline ANSI style codes. function underline(address self) internal pure returns (string memory) { return underline(vm.toString(self)); } + /// @notice Returns the string representation of `self` wrapped in underline ANSI style codes. function underline(bool self) internal pure returns (string memory) { return underline(vm.toString(self)); } + /// @notice Returns the string representation of `self` wrapped in underline ANSI style codes. function underlineBytes(bytes memory self) internal pure returns (string memory) { return underline(vm.toString(self)); } + /// @notice Returns the string representation of `self` wrapped in underline ANSI style codes. function underlineBytes32(bytes32 self) internal pure returns (string memory) { return underline(vm.toString(self)); } + /// @notice Returns `self` wrapped in inverse ANSI style codes. function inverse(string memory self) internal pure returns (string memory) { - return styleConcat(INVERSE, self); + return _styleConcat(INVERSE, self); } + /// @notice Returns the string representation of `self` wrapped in inverse ANSI style codes. function inverse(uint256 self) internal pure returns (string memory) { return inverse(vm.toString(self)); } + /// @notice Returns the string representation of `self` wrapped in inverse ANSI style codes. function inverse(int256 self) internal pure returns (string memory) { return inverse(vm.toString(self)); } + /// @notice Returns the string representation of `self` wrapped in inverse ANSI style codes. function inverse(address self) internal pure returns (string memory) { return inverse(vm.toString(self)); } + /// @notice Returns the string representation of `self` wrapped in inverse ANSI style codes. function inverse(bool self) internal pure returns (string memory) { return inverse(vm.toString(self)); } + /// @notice Returns the string representation of `self` wrapped in inverse ANSI style codes. function inverseBytes(bytes memory self) internal pure returns (string memory) { return inverse(vm.toString(self)); } + /// @notice Returns the string representation of `self` wrapped in inverse ANSI style codes. function inverseBytes32(bytes32 self) internal pure returns (string memory) { return inverse(vm.toString(self)); } diff --git a/dependencies/forge-std-1.11.0/src/StdToml.sol b/dependencies/forge-std-1.16.2/src/StdToml.sol similarity index 65% rename from dependencies/forge-std-1.11.0/src/StdToml.sol rename to dependencies/forge-std-1.16.2/src/StdToml.sol index 7ad3be2..a5198d8 100644 --- a/dependencies/forge-std-1.11.0/src/StdToml.sol +++ b/dependencies/forge-std-1.16.2/src/StdToml.sol @@ -1,7 +1,5 @@ -// SPDX-License-Identifier: MIT -pragma solidity >=0.6.0 <0.9.0; - -pragma experimental ABIEncoderV2; +// SPDX-License-Identifier: MIT OR Apache-2.0 +pragma solidity >=0.8.13 <0.9.0; import {VmSafe} from "./Vm.sol"; @@ -10,89 +8,107 @@ import {VmSafe} from "./Vm.sol"; // ``` // using stdToml for string; // string memory toml = vm.readFile(""); -// toml.readUint(""); +// toml.readUint(""); // ``` // To write: // ``` // using stdToml for string; -// string memory json = "json"; -// json.serialize("a", uint256(123)); -// string memory semiFinal = json.serialize("b", string("test")); -// string memory finalJson = json.serialize("c", semiFinal); -// finalJson.write(""); +// string memory toml = "toml"; +// toml.serialize("a", uint256(123)); +// string memory semiFinal = toml.serialize("b", string("test")); +// string memory finalToml = toml.serialize("c", semiFinal); +// finalToml.write(""); // ``` library stdToml { VmSafe private constant vm = VmSafe(address(uint160(uint256(keccak256("hevm cheat code"))))); + /// @notice Returns whether `key` exists in `toml`. function keyExists(string memory toml, string memory key) internal view returns (bool) { return vm.keyExistsToml(toml, key); } + /// @notice ABI-encodes the TOML value selected by `key`. function parseRaw(string memory toml, string memory key) internal pure returns (bytes memory) { return vm.parseToml(toml, key); } + /// @notice Reads a uint256 value at `key` from `toml`. function readUint(string memory toml, string memory key) internal pure returns (uint256) { return vm.parseTomlUint(toml, key); } + /// @notice Reads a uint256 array at `key` from `toml`. function readUintArray(string memory toml, string memory key) internal pure returns (uint256[] memory) { return vm.parseTomlUintArray(toml, key); } + /// @notice Reads an int256 value at `key` from `toml`. function readInt(string memory toml, string memory key) internal pure returns (int256) { return vm.parseTomlInt(toml, key); } + /// @notice Reads an int256 array at `key` from `toml`. function readIntArray(string memory toml, string memory key) internal pure returns (int256[] memory) { return vm.parseTomlIntArray(toml, key); } + /// @notice Reads a bytes32 value at `key` from `toml`. function readBytes32(string memory toml, string memory key) internal pure returns (bytes32) { return vm.parseTomlBytes32(toml, key); } + /// @notice Reads a bytes32 array at `key` from `toml`. function readBytes32Array(string memory toml, string memory key) internal pure returns (bytes32[] memory) { return vm.parseTomlBytes32Array(toml, key); } + /// @notice Reads a string value at `key` from `toml`. function readString(string memory toml, string memory key) internal pure returns (string memory) { return vm.parseTomlString(toml, key); } + /// @notice Reads a string array at `key` from `toml`. function readStringArray(string memory toml, string memory key) internal pure returns (string[] memory) { return vm.parseTomlStringArray(toml, key); } + /// @notice Reads an address value at `key` from `toml`. function readAddress(string memory toml, string memory key) internal pure returns (address) { return vm.parseTomlAddress(toml, key); } + /// @notice Reads an address array at `key` from `toml`. function readAddressArray(string memory toml, string memory key) internal pure returns (address[] memory) { return vm.parseTomlAddressArray(toml, key); } + /// @notice Reads a bool value at `key` from `toml`. function readBool(string memory toml, string memory key) internal pure returns (bool) { return vm.parseTomlBool(toml, key); } + /// @notice Reads a bool array at `key` from `toml`. function readBoolArray(string memory toml, string memory key) internal pure returns (bool[] memory) { return vm.parseTomlBoolArray(toml, key); } + /// @notice Reads a bytes value at `key` from `toml`. function readBytes(string memory toml, string memory key) internal pure returns (bytes memory) { return vm.parseTomlBytes(toml, key); } + /// @notice Reads a bytes array at `key` from `toml`. function readBytesArray(string memory toml, string memory key) internal pure returns (bytes[] memory) { return vm.parseTomlBytesArray(toml, key); } + /// @notice Reads a uint256 value at `key` from `toml`, returning `defaultValue` if the key does not exist. function readUintOr(string memory toml, string memory key, uint256 defaultValue) internal view returns (uint256) { return keyExists(toml, key) ? readUint(toml, key) : defaultValue; } + /// @notice Reads a uint256 array at `key` from `toml`, returning `defaultValue` if the key does not exist. function readUintArrayOr(string memory toml, string memory key, uint256[] memory defaultValue) internal view @@ -101,10 +117,12 @@ library stdToml { return keyExists(toml, key) ? readUintArray(toml, key) : defaultValue; } + /// @notice Reads an int256 value at `key` from `toml`, returning `defaultValue` if the key does not exist. function readIntOr(string memory toml, string memory key, int256 defaultValue) internal view returns (int256) { return keyExists(toml, key) ? readInt(toml, key) : defaultValue; } + /// @notice Reads an int256 array at `key` from `toml`, returning `defaultValue` if the key does not exist. function readIntArrayOr(string memory toml, string memory key, int256[] memory defaultValue) internal view @@ -113,6 +131,7 @@ library stdToml { return keyExists(toml, key) ? readIntArray(toml, key) : defaultValue; } + /// @notice Reads a bytes32 value at `key` from `toml`, returning `defaultValue` if the key does not exist. function readBytes32Or(string memory toml, string memory key, bytes32 defaultValue) internal view @@ -121,6 +140,7 @@ library stdToml { return keyExists(toml, key) ? readBytes32(toml, key) : defaultValue; } + /// @notice Reads a bytes32 array at `key` from `toml`, returning `defaultValue` if the key does not exist. function readBytes32ArrayOr(string memory toml, string memory key, bytes32[] memory defaultValue) internal view @@ -129,6 +149,7 @@ library stdToml { return keyExists(toml, key) ? readBytes32Array(toml, key) : defaultValue; } + /// @notice Reads a string value at `key` from `toml`, returning `defaultValue` if the key does not exist. function readStringOr(string memory toml, string memory key, string memory defaultValue) internal view @@ -137,6 +158,7 @@ library stdToml { return keyExists(toml, key) ? readString(toml, key) : defaultValue; } + /// @notice Reads a string array at `key` from `toml`, returning `defaultValue` if the key does not exist. function readStringArrayOr(string memory toml, string memory key, string[] memory defaultValue) internal view @@ -145,6 +167,7 @@ library stdToml { return keyExists(toml, key) ? readStringArray(toml, key) : defaultValue; } + /// @notice Reads an address value at `key` from `toml`, returning `defaultValue` if the key does not exist. function readAddressOr(string memory toml, string memory key, address defaultValue) internal view @@ -153,6 +176,7 @@ library stdToml { return keyExists(toml, key) ? readAddress(toml, key) : defaultValue; } + /// @notice Reads an address array at `key` from `toml`, returning `defaultValue` if the key does not exist. function readAddressArrayOr(string memory toml, string memory key, address[] memory defaultValue) internal view @@ -161,10 +185,12 @@ library stdToml { return keyExists(toml, key) ? readAddressArray(toml, key) : defaultValue; } + /// @notice Reads a bool value at `key` from `toml`, returning `defaultValue` if the key does not exist. function readBoolOr(string memory toml, string memory key, bool defaultValue) internal view returns (bool) { return keyExists(toml, key) ? readBool(toml, key) : defaultValue; } + /// @notice Reads a bool array at `key` from `toml`, returning `defaultValue` if the key does not exist. function readBoolArrayOr(string memory toml, string memory key, bool[] memory defaultValue) internal view @@ -173,6 +199,7 @@ library stdToml { return keyExists(toml, key) ? readBoolArray(toml, key) : defaultValue; } + /// @notice Reads a bytes value at `key` from `toml`, returning `defaultValue` if the key does not exist. function readBytesOr(string memory toml, string memory key, bytes memory defaultValue) internal view @@ -181,6 +208,7 @@ library stdToml { return keyExists(toml, key) ? readBytes(toml, key) : defaultValue; } + /// @notice Reads a bytes array at `key` from `toml`, returning `defaultValue` if the key does not exist. function readBytesArrayOr(string memory toml, string memory key, bytes[] memory defaultValue) internal view @@ -189,25 +217,28 @@ library stdToml { return keyExists(toml, key) ? readBytesArray(toml, key) : defaultValue; } + /// @notice Serializes a JSON object `rootObject` under `jsonKey` and returns the serialized string. + /// @dev Values are accumulated as JSON in memory; conversion to TOML happens on `write`. function serialize(string memory jsonKey, string memory rootObject) internal returns (string memory) { return vm.serializeJson(jsonKey, rootObject); } + /// @notice Serializes a bool `value` under `key` within `jsonKey` and returns the serialized string. function serialize(string memory jsonKey, string memory key, bool value) internal returns (string memory) { return vm.serializeBool(jsonKey, key, value); } - function serialize(string memory jsonKey, string memory key, bool[] memory value) - internal - returns (string memory) - { + /// @notice Serializes a bool array `value` under `key` within `jsonKey` and returns the serialized string. + function serialize(string memory jsonKey, string memory key, bool[] memory value) internal returns (string memory) { return vm.serializeBool(jsonKey, key, value); } + /// @notice Serializes a uint256 `value` under `key` within `jsonKey` and returns the serialized string. function serialize(string memory jsonKey, string memory key, uint256 value) internal returns (string memory) { return vm.serializeUint(jsonKey, key, value); } + /// @notice Serializes a uint256 array `value` under `key` within `jsonKey` and returns the serialized string. function serialize(string memory jsonKey, string memory key, uint256[] memory value) internal returns (string memory) @@ -215,10 +246,12 @@ library stdToml { return vm.serializeUint(jsonKey, key, value); } + /// @notice Serializes an int256 `value` under `key` within `jsonKey` and returns the serialized string. function serialize(string memory jsonKey, string memory key, int256 value) internal returns (string memory) { return vm.serializeInt(jsonKey, key, value); } + /// @notice Serializes an int256 array `value` under `key` within `jsonKey` and returns the serialized string. function serialize(string memory jsonKey, string memory key, int256[] memory value) internal returns (string memory) @@ -226,10 +259,12 @@ library stdToml { return vm.serializeInt(jsonKey, key, value); } + /// @notice Serializes an address `value` under `key` within `jsonKey` and returns the serialized string. function serialize(string memory jsonKey, string memory key, address value) internal returns (string memory) { return vm.serializeAddress(jsonKey, key, value); } + /// @notice Serializes an address array `value` under `key` within `jsonKey` and returns the serialized string. function serialize(string memory jsonKey, string memory key, address[] memory value) internal returns (string memory) @@ -237,10 +272,12 @@ library stdToml { return vm.serializeAddress(jsonKey, key, value); } + /// @notice Serializes a bytes32 `value` under `key` within `jsonKey` and returns the serialized string. function serialize(string memory jsonKey, string memory key, bytes32 value) internal returns (string memory) { return vm.serializeBytes32(jsonKey, key, value); } + /// @notice Serializes a bytes32 array `value` under `key` within `jsonKey` and returns the serialized string. function serialize(string memory jsonKey, string memory key, bytes32[] memory value) internal returns (string memory) @@ -248,10 +285,12 @@ library stdToml { return vm.serializeBytes32(jsonKey, key, value); } + /// @notice Serializes a bytes `value` under `key` within `jsonKey` and returns the serialized string. function serialize(string memory jsonKey, string memory key, bytes memory value) internal returns (string memory) { return vm.serializeBytes(jsonKey, key, value); } + /// @notice Serializes a bytes array `value` under `key` within `jsonKey` and returns the serialized string. function serialize(string memory jsonKey, string memory key, bytes[] memory value) internal returns (string memory) @@ -259,13 +298,12 @@ library stdToml { return vm.serializeBytes(jsonKey, key, value); } - function serialize(string memory jsonKey, string memory key, string memory value) - internal - returns (string memory) - { + /// @notice Serializes a string `value` under `key` within `jsonKey` and returns the serialized string. + function serialize(string memory jsonKey, string memory key, string memory value) internal returns (string memory) { return vm.serializeString(jsonKey, key, value); } + /// @notice Serializes a string array `value` under `key` within `jsonKey` and returns the serialized string. function serialize(string memory jsonKey, string memory key, string[] memory value) internal returns (string memory) @@ -273,10 +311,12 @@ library stdToml { return vm.serializeString(jsonKey, key, value); } + /// @notice Writes the serialized object `jsonKey` to `path` as a TOML file. function write(string memory jsonKey, string memory path) internal { vm.writeToml(jsonKey, path); } + /// @notice Writes the value at `valueKey` from the serialized object `jsonKey` to `path` as a TOML file. function write(string memory jsonKey, string memory path, string memory valueKey) internal { vm.writeToml(jsonKey, path, valueKey); } diff --git a/dependencies/forge-std-1.11.0/src/StdUtils.sol b/dependencies/forge-std-1.16.2/src/StdUtils.sol similarity index 56% rename from dependencies/forge-std-1.11.0/src/StdUtils.sol rename to dependencies/forge-std-1.16.2/src/StdUtils.sol index 9321df1..8dd7b47 100644 --- a/dependencies/forge-std-1.11.0/src/StdUtils.sol +++ b/dependencies/forge-std-1.16.2/src/StdUtils.sol @@ -1,9 +1,8 @@ -// SPDX-License-Identifier: MIT -pragma solidity >=0.6.2 <0.9.0; - -pragma experimental ABIEncoderV2; +// SPDX-License-Identifier: MIT OR Apache-2.0 +pragma solidity >=0.8.13 <0.9.0; import {IMulticall3} from "./interfaces/IMulticall3.sol"; +import {StdConstants} from "./StdConstants.sol"; import {VmSafe} from "./Vm.sol"; abstract contract StdUtils { @@ -11,23 +10,25 @@ abstract contract StdUtils { CONSTANTS //////////////////////////////////////////////////////////////////////////*/ - IMulticall3 private constant multicall = IMulticall3(0xcA11bde05977b3631167028862bE2a173976CA11); VmSafe private constant vm = VmSafe(address(uint160(uint256(keccak256("hevm cheat code"))))); - address private constant CONSOLE2_ADDRESS = 0x000000000000000000636F6e736F6c652e6c6f67; - uint256 private constant INT256_MIN_ABS = + address private constant _CONSOLE2_ADDRESS = 0x000000000000000000636F6e736F6c652e6c6f67; + uint256 private constant _INT256_MIN_ABS = 57896044618658097711785492504343953926634992332820282019728792003956564819968; - uint256 private constant SECP256K1_ORDER = + uint256 private constant _SECP256K1_ORDER = 115792089237316195423570985008687907852837564279074904382605163141518161494337; - uint256 private constant UINT256_MAX = + uint256 private constant _UINT256_MAX = 115792089237316195423570985008687907853269984665640564039457584007913129639935; - // Used by default when deploying with create2, https://github.com/Arachnid/deterministic-deployment-proxy. - address private constant CREATE2_FACTORY = 0x4e59b44847b379578588920cA78FbF26c0B4956C; - /*////////////////////////////////////////////////////////////////////////// INTERNAL FUNCTIONS //////////////////////////////////////////////////////////////////////////*/ + /// @notice Maps an unsigned integer into the inclusive range `[min, max]`. + /// @dev Values outside the range are wrapped into it. + /// @param x The unsigned value to bound. + /// @param min The inclusive lower bound. + /// @param max The inclusive upper bound. + /// @return result The bounded value. function _bound(uint256 x, uint256 min, uint256 max) internal pure virtual returns (uint256 result) { require(min <= max, "StdUtils bound(uint256,uint256,uint256): Max is less than min."); // If x is between min and max, return x directly. This is to ensure that dictionary values @@ -36,10 +37,10 @@ abstract contract StdUtils { uint256 size = max - min + 1; - // If the value is 0, 1, 2, 3, wrap that to min, min+1, min+2, min+3. Similarly for the UINT256_MAX side. + // If the value is 0, 1, 2, 3, wrap that to min, min+1, min+2, min+3. Similarly for the _UINT256_MAX side. // This helps ensure coverage of the min/max values. if (x <= 3 && size > x) return min + x; - if (x >= UINT256_MAX - 3 && size > UINT256_MAX - x) return max - (UINT256_MAX - x); + if (x >= _UINT256_MAX - 3 && size > _UINT256_MAX - x) return max - (_UINT256_MAX - x); // Otherwise, wrap x into the range [min, max], i.e. the range is inclusive. if (x > max) { @@ -55,81 +56,120 @@ abstract contract StdUtils { } } + /// @notice Wrapper for `_bound(uint256,uint256,uint256)`. + /// @param x The unsigned value to bound. + /// @param min The inclusive lower bound. + /// @param max The inclusive upper bound. + /// @return result The bounded value. function bound(uint256 x, uint256 min, uint256 max) internal pure virtual returns (uint256 result) { result = _bound(x, min, max); - console2_log_StdUtils("Bound result", result); } + /// @notice Maps a signed integer into the inclusive range `[min, max]`. + /// @dev Values outside the range are wrapped into it. + /// @param x The signed value to bound. + /// @param min The inclusive lower bound. + /// @param max The inclusive upper bound. + /// @return result The bounded value. function _bound(int256 x, int256 min, int256 max) internal pure virtual returns (int256 result) { require(min <= max, "StdUtils bound(int256,int256,int256): Max is less than min."); // Shifting all int256 values to uint256 to use _bound function. The range of two types are: // int256 : -(2**255) ~ (2**255 - 1) // uint256: 0 ~ (2**256 - 1) - // So, add 2**255, INT256_MIN_ABS to the integer values. + // So, add 2**255, _INT256_MIN_ABS to the integer values. // // If the given integer value is -2**255, we cannot use `-uint256(-x)` because of the overflow. // So, use `~uint256(x) + 1` instead. - uint256 _x = x < 0 ? (INT256_MIN_ABS - ~uint256(x) - 1) : (uint256(x) + INT256_MIN_ABS); - uint256 _min = min < 0 ? (INT256_MIN_ABS - ~uint256(min) - 1) : (uint256(min) + INT256_MIN_ABS); - uint256 _max = max < 0 ? (INT256_MIN_ABS - ~uint256(max) - 1) : (uint256(max) + INT256_MIN_ABS); + uint256 _x = x < 0 ? (_INT256_MIN_ABS - ~uint256(x) - 1) : (uint256(x) + _INT256_MIN_ABS); + uint256 _min = min < 0 ? (_INT256_MIN_ABS - ~uint256(min) - 1) : (uint256(min) + _INT256_MIN_ABS); + uint256 _max = max < 0 ? (_INT256_MIN_ABS - ~uint256(max) - 1) : (uint256(max) + _INT256_MIN_ABS); uint256 y = _bound(_x, _min, _max); - // To move it back to int256 value, subtract INT256_MIN_ABS at here. - result = y < INT256_MIN_ABS ? int256(~(INT256_MIN_ABS - y) + 1) : int256(y - INT256_MIN_ABS); + // To move it back to int256 value, subtract _INT256_MIN_ABS at here. + result = y < _INT256_MIN_ABS ? int256(~(_INT256_MIN_ABS - y) + 1) : int256(y - _INT256_MIN_ABS); } + /// @notice Wrapper for `_bound(int256,int256,int256)`. + /// @param x The signed value to bound. + /// @param min The inclusive lower bound. + /// @param max The inclusive upper bound. + /// @return result The bounded value. function bound(int256 x, int256 min, int256 max) internal pure virtual returns (int256 result) { result = _bound(x, min, max); - console2_log_StdUtils("Bound result", vm.toString(result)); } + /// @notice Maps a value into the valid secp256k1 private key range `[1, n - 1]`. + /// @param privateKey The raw private key candidate. + /// @return result The bounded private key. function boundPrivateKey(uint256 privateKey) internal pure virtual returns (uint256 result) { - result = _bound(privateKey, 1, SECP256K1_ORDER - 1); + result = _bound(privateKey, 1, _SECP256K1_ORDER - 1); } + /// @notice Converts a byte array (up to 32 bytes) into a `uint256`. + /// @param b The byte array to decode. + /// @return The decoded unsigned integer. function bytesToUint(bytes memory b) internal pure virtual returns (uint256) { require(b.length <= 32, "StdUtils bytesToUint(bytes): Bytes length exceeds 32."); return abi.decode(abi.encodePacked(new bytes(32 - b.length), b), (uint256)); } - /// @dev Compute the address a contract will be deployed at for a given deployer address and nonce + /// @notice Computes the CREATE deployment address for `deployer` and `nonce`. + /// @dev Deprecated in favor of `vm.computeCreateAddress`. + /// @param deployer The deployer address. + /// @param nonce The deployer nonce used for CREATE. + /// @return The computed CREATE address. function computeCreateAddress(address deployer, uint256 nonce) internal pure virtual returns (address) { - console2_log_StdUtils("computeCreateAddress is deprecated. Please use vm.computeCreateAddress instead."); + _console2_log_StdUtils("computeCreateAddress is deprecated. Please use vm.computeCreateAddress instead."); return vm.computeCreateAddress(deployer, nonce); } + /// @notice Computes the CREATE2 address from a salt, init code hash, and deployer. + /// @dev Deprecated in favor of `vm.computeCreate2Address`. + /// @param salt The CREATE2 salt. + /// @param initcodeHash The hash of the full init code. + /// @param deployer The deployer address. + /// @return The computed CREATE2 address. function computeCreate2Address(bytes32 salt, bytes32 initcodeHash, address deployer) internal pure virtual returns (address) { - console2_log_StdUtils("computeCreate2Address is deprecated. Please use vm.computeCreate2Address instead."); + _console2_log_StdUtils("computeCreate2Address is deprecated. Please use vm.computeCreate2Address instead."); return vm.computeCreate2Address(salt, initcodeHash, deployer); } - /// @dev returns the address of a contract created with CREATE2 using the default CREATE2 deployer + /// @notice Computes a CREATE2 address using the default CREATE2 deployer. + /// @dev Deprecated in favor of `vm.computeCreate2Address`. + /// @param salt The CREATE2 salt. + /// @param initCodeHash The hash of the full init code. + /// @return The computed CREATE2 address. function computeCreate2Address(bytes32 salt, bytes32 initCodeHash) internal pure returns (address) { - console2_log_StdUtils("computeCreate2Address is deprecated. Please use vm.computeCreate2Address instead."); + _console2_log_StdUtils("computeCreate2Address is deprecated. Please use vm.computeCreate2Address instead."); return vm.computeCreate2Address(salt, initCodeHash); } - /// @dev returns the hash of the init code (creation code + no args) used in CREATE2 with no constructor arguments - /// @param creationCode the creation code of a contract C, as returned by type(C).creationCode + /// @notice Returns the init code hash for CREATE2 without constructor arguments. + /// @param creationCode The creation code of contract `C`, as returned by `type(C).creationCode`. + /// @return The keccak256 hash of the init code. function hashInitCode(bytes memory creationCode) internal pure returns (bytes32) { return hashInitCode(creationCode, ""); } - /// @dev returns the hash of the init code (creation code + ABI-encoded args) used in CREATE2 - /// @param creationCode the creation code of a contract C, as returned by type(C).creationCode - /// @param args the ABI-encoded arguments to the constructor of C + /// @notice Returns the init code hash for CREATE2 with ABI-encoded constructor arguments. + /// @param creationCode The creation code of contract `C`, as returned by `type(C).creationCode`. + /// @param args The ABI-encoded constructor arguments for `C`. + /// @return The keccak256 hash of `creationCode || args`. function hashInitCode(bytes memory creationCode, bytes memory args) internal pure returns (bytes32) { return keccak256(abi.encodePacked(creationCode, args)); } - // Performs a single call with Multicall3 to query the ERC-20 token balances of the given addresses. + /// @notice Queries ERC-20 balances for multiple addresses in one Multicall3 request. + /// @param token The ERC-20 token contract to query. + /// @param addresses The addresses to query balances for. + /// @return balances The token balances in the same order as `addresses`. function getTokenBalances(address token, address[] memory addresses) internal virtual @@ -145,12 +185,12 @@ abstract contract StdUtils { uint256 length = addresses.length; IMulticall3.Call[] memory calls = new IMulticall3.Call[](length); for (uint256 i = 0; i < length; ++i) { - // 0x70a08231 = bytes4("balanceOf(address)")) + // 0x70a08231 = bytes4(keccak256("balanceOf(address)")) calls[i] = IMulticall3.Call({target: token, callData: abi.encodeWithSelector(0x70a08231, (addresses[i]))}); } // Make the aggregate call. - (, bytes[] memory returnData) = multicall.aggregate(calls); + (, bytes[] memory returnData) = StdConstants.MULTICALL3_ADDRESS.aggregate(calls); // ABI decode the return data and return the balances. balances = new uint256[](length); @@ -163,7 +203,7 @@ abstract contract StdUtils { PRIVATE FUNCTIONS //////////////////////////////////////////////////////////////////////////*/ - function addressFromLast20Bytes(bytes32 bytesValue) private pure returns (address) { + function _addressFromLast20Bytes(bytes32 bytesValue) private pure returns (address) { return address(uint160(uint256(bytesValue))); } @@ -186,23 +226,22 @@ abstract contract StdUtils { function _sendLogPayloadView(bytes memory payload) private view { uint256 payloadLength = payload.length; - address consoleAddress = CONSOLE2_ADDRESS; - /// @solidity memory-safe-assembly - assembly { + address consoleAddress = _CONSOLE2_ADDRESS; + assembly ("memory-safe") { let payloadStart := add(payload, 32) let r := staticcall(gas(), consoleAddress, payloadStart, payloadLength, 0, 0) } } - function console2_log_StdUtils(string memory p0) private pure { + function _console2_log_StdUtils(string memory p0) private pure { _sendLogPayload(abi.encodeWithSignature("log(string)", p0)); } - function console2_log_StdUtils(string memory p0, uint256 p1) private pure { + function _console2_log_StdUtils(string memory p0, uint256 p1) private pure { _sendLogPayload(abi.encodeWithSignature("log(string,uint256)", p0, p1)); } - function console2_log_StdUtils(string memory p0, string memory p1) private pure { + function _console2_log_StdUtils(string memory p0, string memory p1) private pure { _sendLogPayload(abi.encodeWithSignature("log(string,string)", p0, p1)); } } diff --git a/dependencies/forge-std-1.11.0/src/Test.sol b/dependencies/forge-std-1.16.2/src/Test.sol similarity index 90% rename from dependencies/forge-std-1.11.0/src/Test.sol rename to dependencies/forge-std-1.16.2/src/Test.sol index 11b18f2..af91dd8 100644 --- a/dependencies/forge-std-1.11.0/src/Test.sol +++ b/dependencies/forge-std-1.16.2/src/Test.sol @@ -1,7 +1,5 @@ -// SPDX-License-Identifier: MIT -pragma solidity >=0.6.2 <0.9.0; - -pragma experimental ABIEncoderV2; +// SPDX-License-Identifier: MIT OR Apache-2.0 +pragma solidity >=0.8.13 <0.9.0; // 💬 ABOUT // Forge Std's default Test. diff --git a/dependencies/forge-std-1.11.0/src/Vm.sol b/dependencies/forge-std-1.16.2/src/Vm.sol similarity index 90% rename from dependencies/forge-std-1.11.0/src/Vm.sol rename to dependencies/forge-std-1.16.2/src/Vm.sol index cd88370..4fe3f41 100644 --- a/dependencies/forge-std-1.11.0/src/Vm.sol +++ b/dependencies/forge-std-1.16.2/src/Vm.sol @@ -1,8 +1,7 @@ // Automatically @generated by scripts/vm.py. Do not modify manually. // SPDX-License-Identifier: MIT OR Apache-2.0 -pragma solidity >=0.6.2 <0.9.0; -pragma experimental ABIEncoderV2; +pragma solidity >=0.8.13 <0.9.0; /// The `VmSafe` interface does not allow manipulation of the EVM state or other actions that may /// result in Script simulations differing from on-chain execution. It is recommended to only use @@ -255,7 +254,7 @@ interface VmSafe { bool reverted; } - /// Gas used. Returned by `lastCallGas`. + /// Gas used. Returned by `lastCallGas` and `lastFrameGas`. struct Gas { // The gas limit of the call. uint64 gasLimit; @@ -343,6 +342,10 @@ interface VmSafe { // ======== Crypto ======== + /// Generates an Ed25519 key pair from a deterministic salt. + /// Returns (publicKey, privateKey) as 32-byte values. + function createEd25519Key(bytes32 salt) external pure returns (bytes32 publicKey, bytes32 privateKey); + /// Derives a private key from the name, labels the account with that name, and returns the wallet. function createWallet(string calldata walletLabel) external returns (Wallet memory wallet); @@ -377,6 +380,9 @@ interface VmSafe { pure returns (uint256 privateKey); + /// Derives the Ed25519 public key from a private key. + function publicKeyEd25519(bytes32 privateKey) external pure returns (bytes32 publicKey); + /// Derives secp256r1 public key from the provided `privateKey`. function publicKeyP256(uint256 privateKey) external pure returns (uint256 publicKeyX, uint256 publicKeyY); @@ -402,7 +408,7 @@ interface VmSafe { /// Returns a compact signature (`r`, `vs`) as per EIP-2098, where `vs` encodes both the /// signature's `s` value, and the recovery id `v` in a single bytes32. /// This format reduces the signature size from 65 to 64 bytes. - function signCompact(Wallet calldata wallet, bytes32 digest) external returns (bytes32 r, bytes32 vs); + function signCompact(Wallet calldata wallet, bytes32 digest) external pure returns (bytes32 r, bytes32 vs); /// Signs `digest` with `privateKey` using the secp256k1 curve. /// Returns a compact signature (`r`, `vs`) as per EIP-2098, where `vs` encodes both the @@ -427,11 +433,42 @@ interface VmSafe { /// Raises error if none of the signers passed into the script have provided address. function signCompact(address signer, bytes32 digest) external pure returns (bytes32 r, bytes32 vs); + /// Signs a message with namespace using Ed25519. + /// The signature covers namespace || message for domain separation. + /// Returns a 64-byte Ed25519 signature. + function signEd25519(bytes calldata namespace, bytes calldata message, bytes32 privateKey) + external + pure + returns (bytes memory signature); + + /// Signs `digest` as a Tempo V2 keychain signature for `account` using a secp256k1 access key. + /// Returns the encoded signature bytes accepted by `SignatureVerifier.verifyKeychain`. + function signKeychain(uint256 privateKey, address account, bytes32 digest) + external + pure + returns (bytes memory signature); + + /// Signs `digest` as a Tempo V2 keychain signature for `account` using a root or admin secp256k1 key. + /// Returns the encoded signature bytes accepted by `SignatureVerifier.verifyKeychainAdmin`. + /// The supplied `digest` should already be domain-separated with chain ID, contract address, + /// and account address. + function signKeychainAdmin(uint256 privateKey, address account, bytes32 digest) + external + pure + returns (bytes memory signature); + /// Signs `digest` with `privateKey` using the secp256r1 curve. function signP256(uint256 privateKey, bytes32 digest) external pure returns (bytes32 r, bytes32 s); + /// Signs `digest` with `privateKey` on the secp256k1 curve, using the given `nonce` + /// as the raw ephemeral k value in ECDSA (instead of deriving it deterministically). + function signWithNonceUnsafe(uint256 privateKey, bytes32 digest, uint256 nonce) + external + pure + returns (uint8 v, bytes32 r, bytes32 s); + /// Signs data with a `Wallet`. - function sign(Wallet calldata wallet, bytes32 digest) external returns (uint8 v, bytes32 r, bytes32 s); + function sign(Wallet calldata wallet, bytes32 digest) external pure returns (uint8 v, bytes32 r, bytes32 s); /// Signs `digest` with `privateKey` using the secp256k1 curve. function sign(uint256 privateKey, bytes32 digest) external pure returns (uint8 v, bytes32 r, bytes32 s); @@ -447,6 +484,15 @@ interface VmSafe { /// Raises error if none of the signers passed into the script have provided address. function sign(address signer, bytes32 digest) external pure returns (uint8 v, bytes32 r, bytes32 s); + /// Verifies an Ed25519 signature over namespace || message. + /// Returns true if signature is valid, false otherwise. + function verifyEd25519( + bytes calldata signature, + bytes calldata namespace, + bytes calldata message, + bytes32 publicKey + ) external pure returns (bool valid); + // ======== Environment ======== /// Gets the environment variable `name` and parses it as `address`. @@ -646,6 +692,10 @@ interface VmSafe { /// See https://github.com/foundry-rs/foundry/issues/6180 function getChainId() external view returns (uint256 blockChainId); + /// Returns the test or script execution evm version. + /// **Note:** The execution evm version is not the same as the compilation one. + function getEvmVersion() external pure returns (string memory evm); + /// Gets the map key and parent of a mapping at a given slot, for a given address. function getMappingKeyAndParentOf(address target, bytes32 elementSlot) external @@ -672,6 +722,9 @@ interface VmSafe { /// Gets all the recorded logs. function getRecordedLogs() external view returns (Log[] memory logs); + /// Gets all the recorded logs, in JSON format. + function getRecordedLogsJson() external view returns (string memory logsJson); + /// Returns state diffs from current `vm.startStateDiffRecording` session. function getStateDiff() external view returns (string memory diff); @@ -681,8 +734,22 @@ interface VmSafe { /// Returns an array of `StorageAccess` from current `vm.stateStateDiffRecording` session function getStorageAccesses() external view returns (StorageAccess[] memory storageAccesses); - /// Gets the gas used in the last call from the callee perspective. - function lastCallGas() external view returns (Gas memory gas); + /// Returns an array of storage slots occupied by the specified variable. + function getStorageSlots(address target, string calldata variableName) + external + view + returns (uint256[] memory slots); + + /// Returns `true` if `spender` is on the active Tempo hardfork's implicit-approval list, + /// meaning it can pull TIP-20 tokens from `msg.sender` without a prior `approve()`. + /// Returns `false` on non-Tempo networks. + function isImplicitlyApproved(address spender) external view returns (bool implicitlyApproved); + + /// Returns true if isolated test execution is enabled. + function isIsolateMode() external view returns (bool result); + + /// Gets the gas used in the last call or create from the callee perspective. + function lastFrameGas() external view returns (Gas memory gas); /// Loads a storage slot from an address. function load(address target, bytes32 slot) external view returns (bytes32 data); @@ -703,6 +770,14 @@ interface VmSafe { /// Resumes gas metering (i.e. gas usage is counted again). Noop if already on. function resumeGasMetering() external; + /// Performs an Ethereum JSON-RPC request to the current fork URL and returns the JSON result. + function rpcJson(string calldata method, string calldata params) external returns (string memory data); + + /// Performs an Ethereum JSON-RPC request to the given endpoint and returns the JSON result. + function rpcJson(string calldata urlOrAlias, string calldata method, string calldata params) + external + returns (string memory data); + /// Performs an Ethereum JSON-RPC request to the current fork URL. function rpc(string calldata method, string calldata params) external returns (bytes memory data); @@ -711,6 +786,10 @@ interface VmSafe { external returns (bytes memory data); + /// Set the exact test or script execution evm version, e.g. `berlin`, `cancun`. + /// **Note:** The execution evm version is not the same as the compilation one. + function setEvmVersion(string calldata evm) external; + /// Records the debug trace during the run. function startDebugTraceRecording() external; @@ -733,6 +812,10 @@ interface VmSafe { /// Stops recording storage reads and writes. function stopRecord() external; + /// DEPRECATED: use `lastFrameGas` instead. + /// Gets the gas used in the last call from the callee perspective. + function lastCallGas() external view returns (Gas memory gas); + // ======== Filesystem ======== /// Closes file for reading, resetting the offset and allowing to read it from beginning with readLine. @@ -752,49 +835,69 @@ interface VmSafe { /// `path` is relative to the project root. function createDir(string calldata path, bool recursive) external; + /// Get the source file path of the currently running test or script contract, + /// relative to the project root. + function currentFilePath() external view returns (string memory path); + /// Deploys a contract from an artifact file. Takes in the relative path to the json file or the path to the - /// artifact in the form of :: where and parts are optional. + /// artifact in the form of :: or :: where and + /// / parts are optional. + /// Reverts if the target artifact contains unlinked library placeholders. function deployCode(string calldata artifactPath) external returns (address deployedAddress); /// Deploys a contract from an artifact file. Takes in the relative path to the json file or the path to the - /// artifact in the form of :: where and parts are optional. + /// artifact in the form of :: or :: where and + /// / parts are optional. + /// Reverts if the target artifact contains unlinked library placeholders. /// Additionally accepts abi-encoded constructor arguments. function deployCode(string calldata artifactPath, bytes calldata constructorArgs) external returns (address deployedAddress); /// Deploys a contract from an artifact file. Takes in the relative path to the json file or the path to the - /// artifact in the form of :: where and parts are optional. + /// artifact in the form of :: or :: where and + /// / parts are optional. + /// Reverts if the target artifact contains unlinked library placeholders. /// Additionally accepts `msg.value`. function deployCode(string calldata artifactPath, uint256 value) external returns (address deployedAddress); /// Deploys a contract from an artifact file. Takes in the relative path to the json file or the path to the - /// artifact in the form of :: where and parts are optional. + /// artifact in the form of :: or :: where and + /// / parts are optional. + /// Reverts if the target artifact contains unlinked library placeholders. /// Additionally accepts abi-encoded constructor arguments and `msg.value`. function deployCode(string calldata artifactPath, bytes calldata constructorArgs, uint256 value) external returns (address deployedAddress); /// Deploys a contract from an artifact file, using the CREATE2 salt. Takes in the relative path to the json file or the path to the - /// artifact in the form of :: where and parts are optional. + /// artifact in the form of :: or :: where and + /// / parts are optional. + /// Reverts if the target artifact contains unlinked library placeholders. function deployCode(string calldata artifactPath, bytes32 salt) external returns (address deployedAddress); /// Deploys a contract from an artifact file, using the CREATE2 salt. Takes in the relative path to the json file or the path to the - /// artifact in the form of :: where and parts are optional. + /// artifact in the form of :: or :: where and + /// / parts are optional. + /// Reverts if the target artifact contains unlinked library placeholders. /// Additionally accepts abi-encoded constructor arguments. function deployCode(string calldata artifactPath, bytes calldata constructorArgs, bytes32 salt) external returns (address deployedAddress); /// Deploys a contract from an artifact file, using the CREATE2 salt. Takes in the relative path to the json file or the path to the - /// artifact in the form of :: where and parts are optional. + /// artifact in the form of :: or :: where and + /// / parts are optional. + /// Reverts if the target artifact contains unlinked library placeholders. /// Additionally accepts `msg.value`. function deployCode(string calldata artifactPath, uint256 value, bytes32 salt) external returns (address deployedAddress); /// Deploys a contract from an artifact file, using the CREATE2 salt. Takes in the relative path to the json file or the path to the - /// artifact in the form of :: where and parts are optional. + /// artifact in the form of :: or :: where and + /// / parts are optional. + /// Reverts if the target artifact contains unlinked library placeholders. /// Additionally accepts abi-encoded constructor arguments and `msg.value`. function deployCode(string calldata artifactPath, bytes calldata constructorArgs, uint256 value, bytes32 salt) external @@ -839,21 +942,21 @@ interface VmSafe { returns (BroadcastTxSummary[] memory); /// Gets the creation bytecode from an artifact file. Takes in the relative path to the json file or the path to the - /// artifact in the form of :: where and parts are optional. + /// artifact in the form of :: or :: where and + /// / parts are optional. Use to select artifacts compiled with a specific profile + /// from foundry.toml. function getCode(string calldata artifactPath) external view returns (bytes memory creationBytecode); /// Gets the deployed bytecode from an artifact file. Takes in the relative path to the json file or the path to the - /// artifact in the form of :: where and parts are optional. + /// artifact in the form of :: or :: where and + /// / parts are optional. function getDeployedCode(string calldata artifactPath) external view returns (bytes memory runtimeBytecode); /// Returns the most recent deployment for the current `chainId`. function getDeployment(string calldata contractName) external view returns (address deployedAddress); /// Returns the most recent deployment for the given contract on `chainId` - function getDeployment(string calldata contractName, uint64 chainId) - external - view - returns (address deployedAddress); + function getDeployment(string calldata contractName, uint64 chainId) external view returns (address deployedAddress); /// Returns all deployments for the given contract on `chainId` /// Sorted in descending order of deployment time i.e descending order of BroadcastTxSummary.blockNumber. @@ -960,10 +1063,7 @@ interface VmSafe { function parseJsonAddress(string calldata json, string calldata key) external pure returns (address); /// Parses a string of JSON data at `key` and coerces it to `address[]`. - function parseJsonAddressArray(string calldata json, string calldata key) - external - pure - returns (address[] memory); + function parseJsonAddressArray(string calldata json, string calldata key) external pure returns (address[] memory); /// Parses a string of JSON data at `key` and coerces it to `bool`. function parseJsonBool(string calldata json, string calldata key) external pure returns (bool); @@ -978,10 +1078,7 @@ interface VmSafe { function parseJsonBytes32(string calldata json, string calldata key) external pure returns (bytes32); /// Parses a string of JSON data at `key` and coerces it to `bytes32[]`. - function parseJsonBytes32Array(string calldata json, string calldata key) - external - pure - returns (bytes32[] memory); + function parseJsonBytes32Array(string calldata json, string calldata key) external pure returns (bytes32[] memory); /// Parses a string of JSON data at `key` and coerces it to `bytes[]`. function parseJsonBytesArray(string calldata json, string calldata key) external pure returns (bytes[] memory); @@ -1008,10 +1105,7 @@ interface VmSafe { returns (bytes memory); /// Parses a string of JSON data and coerces it to type corresponding to `typeDescription`. - function parseJsonType(string calldata json, string calldata typeDescription) - external - pure - returns (bytes memory); + function parseJsonType(string calldata json, string calldata typeDescription) external pure returns (bytes memory); /// Parses a string of JSON data at `key` and coerces it to type corresponding to `typeDescription`. function parseJsonType(string calldata json, string calldata key, string calldata typeDescription) @@ -1293,7 +1387,7 @@ interface VmSafe { uint256 right, uint256 maxDelta, uint256 decimals, - string calldata error + string calldata err ) external pure; /// Compares two `int256` values. Expects difference to be less than or equal to `maxDelta`. @@ -1307,7 +1401,7 @@ interface VmSafe { int256 right, uint256 maxDelta, uint256 decimals, - string calldata error + string calldata err ) external pure; /// Compares two `uint256` values. Expects difference to be less than or equal to `maxDelta`. @@ -1315,14 +1409,14 @@ interface VmSafe { /// Compares two `uint256` values. Expects difference to be less than or equal to `maxDelta`. /// Includes error message into revert string on failure. - function assertApproxEqAbs(uint256 left, uint256 right, uint256 maxDelta, string calldata error) external pure; + function assertApproxEqAbs(uint256 left, uint256 right, uint256 maxDelta, string calldata err) external pure; /// Compares two `int256` values. Expects difference to be less than or equal to `maxDelta`. function assertApproxEqAbs(int256 left, int256 right, uint256 maxDelta) external pure; /// Compares two `int256` values. Expects difference to be less than or equal to `maxDelta`. /// Includes error message into revert string on failure. - function assertApproxEqAbs(int256 left, int256 right, uint256 maxDelta, string calldata error) external pure; + function assertApproxEqAbs(int256 left, int256 right, uint256 maxDelta, string calldata err) external pure; /// Compares two `uint256` values. Expects relative difference in percents to be less than or equal to `maxPercentDelta`. /// `maxPercentDelta` is an 18 decimal fixed point number, where 1e18 == 100% @@ -1339,7 +1433,7 @@ interface VmSafe { uint256 right, uint256 maxPercentDelta, uint256 decimals, - string calldata error + string calldata err ) external pure; /// Compares two `int256` values. Expects relative difference in percents to be less than or equal to `maxPercentDelta`. @@ -1357,7 +1451,7 @@ interface VmSafe { int256 right, uint256 maxPercentDelta, uint256 decimals, - string calldata error + string calldata err ) external pure; /// Compares two `uint256` values. Expects relative difference in percents to be less than or equal to `maxPercentDelta`. @@ -1367,9 +1461,7 @@ interface VmSafe { /// Compares two `uint256` values. Expects relative difference in percents to be less than or equal to `maxPercentDelta`. /// `maxPercentDelta` is an 18 decimal fixed point number, where 1e18 == 100% /// Includes error message into revert string on failure. - function assertApproxEqRel(uint256 left, uint256 right, uint256 maxPercentDelta, string calldata error) - external - pure; + function assertApproxEqRel(uint256 left, uint256 right, uint256 maxPercentDelta, string calldata err) external pure; /// Compares two `int256` values. Expects relative difference in percents to be less than or equal to `maxPercentDelta`. /// `maxPercentDelta` is an 18 decimal fixed point number, where 1e18 == 100% @@ -1378,59 +1470,57 @@ interface VmSafe { /// Compares two `int256` values. Expects relative difference in percents to be less than or equal to `maxPercentDelta`. /// `maxPercentDelta` is an 18 decimal fixed point number, where 1e18 == 100% /// Includes error message into revert string on failure. - function assertApproxEqRel(int256 left, int256 right, uint256 maxPercentDelta, string calldata error) - external - pure; + function assertApproxEqRel(int256 left, int256 right, uint256 maxPercentDelta, string calldata err) external pure; /// Asserts that two `uint256` values are equal, formatting them with decimals in failure message. function assertEqDecimal(uint256 left, uint256 right, uint256 decimals) external pure; /// Asserts that two `uint256` values are equal, formatting them with decimals in failure message. /// Includes error message into revert string on failure. - function assertEqDecimal(uint256 left, uint256 right, uint256 decimals, string calldata error) external pure; + function assertEqDecimal(uint256 left, uint256 right, uint256 decimals, string calldata err) external pure; /// Asserts that two `int256` values are equal, formatting them with decimals in failure message. function assertEqDecimal(int256 left, int256 right, uint256 decimals) external pure; /// Asserts that two `int256` values are equal, formatting them with decimals in failure message. /// Includes error message into revert string on failure. - function assertEqDecimal(int256 left, int256 right, uint256 decimals, string calldata error) external pure; + function assertEqDecimal(int256 left, int256 right, uint256 decimals, string calldata err) external pure; /// Asserts that two `bool` values are equal. function assertEq(bool left, bool right) external pure; /// Asserts that two `bool` values are equal and includes error message into revert string on failure. - function assertEq(bool left, bool right, string calldata error) external pure; + function assertEq(bool left, bool right, string calldata err) external pure; /// Asserts that two `string` values are equal. function assertEq(string calldata left, string calldata right) external pure; /// Asserts that two `string` values are equal and includes error message into revert string on failure. - function assertEq(string calldata left, string calldata right, string calldata error) external pure; + function assertEq(string calldata left, string calldata right, string calldata err) external pure; /// Asserts that two `bytes` values are equal. function assertEq(bytes calldata left, bytes calldata right) external pure; /// Asserts that two `bytes` values are equal and includes error message into revert string on failure. - function assertEq(bytes calldata left, bytes calldata right, string calldata error) external pure; + function assertEq(bytes calldata left, bytes calldata right, string calldata err) external pure; /// Asserts that two arrays of `bool` values are equal. function assertEq(bool[] calldata left, bool[] calldata right) external pure; /// Asserts that two arrays of `bool` values are equal and includes error message into revert string on failure. - function assertEq(bool[] calldata left, bool[] calldata right, string calldata error) external pure; + function assertEq(bool[] calldata left, bool[] calldata right, string calldata err) external pure; /// Asserts that two arrays of `uint256 values are equal. function assertEq(uint256[] calldata left, uint256[] calldata right) external pure; /// Asserts that two arrays of `uint256` values are equal and includes error message into revert string on failure. - function assertEq(uint256[] calldata left, uint256[] calldata right, string calldata error) external pure; + function assertEq(uint256[] calldata left, uint256[] calldata right, string calldata err) external pure; /// Asserts that two arrays of `int256` values are equal. function assertEq(int256[] calldata left, int256[] calldata right) external pure; /// Asserts that two arrays of `int256` values are equal and includes error message into revert string on failure. - function assertEq(int256[] calldata left, int256[] calldata right, string calldata error) external pure; + function assertEq(int256[] calldata left, int256[] calldata right, string calldata err) external pure; /// Asserts that two `uint256` values are equal. function assertEq(uint256 left, uint256 right) external pure; @@ -1439,52 +1529,52 @@ interface VmSafe { function assertEq(address[] calldata left, address[] calldata right) external pure; /// Asserts that two arrays of `address` values are equal and includes error message into revert string on failure. - function assertEq(address[] calldata left, address[] calldata right, string calldata error) external pure; + function assertEq(address[] calldata left, address[] calldata right, string calldata err) external pure; /// Asserts that two arrays of `bytes32` values are equal. function assertEq(bytes32[] calldata left, bytes32[] calldata right) external pure; /// Asserts that two arrays of `bytes32` values are equal and includes error message into revert string on failure. - function assertEq(bytes32[] calldata left, bytes32[] calldata right, string calldata error) external pure; + function assertEq(bytes32[] calldata left, bytes32[] calldata right, string calldata err) external pure; /// Asserts that two arrays of `string` values are equal. function assertEq(string[] calldata left, string[] calldata right) external pure; /// Asserts that two arrays of `string` values are equal and includes error message into revert string on failure. - function assertEq(string[] calldata left, string[] calldata right, string calldata error) external pure; + function assertEq(string[] calldata left, string[] calldata right, string calldata err) external pure; /// Asserts that two arrays of `bytes` values are equal. function assertEq(bytes[] calldata left, bytes[] calldata right) external pure; /// Asserts that two arrays of `bytes` values are equal and includes error message into revert string on failure. - function assertEq(bytes[] calldata left, bytes[] calldata right, string calldata error) external pure; + function assertEq(bytes[] calldata left, bytes[] calldata right, string calldata err) external pure; /// Asserts that two `uint256` values are equal and includes error message into revert string on failure. - function assertEq(uint256 left, uint256 right, string calldata error) external pure; + function assertEq(uint256 left, uint256 right, string calldata err) external pure; /// Asserts that two `int256` values are equal. function assertEq(int256 left, int256 right) external pure; /// Asserts that two `int256` values are equal and includes error message into revert string on failure. - function assertEq(int256 left, int256 right, string calldata error) external pure; + function assertEq(int256 left, int256 right, string calldata err) external pure; /// Asserts that two `address` values are equal. function assertEq(address left, address right) external pure; /// Asserts that two `address` values are equal and includes error message into revert string on failure. - function assertEq(address left, address right, string calldata error) external pure; + function assertEq(address left, address right, string calldata err) external pure; /// Asserts that two `bytes32` values are equal. function assertEq(bytes32 left, bytes32 right) external pure; /// Asserts that two `bytes32` values are equal and includes error message into revert string on failure. - function assertEq(bytes32 left, bytes32 right, string calldata error) external pure; + function assertEq(bytes32 left, bytes32 right, string calldata err) external pure; /// Asserts that the given condition is false. function assertFalse(bool condition) external pure; /// Asserts that the given condition is false and includes error message into revert string on failure. - function assertFalse(bool condition, string calldata error) external pure; + function assertFalse(bool condition, string calldata err) external pure; /// Compares two `uint256` values. Expects first value to be greater than or equal to second. /// Formats values with decimals in failure message. @@ -1492,7 +1582,7 @@ interface VmSafe { /// Compares two `uint256` values. Expects first value to be greater than or equal to second. /// Formats values with decimals in failure message. Includes error message into revert string on failure. - function assertGeDecimal(uint256 left, uint256 right, uint256 decimals, string calldata error) external pure; + function assertGeDecimal(uint256 left, uint256 right, uint256 decimals, string calldata err) external pure; /// Compares two `int256` values. Expects first value to be greater than or equal to second. /// Formats values with decimals in failure message. @@ -1500,21 +1590,21 @@ interface VmSafe { /// Compares two `int256` values. Expects first value to be greater than or equal to second. /// Formats values with decimals in failure message. Includes error message into revert string on failure. - function assertGeDecimal(int256 left, int256 right, uint256 decimals, string calldata error) external pure; + function assertGeDecimal(int256 left, int256 right, uint256 decimals, string calldata err) external pure; /// Compares two `uint256` values. Expects first value to be greater than or equal to second. function assertGe(uint256 left, uint256 right) external pure; /// Compares two `uint256` values. Expects first value to be greater than or equal to second. /// Includes error message into revert string on failure. - function assertGe(uint256 left, uint256 right, string calldata error) external pure; + function assertGe(uint256 left, uint256 right, string calldata err) external pure; /// Compares two `int256` values. Expects first value to be greater than or equal to second. function assertGe(int256 left, int256 right) external pure; /// Compares two `int256` values. Expects first value to be greater than or equal to second. /// Includes error message into revert string on failure. - function assertGe(int256 left, int256 right, string calldata error) external pure; + function assertGe(int256 left, int256 right, string calldata err) external pure; /// Compares two `uint256` values. Expects first value to be greater than second. /// Formats values with decimals in failure message. @@ -1522,7 +1612,7 @@ interface VmSafe { /// Compares two `uint256` values. Expects first value to be greater than second. /// Formats values with decimals in failure message. Includes error message into revert string on failure. - function assertGtDecimal(uint256 left, uint256 right, uint256 decimals, string calldata error) external pure; + function assertGtDecimal(uint256 left, uint256 right, uint256 decimals, string calldata err) external pure; /// Compares two `int256` values. Expects first value to be greater than second. /// Formats values with decimals in failure message. @@ -1530,21 +1620,21 @@ interface VmSafe { /// Compares two `int256` values. Expects first value to be greater than second. /// Formats values with decimals in failure message. Includes error message into revert string on failure. - function assertGtDecimal(int256 left, int256 right, uint256 decimals, string calldata error) external pure; + function assertGtDecimal(int256 left, int256 right, uint256 decimals, string calldata err) external pure; /// Compares two `uint256` values. Expects first value to be greater than second. function assertGt(uint256 left, uint256 right) external pure; /// Compares two `uint256` values. Expects first value to be greater than second. /// Includes error message into revert string on failure. - function assertGt(uint256 left, uint256 right, string calldata error) external pure; + function assertGt(uint256 left, uint256 right, string calldata err) external pure; /// Compares two `int256` values. Expects first value to be greater than second. function assertGt(int256 left, int256 right) external pure; /// Compares two `int256` values. Expects first value to be greater than second. /// Includes error message into revert string on failure. - function assertGt(int256 left, int256 right, string calldata error) external pure; + function assertGt(int256 left, int256 right, string calldata err) external pure; /// Compares two `uint256` values. Expects first value to be less than or equal to second. /// Formats values with decimals in failure message. @@ -1552,7 +1642,7 @@ interface VmSafe { /// Compares two `uint256` values. Expects first value to be less than or equal to second. /// Formats values with decimals in failure message. Includes error message into revert string on failure. - function assertLeDecimal(uint256 left, uint256 right, uint256 decimals, string calldata error) external pure; + function assertLeDecimal(uint256 left, uint256 right, uint256 decimals, string calldata err) external pure; /// Compares two `int256` values. Expects first value to be less than or equal to second. /// Formats values with decimals in failure message. @@ -1560,21 +1650,21 @@ interface VmSafe { /// Compares two `int256` values. Expects first value to be less than or equal to second. /// Formats values with decimals in failure message. Includes error message into revert string on failure. - function assertLeDecimal(int256 left, int256 right, uint256 decimals, string calldata error) external pure; + function assertLeDecimal(int256 left, int256 right, uint256 decimals, string calldata err) external pure; /// Compares two `uint256` values. Expects first value to be less than or equal to second. function assertLe(uint256 left, uint256 right) external pure; /// Compares two `uint256` values. Expects first value to be less than or equal to second. /// Includes error message into revert string on failure. - function assertLe(uint256 left, uint256 right, string calldata error) external pure; + function assertLe(uint256 left, uint256 right, string calldata err) external pure; /// Compares two `int256` values. Expects first value to be less than or equal to second. function assertLe(int256 left, int256 right) external pure; /// Compares two `int256` values. Expects first value to be less than or equal to second. /// Includes error message into revert string on failure. - function assertLe(int256 left, int256 right, string calldata error) external pure; + function assertLe(int256 left, int256 right, string calldata err) external pure; /// Compares two `uint256` values. Expects first value to be less than second. /// Formats values with decimals in failure message. @@ -1582,7 +1672,7 @@ interface VmSafe { /// Compares two `uint256` values. Expects first value to be less than second. /// Formats values with decimals in failure message. Includes error message into revert string on failure. - function assertLtDecimal(uint256 left, uint256 right, uint256 decimals, string calldata error) external pure; + function assertLtDecimal(uint256 left, uint256 right, uint256 decimals, string calldata err) external pure; /// Compares two `int256` values. Expects first value to be less than second. /// Formats values with decimals in failure message. @@ -1590,71 +1680,71 @@ interface VmSafe { /// Compares two `int256` values. Expects first value to be less than second. /// Formats values with decimals in failure message. Includes error message into revert string on failure. - function assertLtDecimal(int256 left, int256 right, uint256 decimals, string calldata error) external pure; + function assertLtDecimal(int256 left, int256 right, uint256 decimals, string calldata err) external pure; /// Compares two `uint256` values. Expects first value to be less than second. function assertLt(uint256 left, uint256 right) external pure; /// Compares two `uint256` values. Expects first value to be less than second. /// Includes error message into revert string on failure. - function assertLt(uint256 left, uint256 right, string calldata error) external pure; + function assertLt(uint256 left, uint256 right, string calldata err) external pure; /// Compares two `int256` values. Expects first value to be less than second. function assertLt(int256 left, int256 right) external pure; /// Compares two `int256` values. Expects first value to be less than second. /// Includes error message into revert string on failure. - function assertLt(int256 left, int256 right, string calldata error) external pure; + function assertLt(int256 left, int256 right, string calldata err) external pure; /// Asserts that two `uint256` values are not equal, formatting them with decimals in failure message. function assertNotEqDecimal(uint256 left, uint256 right, uint256 decimals) external pure; /// Asserts that two `uint256` values are not equal, formatting them with decimals in failure message. /// Includes error message into revert string on failure. - function assertNotEqDecimal(uint256 left, uint256 right, uint256 decimals, string calldata error) external pure; + function assertNotEqDecimal(uint256 left, uint256 right, uint256 decimals, string calldata err) external pure; /// Asserts that two `int256` values are not equal, formatting them with decimals in failure message. function assertNotEqDecimal(int256 left, int256 right, uint256 decimals) external pure; /// Asserts that two `int256` values are not equal, formatting them with decimals in failure message. /// Includes error message into revert string on failure. - function assertNotEqDecimal(int256 left, int256 right, uint256 decimals, string calldata error) external pure; + function assertNotEqDecimal(int256 left, int256 right, uint256 decimals, string calldata err) external pure; /// Asserts that two `bool` values are not equal. function assertNotEq(bool left, bool right) external pure; /// Asserts that two `bool` values are not equal and includes error message into revert string on failure. - function assertNotEq(bool left, bool right, string calldata error) external pure; + function assertNotEq(bool left, bool right, string calldata err) external pure; /// Asserts that two `string` values are not equal. function assertNotEq(string calldata left, string calldata right) external pure; /// Asserts that two `string` values are not equal and includes error message into revert string on failure. - function assertNotEq(string calldata left, string calldata right, string calldata error) external pure; + function assertNotEq(string calldata left, string calldata right, string calldata err) external pure; /// Asserts that two `bytes` values are not equal. function assertNotEq(bytes calldata left, bytes calldata right) external pure; /// Asserts that two `bytes` values are not equal and includes error message into revert string on failure. - function assertNotEq(bytes calldata left, bytes calldata right, string calldata error) external pure; + function assertNotEq(bytes calldata left, bytes calldata right, string calldata err) external pure; /// Asserts that two arrays of `bool` values are not equal. function assertNotEq(bool[] calldata left, bool[] calldata right) external pure; /// Asserts that two arrays of `bool` values are not equal and includes error message into revert string on failure. - function assertNotEq(bool[] calldata left, bool[] calldata right, string calldata error) external pure; + function assertNotEq(bool[] calldata left, bool[] calldata right, string calldata err) external pure; /// Asserts that two arrays of `uint256` values are not equal. function assertNotEq(uint256[] calldata left, uint256[] calldata right) external pure; /// Asserts that two arrays of `uint256` values are not equal and includes error message into revert string on failure. - function assertNotEq(uint256[] calldata left, uint256[] calldata right, string calldata error) external pure; + function assertNotEq(uint256[] calldata left, uint256[] calldata right, string calldata err) external pure; /// Asserts that two arrays of `int256` values are not equal. function assertNotEq(int256[] calldata left, int256[] calldata right) external pure; /// Asserts that two arrays of `int256` values are not equal and includes error message into revert string on failure. - function assertNotEq(int256[] calldata left, int256[] calldata right, string calldata error) external pure; + function assertNotEq(int256[] calldata left, int256[] calldata right, string calldata err) external pure; /// Asserts that two `uint256` values are not equal. function assertNotEq(uint256 left, uint256 right) external pure; @@ -1663,56 +1753,59 @@ interface VmSafe { function assertNotEq(address[] calldata left, address[] calldata right) external pure; /// Asserts that two arrays of `address` values are not equal and includes error message into revert string on failure. - function assertNotEq(address[] calldata left, address[] calldata right, string calldata error) external pure; + function assertNotEq(address[] calldata left, address[] calldata right, string calldata err) external pure; /// Asserts that two arrays of `bytes32` values are not equal. function assertNotEq(bytes32[] calldata left, bytes32[] calldata right) external pure; /// Asserts that two arrays of `bytes32` values are not equal and includes error message into revert string on failure. - function assertNotEq(bytes32[] calldata left, bytes32[] calldata right, string calldata error) external pure; + function assertNotEq(bytes32[] calldata left, bytes32[] calldata right, string calldata err) external pure; /// Asserts that two arrays of `string` values are not equal. function assertNotEq(string[] calldata left, string[] calldata right) external pure; /// Asserts that two arrays of `string` values are not equal and includes error message into revert string on failure. - function assertNotEq(string[] calldata left, string[] calldata right, string calldata error) external pure; + function assertNotEq(string[] calldata left, string[] calldata right, string calldata err) external pure; /// Asserts that two arrays of `bytes` values are not equal. function assertNotEq(bytes[] calldata left, bytes[] calldata right) external pure; /// Asserts that two arrays of `bytes` values are not equal and includes error message into revert string on failure. - function assertNotEq(bytes[] calldata left, bytes[] calldata right, string calldata error) external pure; + function assertNotEq(bytes[] calldata left, bytes[] calldata right, string calldata err) external pure; /// Asserts that two `uint256` values are not equal and includes error message into revert string on failure. - function assertNotEq(uint256 left, uint256 right, string calldata error) external pure; + function assertNotEq(uint256 left, uint256 right, string calldata err) external pure; /// Asserts that two `int256` values are not equal. function assertNotEq(int256 left, int256 right) external pure; /// Asserts that two `int256` values are not equal and includes error message into revert string on failure. - function assertNotEq(int256 left, int256 right, string calldata error) external pure; + function assertNotEq(int256 left, int256 right, string calldata err) external pure; /// Asserts that two `address` values are not equal. function assertNotEq(address left, address right) external pure; /// Asserts that two `address` values are not equal and includes error message into revert string on failure. - function assertNotEq(address left, address right, string calldata error) external pure; + function assertNotEq(address left, address right, string calldata err) external pure; /// Asserts that two `bytes32` values are not equal. function assertNotEq(bytes32 left, bytes32 right) external pure; /// Asserts that two `bytes32` values are not equal and includes error message into revert string on failure. - function assertNotEq(bytes32 left, bytes32 right, string calldata error) external pure; + function assertNotEq(bytes32 left, bytes32 right, string calldata err) external pure; /// Asserts that the given condition is true. function assertTrue(bool condition) external pure; /// Asserts that the given condition is true and includes error message into revert string on failure. - function assertTrue(bool condition, string calldata error) external pure; + function assertTrue(bool condition, string calldata err) external pure; /// If the condition is false, discard this run's fuzz inputs and generate new ones. function assume(bool condition) external pure; + /// Skips a fuzz/invariant input unless `spender` is implicitly approved. + function assumeImplicitApproval(address spender) external view; + /// Discard this run's fuzz inputs and generate new ones if next call reverted. function assumeNoRevert() external pure; @@ -1779,10 +1872,7 @@ interface VmSafe { function parseTomlAddress(string calldata toml, string calldata key) external pure returns (address); /// Parses a string of TOML data at `key` and coerces it to `address[]`. - function parseTomlAddressArray(string calldata toml, string calldata key) - external - pure - returns (address[] memory); + function parseTomlAddressArray(string calldata toml, string calldata key) external pure returns (address[] memory); /// Parses a string of TOML data at `key` and coerces it to `bool`. function parseTomlBool(string calldata toml, string calldata key) external pure returns (bool); @@ -1797,10 +1887,7 @@ interface VmSafe { function parseTomlBytes32(string calldata toml, string calldata key) external pure returns (bytes32); /// Parses a string of TOML data at `key` and coerces it to `bytes32[]`. - function parseTomlBytes32Array(string calldata toml, string calldata key) - external - pure - returns (bytes32[] memory); + function parseTomlBytes32Array(string calldata toml, string calldata key) external pure returns (bytes32[] memory); /// Parses a string of TOML data at `key` and coerces it to `bytes[]`. function parseTomlBytesArray(string calldata toml, string calldata key) external pure returns (bytes[] memory); @@ -1827,10 +1914,7 @@ interface VmSafe { returns (bytes memory); /// Parses a string of TOML data and coerces it to type corresponding to `typeDescription`. - function parseTomlType(string calldata toml, string calldata typeDescription) - external - pure - returns (bytes memory); + function parseTomlType(string calldata toml, string calldata typeDescription) external pure returns (bytes memory); /// Parses a string of TOML data at `key` and coerces it to type corresponding to `typeDescription`. function parseTomlType(string calldata toml, string calldata key, string calldata typeDescription) @@ -1867,10 +1951,7 @@ interface VmSafe { function bound(int256 current, int256 min, int256 max) external view returns (int256); /// Compute the address of a contract created with CREATE2 using the given CREATE2 deployer. - function computeCreate2Address(bytes32 salt, bytes32 initCodeHash, address deployer) - external - pure - returns (address); + function computeCreate2Address(bytes32 salt, bytes32 initCodeHash, address deployer) external pure returns (address); /// Compute the address of a contract created with CREATE2 using the default CREATE2 deployer. function computeCreate2Address(bytes32 salt, bytes32 initCodeHash) external pure returns (address); @@ -1878,16 +1959,13 @@ interface VmSafe { /// Compute the address a contract will be deployed at for a given deployer address and nonce. function computeCreateAddress(address deployer, uint256 nonce) external pure returns (address); - /// Utility cheatcode to copy storage of `from` contract to another `to` contract. - function copyStorage(address from, address to) external; - /// Generates the struct hash of the canonical EIP-712 type representation and its abi-encoded data. /// Supports 2 different inputs: /// 1. Name of the type (i.e. "PermitSingle"): /// * requires previous binding generation with `forge bind-json`. /// * bindings will be retrieved from the path configured in `foundry.toml`. /// 2. String representation of the type (i.e. "Foo(Bar bar) Bar(uint256 baz)"). - /// * Note: the cheatcode will use the canonical type even if the input is malformated + /// * Note: the cheatcode will use the canonical type even if the input is malformed /// with the wrong order of elements or with extra whitespaces. function eip712HashStruct(string calldata typeNameOrDefinition, bytes calldata abiEncodedData) external @@ -1911,7 +1989,7 @@ interface VmSafe { /// * requires previous binding generation with `forge bind-json`. /// * bindings will be retrieved from the path configured in `foundry.toml`. /// 2. String representation of the type (i.e. "Foo(Bar bar) Bar(uint256 baz)"). - /// * Note: the cheatcode will output the canonical type even if the input is malformated + /// * Note: the cheatcode will output the canonical type even if the input is malformed /// with the wrong order of elements or with extra whitespaces. function eip712HashType(string calldata typeNameOrDefinition) external pure returns (bytes32 typeHash); @@ -1931,6 +2009,9 @@ interface VmSafe { /// Returns ENS namehash for provided string. function ensNamehash(string calldata name) external pure returns (bytes32); + /// RLP decodes an RLP payload into a list of bytes. + function fromRlp(bytes calldata rlp) external pure returns (bytes[] memory data); + /// Gets the label for the specified address. function getLabel(address account) external view returns (string memory currentLabel); @@ -1974,13 +2055,6 @@ interface VmSafe { /// Unpauses collection of call traces. function resumeTracing() external view; - /// Utility cheatcode to set arbitrary storage for given target address. - function setArbitraryStorage(address target) external; - - /// Utility cheatcode to set arbitrary storage for given target address and overwrite - /// any storage slots that have been previously set. - function setArbitraryStorage(address target, bool overwrite) external; - /// Set RNG seed. function setSeed(uint256 seed) external; @@ -2001,6 +2075,9 @@ interface VmSafe { /// Encodes a `string` value to a base64 string. function toBase64(string calldata data) external pure returns (string memory); + + /// RLP encodes a list of bytes into an RLP payload. + function toRlp(bytes[] calldata data) external pure returns (bytes memory); } /// The `Vm` interface does allow manipulation of the EVM state. These are all intended to be used @@ -2086,6 +2163,12 @@ interface Vm is VmSafe { /// Sets an address' code. function etch(address target, bytes calldata newRuntimeBytecode) external; + /// Executes an RLP-encoded signed transaction with full EVM semantics (like `--isolate` mode). + /// The transaction is decoded from EIP-2718 format (type byte prefix + RLP payload) or legacy RLP. + /// Returns the execution output bytes. + /// This cheatcode is not allowed in `forge script` contexts. + function executeTransaction(bytes calldata rawTx) external returns (bytes memory); + /// Sets `block.basefee`. function fee(uint256 newBasefee) external; @@ -2117,8 +2200,7 @@ interface Vm is VmSafe { function mockCallRevert(address callee, bytes calldata data, bytes calldata revertData) external; /// Reverts a call to an address with a specific `msg.value`, with specified revert data. - function mockCallRevert(address callee, uint256 msgValue, bytes calldata data, bytes calldata revertData) - external; + function mockCallRevert(address callee, uint256 msgValue, bytes calldata data, bytes calldata revertData) external; /// Reverts a call to an address with specified revert data. /// Overload to pass the function selector directly `token.approve.selector` instead of `abi.encodeWithSelector(token.approve.selector)`. @@ -2238,17 +2320,25 @@ interface Vm is VmSafe { /// It only sets the blockhash for blocks where `block.number - 256 <= number < block.number`. function setBlockhash(uint256 blockNumber, bytes32 blockHash) external; + /// Sets a TIP-20 token's logo URI directly in storage. + /// This bypasses the token admin check, but still validates the URI against T5 constraints. + function setLogoURI(address token, string calldata newLogoURI) external; + /// Sets the nonce of an account. Must be higher than the current nonce of the account. function setNonce(address account, uint64 newNonce) external; /// Sets the nonce of an account to an arbitrary value. function setNonceUnsafe(address account, uint64 newNonce) external; - /// Snapshot capture the gas usage of the last call by name from the callee perspective. - function snapshotGasLastCall(string calldata name) external returns (uint256 gasUsed); + /// Sets a TIP-20 token's logo URI directly in storage. + /// This bypasses the token admin check, but still validates the URI against T5 constraints. + function setTip20LogoURI(address token, string calldata newLogoURI) external; - /// Snapshot capture the gas usage of the last call by name in a group from the callee perspective. - function snapshotGasLastCall(string calldata group, string calldata name) external returns (uint256 gasUsed); + /// Snapshot capture the gas usage of the last call or create by name from the callee perspective. + function snapshotGasLastFrame(string calldata name) external returns (uint256 gasUsed); + + /// Snapshot capture the gas usage of the last call or create by name in a group from the callee perspective. + function snapshotGasLastFrame(string calldata group, string calldata name) external returns (uint256 gasUsed); /// Snapshot the current state of the evm. /// Returns the ID of the snapshot that was created. @@ -2324,6 +2414,14 @@ interface Vm is VmSafe { /// `revertTo` is being deprecated in favor of `revertToState`. It will be removed in future versions. function revertTo(uint256 snapshotId) external returns (bool success); + /// DEPRECATED: use `snapshotGasLastFrame` instead. + /// Snapshot capture the gas usage of the last call by name from the callee perspective. + function snapshotGasLastCall(string calldata name) external returns (uint256 gasUsed); + + /// DEPRECATED: use `snapshotGasLastFrame` instead. + /// Snapshot capture the gas usage of the last call by name in a group from the callee perspective. + function snapshotGasLastCall(string calldata group, string calldata name) external returns (uint256 gasUsed); + /// `snapshot` is being deprecated in favor of `snapshotState`. It will be removed in future versions. function snapshot() external returns (uint256 snapshotId); @@ -2388,15 +2486,20 @@ interface Vm is VmSafe { /// Prepare an expected log with (bool checkTopic1, bool checkTopic2, bool checkTopic3, bool checkData.). /// Call this function, then emit an event, then call a function. Internally after the call, we check if /// logs were emitted in the expected order with the expected topics and data (as specified by the booleans). + /// Must be placed immediately before the call you want to assert on. If the next call reverts and the + /// revert is caught by the caller (low-level call or try/catch), the expectation remains active and may + /// be satisfied by a log emitted from a later call. function expectEmit(bool checkTopic1, bool checkTopic2, bool checkTopic3, bool checkData) external; /// Same as the previous method, but also checks supplied address against emitting contract. - function expectEmit(bool checkTopic1, bool checkTopic2, bool checkTopic3, bool checkData, address emitter) - external; + function expectEmit(bool checkTopic1, bool checkTopic2, bool checkTopic3, bool checkData, address emitter) external; /// Prepare an expected log with all topic and data checks enabled. /// Call this function, then emit an event, then call a function. Internally after the call, we check if /// logs were emitted in the expected order with the expected topics and data. + /// Must be placed immediately before the call you want to assert on. If the next call reverts and the + /// revert is caught by the caller (low-level call or try/catch), the expectation remains active and may + /// be satisfied by a log emitted from a later call. function expectEmit() external; /// Same as the previous method, but also checks supplied address against emitting contract. @@ -2421,10 +2524,22 @@ interface Vm is VmSafe { /// Expect a given number of logs from a specific emitter with all topic and data checks enabled. function expectEmit(address emitter, uint64 count) external; + /// Expects a call to `SignatureVerifier.verifyKeychainAdmin(account, digest, signature)`. + /// The supplied `digest` should already be domain-separated with chain ID, contract address, + /// and account address. + function expectKeychainAdminVerified(address account, bytes32 digest, bytes calldata signature) external; + + /// Expects a call to `SignatureVerifier.verifyKeychain(account, digest, signature)`. + function expectKeychainVerified(address account, bytes32 digest, bytes calldata signature) external; + + /// Expects a TIP-20 `LogoURIUpdated(address indexed updater, string newLogoURI)` event. + function expectLogoURIUpdated(address token, address updater, string calldata newLogoURI) external; + /// Expects an error on next call that starts with the revert data. function expectPartialRevert(bytes4 revertData) external; /// Expects an error on next call to reverter address, that starts with the revert data. + /// See `expectRevert(address)` for `reverter` matching semantics. function expectPartialRevert(bytes4 revertData, address reverter) external; /// Expects an error on next call with any revert data. @@ -2434,21 +2549,35 @@ interface Vm is VmSafe { function expectRevert(bytes4 revertData) external; /// Expects a `count` number of reverts from the upcoming calls from the reverter address that match the revert data. + /// See `expectRevert(address)` for `reverter` matching semantics. function expectRevert(bytes4 revertData, address reverter, uint64 count) external; /// Expects a `count` number of reverts from the upcoming calls from the reverter address that exactly match the revert data. + /// See `expectRevert(address)` for `reverter` matching semantics. function expectRevert(bytes calldata revertData, address reverter, uint64 count) external; /// Expects an error on next call that exactly matches the revert data. function expectRevert(bytes calldata revertData) external; /// Expects an error with any revert data on next call to reverter address. + /// The `reverter` argument is matched against the address associated with + /// the frame that produced the revert: + /// - For a CALL: the address that was called. + /// - For a CREATE / CREATE2: the would-be deployed address of the failed + /// deployment (computed from the deployer + nonce, or salt + initcode). + /// For a single expected revert, the innermost reverting frame wins in + /// nested CALL, CREATE, or mixed chains. With `count > 1`, nested + /// CREATE / CREATE2 chains apply the same rule independently to each + /// iteration; nested CALL chains keep their existing + /// outermost-call-per-iteration behavior. function expectRevert(address reverter) external; /// Expects an error from reverter address on next call, with any revert data. + /// See `expectRevert(address)` for `reverter` matching semantics. function expectRevert(bytes4 revertData, address reverter) external; /// Expects an error from reverter address on next call, that exactly matches the revert data. + /// See `expectRevert(address)` for `reverter` matching semantics. function expectRevert(bytes calldata revertData, address reverter) external; /// Expects a `count` number of reverts from the upcoming calls with any revert data or reverter. @@ -2461,6 +2590,7 @@ interface Vm is VmSafe { function expectRevert(bytes calldata revertData, uint64 count) external; /// Expects a `count` number of reverts from the upcoming calls from the reverter address. + /// See `expectRevert(address)` for `reverter` matching semantics. function expectRevert(address reverter, uint64 count) external; /// Only allows memory writes to offsets [0x00, 0x60) ∪ [min, max) in the current subcontext. If any other @@ -2472,6 +2602,9 @@ interface Vm is VmSafe { /// to the set. function expectSafeMemoryCall(uint64 min, uint64 max) external; + /// Expects a TIP-20 `LogoURIUpdated(address indexed updater, string newLogoURI)` event. + function expectTip20LogoURIUpdated(address token, address updater, string calldata newLogoURI) external; + /// Marks a test as skipped. Must be called at the top level of a test. function skip(bool skipTest) external; @@ -2483,6 +2616,9 @@ interface Vm is VmSafe { // ======== Utilities ======== + /// Utility cheatcode to copy storage of `from` contract to another `to` contract. + function copyStorage(address from, address to) external; + /// Causes the next contract creation (via new) to fail and return its initcode in the returndata buffer. /// This allows type-safe access to the initcode payload that would be used for contract creation. /// Example usage: @@ -2491,4 +2627,11 @@ interface Vm is VmSafe { /// try new MyContract(param1, param2) { assert(false); } /// catch (bytes memory interceptedInitcode) { initcode = interceptedInitcode; } function interceptInitcode() external; + + /// Utility cheatcode to set arbitrary storage for given target address. + function setArbitraryStorage(address target) external; + + /// Utility cheatcode to set arbitrary storage for given target address and overwrite + /// any storage slots that have been previously set. + function setArbitraryStorage(address target, bool overwrite) external; } diff --git a/dependencies/forge-std-1.11.0/src/console.sol b/dependencies/forge-std-1.16.2/src/console.sol similarity index 96% rename from dependencies/forge-std-1.11.0/src/console.sol rename to dependencies/forge-std-1.16.2/src/console.sol index 4fdb667..0ac1b69 100644 --- a/dependencies/forge-std-1.11.0/src/console.sol +++ b/dependencies/forge-std-1.16.2/src/console.sol @@ -1,30 +1,21 @@ -// SPDX-License-Identifier: MIT -pragma solidity >=0.4.22 <0.9.0; +// SPDX-License-Identifier: MIT OR Apache-2.0 +pragma solidity >=0.8.13 <0.9.0; library console { - address constant CONSOLE_ADDRESS = - 0x000000000000000000636F6e736F6c652e6c6f67; + address constant CONSOLE_ADDRESS = 0x000000000000000000636F6e736F6c652e6c6f67; function _sendLogPayloadImplementation(bytes memory payload) internal view { address consoleAddress = CONSOLE_ADDRESS; - /// @solidity memory-safe-assembly - assembly { - pop( - staticcall( - gas(), - consoleAddress, - add(payload, 32), - mload(payload), - 0, - 0 - ) - ) + assembly ("memory-safe") { + pop(staticcall(gas(), consoleAddress, add(payload, 32), mload(payload), 0, 0)) } } - function _castToPure( - function(bytes memory) internal view fnIn - ) internal pure returns (function(bytes memory) pure fnOut) { + function _castToPure(function(bytes memory) internal view fnIn) + internal + pure + returns (function(bytes memory) pure fnOut) + { assembly { fnOut := fnIn } @@ -1557,4 +1548,52 @@ library console { function log(address p0, address p1, address p2, address p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(address,address,address,address)", p0, p1, p2, p3)); } + + function table(uint256[] memory values) internal pure { + _sendLogPayload(abi.encodeWithSignature("table(uint256[])", values)); + } + + function table(int256[] memory values) internal pure { + _sendLogPayload(abi.encodeWithSignature("table(int256[])", values)); + } + + function table(address[] memory values) internal pure { + _sendLogPayload(abi.encodeWithSignature("table(address[])", values)); + } + + function table(bytes32[] memory values) internal pure { + _sendLogPayload(abi.encodeWithSignature("table(bytes32[])", values)); + } + + function table(string[] memory values) internal pure { + _sendLogPayload(abi.encodeWithSignature("table(string[])", values)); + } + + function table(bool[] memory values) internal pure { + _sendLogPayload(abi.encodeWithSignature("table(bool[])", values)); + } + + function table(string[] memory keys, uint256[] memory values) internal pure { + _sendLogPayload(abi.encodeWithSignature("table(string[],uint256[])", keys, values)); + } + + function table(string[] memory keys, int256[] memory values) internal pure { + _sendLogPayload(abi.encodeWithSignature("table(string[],int256[])", keys, values)); + } + + function table(string[] memory keys, address[] memory values) internal pure { + _sendLogPayload(abi.encodeWithSignature("table(string[],address[])", keys, values)); + } + + function table(string[] memory keys, bytes32[] memory values) internal pure { + _sendLogPayload(abi.encodeWithSignature("table(string[],bytes32[])", keys, values)); + } + + function table(string[] memory keys, string[] memory values) internal pure { + _sendLogPayload(abi.encodeWithSignature("table(string[],string[])", keys, values)); + } + + function table(string[] memory keys, bool[] memory values) internal pure { + _sendLogPayload(abi.encodeWithSignature("table(string[],bool[])", keys, values)); + } } diff --git a/dependencies/forge-std-1.16.2/src/console2.sol b/dependencies/forge-std-1.16.2/src/console2.sol new file mode 100644 index 0000000..1ecdbbf --- /dev/null +++ b/dependencies/forge-std-1.16.2/src/console2.sol @@ -0,0 +1,4 @@ +// SPDX-License-Identifier: MIT OR Apache-2.0 +pragma solidity >=0.8.13 <0.9.0; + +import {console as console2} from "./console.sol"; diff --git a/dependencies/forge-std-1.11.0/src/interfaces/IERC1155.sol b/dependencies/forge-std-1.16.2/src/interfaces/IERC1155.sol similarity index 98% rename from dependencies/forge-std-1.11.0/src/interfaces/IERC1155.sol rename to dependencies/forge-std-1.16.2/src/interfaces/IERC1155.sol index ffc8298..9bf979d 100644 --- a/dependencies/forge-std-1.11.0/src/interfaces/IERC1155.sol +++ b/dependencies/forge-std-1.16.2/src/interfaces/IERC1155.sol @@ -1,5 +1,5 @@ -// SPDX-License-Identifier: MIT -pragma solidity >=0.6.2; +// SPDX-License-Identifier: MIT OR Apache-2.0 +pragma solidity >=0.8.13 <0.9.0; import {IERC165} from "./IERC165.sol"; diff --git a/dependencies/forge-std-1.11.0/src/interfaces/IERC165.sol b/dependencies/forge-std-1.16.2/src/interfaces/IERC165.sol similarity index 85% rename from dependencies/forge-std-1.11.0/src/interfaces/IERC165.sol rename to dependencies/forge-std-1.16.2/src/interfaces/IERC165.sol index 9af4bf8..fced182 100644 --- a/dependencies/forge-std-1.11.0/src/interfaces/IERC165.sol +++ b/dependencies/forge-std-1.16.2/src/interfaces/IERC165.sol @@ -1,5 +1,5 @@ -// SPDX-License-Identifier: MIT -pragma solidity >=0.6.2; +// SPDX-License-Identifier: MIT OR Apache-2.0 +pragma solidity >=0.8.13 <0.9.0; interface IERC165 { /// @notice Query if a contract implements an interface diff --git a/dependencies/forge-std-1.11.0/src/interfaces/IERC20.sol b/dependencies/forge-std-1.16.2/src/interfaces/IERC20.sol similarity index 96% rename from dependencies/forge-std-1.11.0/src/interfaces/IERC20.sol rename to dependencies/forge-std-1.16.2/src/interfaces/IERC20.sol index ba40806..1a17fe1 100644 --- a/dependencies/forge-std-1.11.0/src/interfaces/IERC20.sol +++ b/dependencies/forge-std-1.16.2/src/interfaces/IERC20.sol @@ -1,5 +1,5 @@ -// SPDX-License-Identifier: MIT -pragma solidity >=0.6.2; +// SPDX-License-Identifier: MIT OR Apache-2.0 +pragma solidity >=0.8.13 <0.9.0; /// @dev Interface of the ERC20 standard as defined in the EIP. /// @dev This includes the optional name, symbol, and decimals metadata. diff --git a/dependencies/forge-std-1.11.0/src/interfaces/IERC4626.sol b/dependencies/forge-std-1.16.2/src/interfaces/IERC4626.sol similarity index 94% rename from dependencies/forge-std-1.11.0/src/interfaces/IERC4626.sol rename to dependencies/forge-std-1.16.2/src/interfaces/IERC4626.sol index c645a0f..e63fce4 100644 --- a/dependencies/forge-std-1.11.0/src/interfaces/IERC4626.sol +++ b/dependencies/forge-std-1.16.2/src/interfaces/IERC4626.sol @@ -1,5 +1,5 @@ -// SPDX-License-Identifier: MIT -pragma solidity >=0.6.2; +// SPDX-License-Identifier: MIT OR Apache-2.0 +pragma solidity >=0.8.13 <0.9.0; import {IERC20} from "./IERC20.sol"; @@ -79,7 +79,7 @@ interface IERC4626 is IERC20 { /// - 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 + /// - MUST revert if all 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. @@ -112,7 +112,7 @@ interface IERC4626 is IERC20 { /// - 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 + /// - MUST revert if all 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. @@ -138,7 +138,7 @@ interface IERC4626 is IERC20 { /// - 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. + /// share price or some other type of condition, meaning the owner will lose assets by withdrawing. function previewWithdraw(uint256 assets) external view returns (uint256 shares); /// @notice Burns shares from owner and sends exactly assets of underlying tokens to receiver. @@ -146,7 +146,7 @@ interface IERC4626 is IERC20 { /// - 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 withdrawal. - /// - MUST revert if all of assets cannot be withdrawn (due to withdrawal limit being reached, slippage, the owner + /// - MUST revert if all 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. @@ -161,7 +161,7 @@ interface IERC4626 is IERC20 { /// - MUST NOT revert. function maxRedeem(address owner) external view returns (uint256 maxShares); - /// @notice Allows an on-chain or off-chain user to simulate the effects of their redeemption at the current block, + /// @notice Allows an on-chain or off-chain user to simulate the effects of their redemption at the current block, /// given current on-chain conditions. /// @dev /// - MUST return as close to and no more than the exact amount of assets that would be withdrawn in a redeem call @@ -173,7 +173,7 @@ interface IERC4626 is IERC20 { /// - 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. + /// share price or some other type of condition, meaning the owner will lose assets by redeeming. function previewRedeem(uint256 shares) external view returns (uint256 assets); /// @notice Burns exactly shares from owner and sends assets of underlying tokens to receiver. @@ -181,7 +181,7 @@ interface IERC4626 is IERC20 { /// - 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 + /// - MUST revert if all 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. diff --git a/dependencies/forge-std-1.11.0/src/interfaces/IERC6909.sol b/dependencies/forge-std-1.16.2/src/interfaces/IERC6909.sol similarity index 97% rename from dependencies/forge-std-1.11.0/src/interfaces/IERC6909.sol rename to dependencies/forge-std-1.16.2/src/interfaces/IERC6909.sol index 6e11cb4..d448b0f 100644 --- a/dependencies/forge-std-1.11.0/src/interfaces/IERC6909.sol +++ b/dependencies/forge-std-1.16.2/src/interfaces/IERC6909.sol @@ -1,5 +1,5 @@ -// SPDX-License-Identifier: MIT -pragma solidity >=0.6.2; +// SPDX-License-Identifier: MIT OR Apache-2.0 +pragma solidity >=0.8.13 <0.9.0; import {IERC165} from "./IERC165.sol"; diff --git a/dependencies/forge-std-1.11.0/src/interfaces/IERC721.sol b/dependencies/forge-std-1.16.2/src/interfaces/IERC721.sol similarity index 99% rename from dependencies/forge-std-1.11.0/src/interfaces/IERC721.sol rename to dependencies/forge-std-1.16.2/src/interfaces/IERC721.sol index 21a4a94..9a03145 100644 --- a/dependencies/forge-std-1.11.0/src/interfaces/IERC721.sol +++ b/dependencies/forge-std-1.16.2/src/interfaces/IERC721.sol @@ -1,5 +1,5 @@ -// SPDX-License-Identifier: MIT -pragma solidity >=0.6.2; +// SPDX-License-Identifier: MIT OR Apache-2.0 +pragma solidity >=0.8.13 <0.9.0; import {IERC165} from "./IERC165.sol"; diff --git a/dependencies/forge-std-1.11.0/src/interfaces/IERC7540.sol b/dependencies/forge-std-1.16.2/src/interfaces/IERC7540.sol similarity index 87% rename from dependencies/forge-std-1.11.0/src/interfaces/IERC7540.sol rename to dependencies/forge-std-1.16.2/src/interfaces/IERC7540.sol index 91a38ca..3082c51 100644 --- a/dependencies/forge-std-1.11.0/src/interfaces/IERC7540.sol +++ b/dependencies/forge-std-1.16.2/src/interfaces/IERC7540.sol @@ -1,5 +1,5 @@ -// SPDX-License-Identifier: MIT -pragma solidity >=0.6.2; +// SPDX-License-Identifier: MIT OR Apache-2.0 +pragma solidity >=0.8.13 <0.9.0; import {IERC7575} from "./IERC7575.sol"; @@ -44,7 +44,7 @@ interface IERC7540Deposit is IERC7540Operator { * @dev Transfers assets from sender into the Vault and submits a Request for asynchronous deposit. * * - MUST support ERC-20 approve / transferFrom on asset as a deposit Request flow. - * - MUST revert if all of assets cannot be requested for deposit. + * - MUST revert if all assets cannot be requested for deposit. * - owner MUST be msg.sender unless some unspecified explicit approval is given by the caller, * approval of ERC-20 tokens from owner to sender is NOT enough. * @@ -64,10 +64,7 @@ interface IERC7540Deposit is IERC7540Operator { * - MUST NOT show any variations depending on the caller. * - MUST NOT revert unless due to integer overflow caused by an unreasonably large input. */ - function pendingDepositRequest(uint256 requestId, address controller) - external - view - returns (uint256 pendingAssets); + function pendingDepositRequest(uint256 requestId, address controller) external view returns (uint256 pendingAssets); /** * @dev Returns the amount of requested assets in Claimable state for the controller to deposit or mint. @@ -98,19 +95,20 @@ interface IERC7540Deposit is IERC7540Operator { function mint(uint256 shares, address receiver, address controller) external returns (uint256 assets); } -/// @dev Interface of the asynchronous deposit Vault interface of ERC7540, as defined in +/// @dev Interface of the asynchronous redeem Vault interface of ERC7540, as defined in /// https://eips.ethereum.org/EIPS/eip-7540 interface IERC7540Redeem is IERC7540Operator { event RedeemRequest( - address indexed controller, address indexed owner, uint256 indexed requestId, address sender, uint256 assets + address indexed controller, address indexed owner, uint256 indexed requestId, address sender, uint256 shares ); /** - * @dev Assumes control of shares from sender into the Vault and submits a Request for asynchronous redeem. + * @dev Assumes control of shares from owner and submits a Request for asynchronous redeem. * - * - MUST support a redeem Request flow where the control of shares is taken from sender directly - * where msg.sender has ERC-20 approval over the shares of owner. - * - MUST revert if all of shares cannot be requested for redeem. + * - MUST support a redeem Request flow where the control of shares is taken from owner directly. + * - Redeem Request approval of shares for a msg.sender not equal to owner MAY come either from ERC-20 approval + * over the shares of owner or if the owner has approved the msg.sender as an operator. + * - MUST revert if all shares cannot be requested for redeem or withdraw. * * @param shares the amount of shares to be redeemed to transfer from owner * @param controller the controller of the request who will be able to operate the request @@ -127,10 +125,7 @@ interface IERC7540Redeem is IERC7540Operator { * - MUST NOT show any variations depending on the caller. * - MUST NOT revert unless due to integer overflow caused by an unreasonably large input. */ - function pendingRedeemRequest(uint256 requestId, address controller) - external - view - returns (uint256 pendingShares); + function pendingRedeemRequest(uint256 requestId, address controller) external view returns (uint256 pendingShares); /** * @dev Returns the amount of requested shares in Claimable state for the controller to redeem or withdraw. diff --git a/dependencies/forge-std-1.11.0/src/interfaces/IERC7575.sol b/dependencies/forge-std-1.16.2/src/interfaces/IERC7575.sol similarity index 95% rename from dependencies/forge-std-1.11.0/src/interfaces/IERC7575.sol rename to dependencies/forge-std-1.16.2/src/interfaces/IERC7575.sol index 207e3e7..980f766 100644 --- a/dependencies/forge-std-1.11.0/src/interfaces/IERC7575.sol +++ b/dependencies/forge-std-1.16.2/src/interfaces/IERC7575.sol @@ -1,5 +1,5 @@ -// SPDX-License-Identifier: MIT -pragma solidity >=0.6.2; +// SPDX-License-Identifier: MIT OR Apache-2.0 +pragma solidity >=0.8.13 <0.9.0; import {IERC165} from "./IERC165.sol"; @@ -99,7 +99,7 @@ interface IERC7575 is IERC165 { * - 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 + * - MUST revert if all 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. @@ -137,7 +137,7 @@ interface IERC7575 is IERC165 { * - 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 + * - MUST revert if all 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. @@ -167,7 +167,7 @@ interface IERC7575 is IERC165 { * - 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. + * share price or some other type of condition, meaning the owner will lose assets by withdrawing. */ function previewWithdraw(uint256 assets) external view returns (uint256 shares); @@ -177,7 +177,7 @@ interface IERC7575 is IERC165 { * - 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 + * - MUST revert if all 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. @@ -196,7 +196,7 @@ interface IERC7575 is IERC165 { function maxRedeem(address owner) external view returns (uint256 maxShares); /** - * @dev Allows an on-chain or off-chain user to simulate the effects of their redeemption at the current block, + * @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 @@ -208,7 +208,7 @@ interface IERC7575 is IERC165 { * - 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. + * share price or some other type of condition, meaning the owner will lose assets by redeeming. */ function previewRedeem(uint256 shares) external view returns (uint256 assets); @@ -218,7 +218,7 @@ interface IERC7575 is IERC165 { * - 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 + * - MUST revert if all 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. diff --git a/dependencies/forge-std-1.11.0/src/interfaces/IMulticall3.sol b/dependencies/forge-std-1.16.2/src/interfaces/IMulticall3.sol similarity index 88% rename from dependencies/forge-std-1.11.0/src/interfaces/IMulticall3.sol rename to dependencies/forge-std-1.16.2/src/interfaces/IMulticall3.sol index 0d031b7..6a94133 100644 --- a/dependencies/forge-std-1.11.0/src/interfaces/IMulticall3.sol +++ b/dependencies/forge-std-1.16.2/src/interfaces/IMulticall3.sol @@ -1,7 +1,5 @@ -// SPDX-License-Identifier: MIT -pragma solidity >=0.6.2 <0.9.0; - -pragma experimental ABIEncoderV2; +// SPDX-License-Identifier: MIT OR Apache-2.0 +pragma solidity >=0.8.13 <0.9.0; interface IMulticall3 { struct Call { @@ -27,10 +25,7 @@ interface IMulticall3 { bytes returnData; } - function aggregate(Call[] calldata calls) - external - payable - returns (uint256 blockNumber, bytes[] memory returnData); + function aggregate(Call[] calldata calls) external payable returns (uint256 blockNumber, bytes[] memory returnData); function aggregate3(Call3[] calldata calls) external payable returns (Result[] memory returnData); diff --git a/dependencies/forge-std-1.11.0/src/safeconsole.sol b/dependencies/forge-std-1.16.2/src/safeconsole.sol similarity index 89% rename from dependencies/forge-std-1.11.0/src/safeconsole.sol rename to dependencies/forge-std-1.16.2/src/safeconsole.sol index 87c475a..e12d060 100644 --- a/dependencies/forge-std-1.11.0/src/safeconsole.sol +++ b/dependencies/forge-std-1.16.2/src/safeconsole.sol @@ -1,5 +1,5 @@ -// SPDX-License-Identifier: MIT -pragma solidity >=0.6.2 <0.9.0; +// SPDX-License-Identifier: MIT OR Apache-2.0 +pragma solidity >=0.8.13 <0.9.0; /// @author philogy /// @dev Code generated automatically by script. @@ -11,16 +11,14 @@ library safeconsole { function _sendLogPayload(uint256 offset, uint256 size) private pure { function(uint256, uint256) internal view fnIn = _sendLogPayloadView; function(uint256, uint256) internal pure pureSendLogPayload; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { pureSendLogPayload := fnIn } pureSendLogPayload(offset, size); } function _sendLogPayloadView(uint256 offset, uint256 size) private view { - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { pop(staticcall(gas(), CONSOLE_ADDR, offset, size, 0x0, 0x0)) } } @@ -28,16 +26,14 @@ library safeconsole { function _memcopy(uint256 fromOffset, uint256 toOffset, uint256 length) private pure { function(uint256, uint256, uint256) internal view fnIn = _memcopyView; function(uint256, uint256, uint256) internal pure pureMemcopy; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { pureMemcopy := fnIn } pureMemcopy(fromOffset, toOffset, length); } function _memcopyView(uint256 fromOffset, uint256 toOffset, uint256 length) private view { - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { pop(staticcall(gas(), 0x4, fromOffset, length, toOffset, length)) } } @@ -48,8 +44,7 @@ library safeconsole { bytes32 m0; bytes32 m1; bytes32 m2; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { m0 := mload(sub(offset, 0x60)) m1 := mload(sub(offset, 0x40)) m2 := mload(sub(offset, 0x20)) @@ -59,8 +54,7 @@ library safeconsole { mstore(sub(offset, 0x20), length) } _sendLogPayload(offset - 0x44, length + 0x44); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(sub(offset, 0x60), m0) mstore(sub(offset, 0x40), m1) mstore(sub(offset, 0x20), m2) @@ -71,15 +65,13 @@ library safeconsole { bytes32 m1; bytes32 m2; uint256 endOffset = offset + length; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { m0 := mload(add(endOffset, 0x00)) m1 := mload(add(endOffset, 0x20)) m2 := mload(add(endOffset, 0x40)) } _memcopy(offset, offset + 0x60, length); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { // Selector of `log(bytes)`. mstore(add(offset, 0x00), 0x0be77f56) mstore(add(offset, 0x20), 0x20) @@ -87,8 +79,7 @@ library safeconsole { } _sendLogPayload(offset + 0x1c, length + 0x44); _memcopy(offset + 0x60, offset, length); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(add(endOffset, 0x00), m0) mstore(add(endOffset, 0x20), m1) mstore(add(endOffset, 0x40), m2) @@ -99,8 +90,7 @@ library safeconsole { function log(address p0) internal pure { bytes32 m0; bytes32 m1; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { m0 := mload(0x00) m1 := mload(0x20) // Selector of `log(address)`. @@ -108,8 +98,7 @@ library safeconsole { mstore(0x20, p0) } _sendLogPayload(0x1c, 0x24); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) } @@ -118,8 +107,7 @@ library safeconsole { function log(bool p0) internal pure { bytes32 m0; bytes32 m1; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { m0 := mload(0x00) m1 := mload(0x20) // Selector of `log(bool)`. @@ -127,8 +115,7 @@ library safeconsole { mstore(0x20, p0) } _sendLogPayload(0x1c, 0x24); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) } @@ -137,8 +124,7 @@ library safeconsole { function log(uint256 p0) internal pure { bytes32 m0; bytes32 m1; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { m0 := mload(0x00) m1 := mload(0x20) // Selector of `log(uint256)`. @@ -146,8 +132,7 @@ library safeconsole { mstore(0x20, p0) } _sendLogPayload(0x1c, 0x24); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) } @@ -158,8 +143,7 @@ library safeconsole { bytes32 m1; bytes32 m2; bytes32 m3; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } @@ -177,8 +161,7 @@ library safeconsole { writeString(0x40, p0) } _sendLogPayload(0x1c, 0x64); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -190,8 +173,7 @@ library safeconsole { bytes32 m0; bytes32 m1; bytes32 m2; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) @@ -201,8 +183,7 @@ library safeconsole { mstore(0x40, p1) } _sendLogPayload(0x1c, 0x44); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -213,8 +194,7 @@ library safeconsole { bytes32 m0; bytes32 m1; bytes32 m2; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) @@ -224,8 +204,7 @@ library safeconsole { mstore(0x40, p1) } _sendLogPayload(0x1c, 0x44); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -236,8 +215,7 @@ library safeconsole { bytes32 m0; bytes32 m1; bytes32 m2; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) @@ -247,8 +225,7 @@ library safeconsole { mstore(0x40, p1) } _sendLogPayload(0x1c, 0x44); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -261,8 +238,7 @@ library safeconsole { bytes32 m2; bytes32 m3; bytes32 m4; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } @@ -282,8 +258,7 @@ library safeconsole { writeString(0x60, p1) } _sendLogPayload(0x1c, 0x84); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -296,8 +271,7 @@ library safeconsole { bytes32 m0; bytes32 m1; bytes32 m2; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) @@ -307,8 +281,7 @@ library safeconsole { mstore(0x40, p1) } _sendLogPayload(0x1c, 0x44); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -319,8 +292,7 @@ library safeconsole { bytes32 m0; bytes32 m1; bytes32 m2; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) @@ -330,8 +302,7 @@ library safeconsole { mstore(0x40, p1) } _sendLogPayload(0x1c, 0x44); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -342,8 +313,7 @@ library safeconsole { bytes32 m0; bytes32 m1; bytes32 m2; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) @@ -353,8 +323,7 @@ library safeconsole { mstore(0x40, p1) } _sendLogPayload(0x1c, 0x44); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -367,8 +336,7 @@ library safeconsole { bytes32 m2; bytes32 m3; bytes32 m4; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } @@ -388,8 +356,7 @@ library safeconsole { writeString(0x60, p1) } _sendLogPayload(0x1c, 0x84); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -402,8 +369,7 @@ library safeconsole { bytes32 m0; bytes32 m1; bytes32 m2; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) @@ -413,8 +379,7 @@ library safeconsole { mstore(0x40, p1) } _sendLogPayload(0x1c, 0x44); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -425,8 +390,7 @@ library safeconsole { bytes32 m0; bytes32 m1; bytes32 m2; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) @@ -436,8 +400,7 @@ library safeconsole { mstore(0x40, p1) } _sendLogPayload(0x1c, 0x44); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -448,8 +411,7 @@ library safeconsole { bytes32 m0; bytes32 m1; bytes32 m2; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) @@ -459,8 +421,7 @@ library safeconsole { mstore(0x40, p1) } _sendLogPayload(0x1c, 0x44); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -473,8 +434,7 @@ library safeconsole { bytes32 m2; bytes32 m3; bytes32 m4; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } @@ -494,8 +454,7 @@ library safeconsole { writeString(0x60, p1) } _sendLogPayload(0x1c, 0x84); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -510,8 +469,7 @@ library safeconsole { bytes32 m2; bytes32 m3; bytes32 m4; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } @@ -531,8 +489,7 @@ library safeconsole { writeString(0x60, p0) } _sendLogPayload(0x1c, 0x84); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -547,8 +504,7 @@ library safeconsole { bytes32 m2; bytes32 m3; bytes32 m4; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } @@ -568,8 +524,7 @@ library safeconsole { writeString(0x60, p0) } _sendLogPayload(0x1c, 0x84); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -584,8 +539,7 @@ library safeconsole { bytes32 m2; bytes32 m3; bytes32 m4; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } @@ -605,8 +559,7 @@ library safeconsole { writeString(0x60, p0) } _sendLogPayload(0x1c, 0x84); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -623,8 +576,7 @@ library safeconsole { bytes32 m4; bytes32 m5; bytes32 m6; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } @@ -647,8 +599,7 @@ library safeconsole { writeString(0xa0, p1) } _sendLogPayload(0x1c, 0xc4); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -664,8 +615,7 @@ library safeconsole { bytes32 m1; bytes32 m2; bytes32 m3; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) @@ -677,8 +627,7 @@ library safeconsole { mstore(0x60, p2) } _sendLogPayload(0x1c, 0x64); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -691,8 +640,7 @@ library safeconsole { bytes32 m1; bytes32 m2; bytes32 m3; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) @@ -704,8 +652,7 @@ library safeconsole { mstore(0x60, p2) } _sendLogPayload(0x1c, 0x64); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -718,8 +665,7 @@ library safeconsole { bytes32 m1; bytes32 m2; bytes32 m3; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) @@ -731,8 +677,7 @@ library safeconsole { mstore(0x60, p2) } _sendLogPayload(0x1c, 0x64); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -747,8 +692,7 @@ library safeconsole { bytes32 m3; bytes32 m4; bytes32 m5; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } @@ -770,8 +714,7 @@ library safeconsole { writeString(0x80, p2) } _sendLogPayload(0x1c, 0xa4); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -786,8 +729,7 @@ library safeconsole { bytes32 m1; bytes32 m2; bytes32 m3; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) @@ -799,8 +741,7 @@ library safeconsole { mstore(0x60, p2) } _sendLogPayload(0x1c, 0x64); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -813,8 +754,7 @@ library safeconsole { bytes32 m1; bytes32 m2; bytes32 m3; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) @@ -826,8 +766,7 @@ library safeconsole { mstore(0x60, p2) } _sendLogPayload(0x1c, 0x64); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -840,8 +779,7 @@ library safeconsole { bytes32 m1; bytes32 m2; bytes32 m3; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) @@ -853,8 +791,7 @@ library safeconsole { mstore(0x60, p2) } _sendLogPayload(0x1c, 0x64); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -869,8 +806,7 @@ library safeconsole { bytes32 m3; bytes32 m4; bytes32 m5; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } @@ -892,8 +828,7 @@ library safeconsole { writeString(0x80, p2) } _sendLogPayload(0x1c, 0xa4); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -908,8 +843,7 @@ library safeconsole { bytes32 m1; bytes32 m2; bytes32 m3; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) @@ -921,8 +855,7 @@ library safeconsole { mstore(0x60, p2) } _sendLogPayload(0x1c, 0x64); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -935,8 +868,7 @@ library safeconsole { bytes32 m1; bytes32 m2; bytes32 m3; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) @@ -948,8 +880,7 @@ library safeconsole { mstore(0x60, p2) } _sendLogPayload(0x1c, 0x64); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -962,8 +893,7 @@ library safeconsole { bytes32 m1; bytes32 m2; bytes32 m3; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) @@ -975,8 +905,7 @@ library safeconsole { mstore(0x60, p2) } _sendLogPayload(0x1c, 0x64); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -991,8 +920,7 @@ library safeconsole { bytes32 m3; bytes32 m4; bytes32 m5; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } @@ -1014,8 +942,7 @@ library safeconsole { writeString(0x80, p2) } _sendLogPayload(0x1c, 0xa4); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -1032,8 +959,7 @@ library safeconsole { bytes32 m3; bytes32 m4; bytes32 m5; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } @@ -1055,8 +981,7 @@ library safeconsole { writeString(0x80, p1) } _sendLogPayload(0x1c, 0xa4); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -1073,8 +998,7 @@ library safeconsole { bytes32 m3; bytes32 m4; bytes32 m5; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } @@ -1096,8 +1020,7 @@ library safeconsole { writeString(0x80, p1) } _sendLogPayload(0x1c, 0xa4); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -1114,8 +1037,7 @@ library safeconsole { bytes32 m3; bytes32 m4; bytes32 m5; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } @@ -1137,8 +1059,7 @@ library safeconsole { writeString(0x80, p1) } _sendLogPayload(0x1c, 0xa4); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -1157,8 +1078,7 @@ library safeconsole { bytes32 m5; bytes32 m6; bytes32 m7; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } @@ -1183,8 +1103,7 @@ library safeconsole { writeString(0xc0, p2) } _sendLogPayload(0x1c, 0xe4); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -1201,8 +1120,7 @@ library safeconsole { bytes32 m1; bytes32 m2; bytes32 m3; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) @@ -1214,8 +1132,7 @@ library safeconsole { mstore(0x60, p2) } _sendLogPayload(0x1c, 0x64); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -1228,8 +1145,7 @@ library safeconsole { bytes32 m1; bytes32 m2; bytes32 m3; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) @@ -1241,8 +1157,7 @@ library safeconsole { mstore(0x60, p2) } _sendLogPayload(0x1c, 0x64); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -1255,8 +1170,7 @@ library safeconsole { bytes32 m1; bytes32 m2; bytes32 m3; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) @@ -1268,8 +1182,7 @@ library safeconsole { mstore(0x60, p2) } _sendLogPayload(0x1c, 0x64); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -1284,8 +1197,7 @@ library safeconsole { bytes32 m3; bytes32 m4; bytes32 m5; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } @@ -1307,8 +1219,7 @@ library safeconsole { writeString(0x80, p2) } _sendLogPayload(0x1c, 0xa4); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -1323,8 +1234,7 @@ library safeconsole { bytes32 m1; bytes32 m2; bytes32 m3; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) @@ -1336,8 +1246,7 @@ library safeconsole { mstore(0x60, p2) } _sendLogPayload(0x1c, 0x64); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -1350,8 +1259,7 @@ library safeconsole { bytes32 m1; bytes32 m2; bytes32 m3; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) @@ -1363,8 +1271,7 @@ library safeconsole { mstore(0x60, p2) } _sendLogPayload(0x1c, 0x64); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -1377,8 +1284,7 @@ library safeconsole { bytes32 m1; bytes32 m2; bytes32 m3; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) @@ -1390,8 +1296,7 @@ library safeconsole { mstore(0x60, p2) } _sendLogPayload(0x1c, 0x64); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -1406,8 +1311,7 @@ library safeconsole { bytes32 m3; bytes32 m4; bytes32 m5; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } @@ -1429,8 +1333,7 @@ library safeconsole { writeString(0x80, p2) } _sendLogPayload(0x1c, 0xa4); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -1445,8 +1348,7 @@ library safeconsole { bytes32 m1; bytes32 m2; bytes32 m3; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) @@ -1458,8 +1360,7 @@ library safeconsole { mstore(0x60, p2) } _sendLogPayload(0x1c, 0x64); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -1472,8 +1373,7 @@ library safeconsole { bytes32 m1; bytes32 m2; bytes32 m3; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) @@ -1485,8 +1385,7 @@ library safeconsole { mstore(0x60, p2) } _sendLogPayload(0x1c, 0x64); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -1499,8 +1398,7 @@ library safeconsole { bytes32 m1; bytes32 m2; bytes32 m3; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) @@ -1512,8 +1410,7 @@ library safeconsole { mstore(0x60, p2) } _sendLogPayload(0x1c, 0x64); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -1528,8 +1425,7 @@ library safeconsole { bytes32 m3; bytes32 m4; bytes32 m5; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } @@ -1551,8 +1447,7 @@ library safeconsole { writeString(0x80, p2) } _sendLogPayload(0x1c, 0xa4); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -1569,8 +1464,7 @@ library safeconsole { bytes32 m3; bytes32 m4; bytes32 m5; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } @@ -1592,8 +1486,7 @@ library safeconsole { writeString(0x80, p1) } _sendLogPayload(0x1c, 0xa4); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -1610,8 +1503,7 @@ library safeconsole { bytes32 m3; bytes32 m4; bytes32 m5; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } @@ -1633,8 +1525,7 @@ library safeconsole { writeString(0x80, p1) } _sendLogPayload(0x1c, 0xa4); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -1651,8 +1542,7 @@ library safeconsole { bytes32 m3; bytes32 m4; bytes32 m5; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } @@ -1674,8 +1564,7 @@ library safeconsole { writeString(0x80, p1) } _sendLogPayload(0x1c, 0xa4); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -1694,8 +1583,7 @@ library safeconsole { bytes32 m5; bytes32 m6; bytes32 m7; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } @@ -1720,8 +1608,7 @@ library safeconsole { writeString(0xc0, p2) } _sendLogPayload(0x1c, 0xe4); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -1738,8 +1625,7 @@ library safeconsole { bytes32 m1; bytes32 m2; bytes32 m3; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) @@ -1751,8 +1637,7 @@ library safeconsole { mstore(0x60, p2) } _sendLogPayload(0x1c, 0x64); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -1765,8 +1650,7 @@ library safeconsole { bytes32 m1; bytes32 m2; bytes32 m3; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) @@ -1778,8 +1662,7 @@ library safeconsole { mstore(0x60, p2) } _sendLogPayload(0x1c, 0x64); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -1792,8 +1675,7 @@ library safeconsole { bytes32 m1; bytes32 m2; bytes32 m3; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) @@ -1805,8 +1687,7 @@ library safeconsole { mstore(0x60, p2) } _sendLogPayload(0x1c, 0x64); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -1821,8 +1702,7 @@ library safeconsole { bytes32 m3; bytes32 m4; bytes32 m5; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } @@ -1844,8 +1724,7 @@ library safeconsole { writeString(0x80, p2) } _sendLogPayload(0x1c, 0xa4); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -1860,8 +1739,7 @@ library safeconsole { bytes32 m1; bytes32 m2; bytes32 m3; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) @@ -1873,8 +1751,7 @@ library safeconsole { mstore(0x60, p2) } _sendLogPayload(0x1c, 0x64); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -1887,8 +1764,7 @@ library safeconsole { bytes32 m1; bytes32 m2; bytes32 m3; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) @@ -1900,8 +1776,7 @@ library safeconsole { mstore(0x60, p2) } _sendLogPayload(0x1c, 0x64); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -1914,8 +1789,7 @@ library safeconsole { bytes32 m1; bytes32 m2; bytes32 m3; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) @@ -1927,8 +1801,7 @@ library safeconsole { mstore(0x60, p2) } _sendLogPayload(0x1c, 0x64); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -1943,8 +1816,7 @@ library safeconsole { bytes32 m3; bytes32 m4; bytes32 m5; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } @@ -1966,8 +1838,7 @@ library safeconsole { writeString(0x80, p2) } _sendLogPayload(0x1c, 0xa4); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -1982,8 +1853,7 @@ library safeconsole { bytes32 m1; bytes32 m2; bytes32 m3; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) @@ -1995,8 +1865,7 @@ library safeconsole { mstore(0x60, p2) } _sendLogPayload(0x1c, 0x64); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -2009,8 +1878,7 @@ library safeconsole { bytes32 m1; bytes32 m2; bytes32 m3; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) @@ -2022,8 +1890,7 @@ library safeconsole { mstore(0x60, p2) } _sendLogPayload(0x1c, 0x64); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -2036,8 +1903,7 @@ library safeconsole { bytes32 m1; bytes32 m2; bytes32 m3; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) @@ -2049,8 +1915,7 @@ library safeconsole { mstore(0x60, p2) } _sendLogPayload(0x1c, 0x64); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -2065,8 +1930,7 @@ library safeconsole { bytes32 m3; bytes32 m4; bytes32 m5; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } @@ -2088,8 +1952,7 @@ library safeconsole { writeString(0x80, p2) } _sendLogPayload(0x1c, 0xa4); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -2106,8 +1969,7 @@ library safeconsole { bytes32 m3; bytes32 m4; bytes32 m5; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } @@ -2129,8 +1991,7 @@ library safeconsole { writeString(0x80, p1) } _sendLogPayload(0x1c, 0xa4); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -2147,8 +2008,7 @@ library safeconsole { bytes32 m3; bytes32 m4; bytes32 m5; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } @@ -2170,8 +2030,7 @@ library safeconsole { writeString(0x80, p1) } _sendLogPayload(0x1c, 0xa4); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -2188,8 +2047,7 @@ library safeconsole { bytes32 m3; bytes32 m4; bytes32 m5; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } @@ -2211,8 +2069,7 @@ library safeconsole { writeString(0x80, p1) } _sendLogPayload(0x1c, 0xa4); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -2231,8 +2088,7 @@ library safeconsole { bytes32 m5; bytes32 m6; bytes32 m7; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } @@ -2257,8 +2113,7 @@ library safeconsole { writeString(0xc0, p2) } _sendLogPayload(0x1c, 0xe4); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -2277,8 +2132,7 @@ library safeconsole { bytes32 m3; bytes32 m4; bytes32 m5; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } @@ -2300,8 +2154,7 @@ library safeconsole { writeString(0x80, p0) } _sendLogPayload(0x1c, 0xa4); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -2318,8 +2171,7 @@ library safeconsole { bytes32 m3; bytes32 m4; bytes32 m5; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } @@ -2341,8 +2193,7 @@ library safeconsole { writeString(0x80, p0) } _sendLogPayload(0x1c, 0xa4); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -2359,8 +2210,7 @@ library safeconsole { bytes32 m3; bytes32 m4; bytes32 m5; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } @@ -2382,8 +2232,7 @@ library safeconsole { writeString(0x80, p0) } _sendLogPayload(0x1c, 0xa4); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -2402,8 +2251,7 @@ library safeconsole { bytes32 m5; bytes32 m6; bytes32 m7; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } @@ -2428,8 +2276,7 @@ library safeconsole { writeString(0xc0, p2) } _sendLogPayload(0x1c, 0xe4); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -2448,8 +2295,7 @@ library safeconsole { bytes32 m3; bytes32 m4; bytes32 m5; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } @@ -2471,8 +2317,7 @@ library safeconsole { writeString(0x80, p0) } _sendLogPayload(0x1c, 0xa4); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -2489,8 +2334,7 @@ library safeconsole { bytes32 m3; bytes32 m4; bytes32 m5; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } @@ -2512,8 +2356,7 @@ library safeconsole { writeString(0x80, p0) } _sendLogPayload(0x1c, 0xa4); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -2530,8 +2373,7 @@ library safeconsole { bytes32 m3; bytes32 m4; bytes32 m5; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } @@ -2553,8 +2395,7 @@ library safeconsole { writeString(0x80, p0) } _sendLogPayload(0x1c, 0xa4); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -2573,8 +2414,7 @@ library safeconsole { bytes32 m5; bytes32 m6; bytes32 m7; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } @@ -2599,8 +2439,7 @@ library safeconsole { writeString(0xc0, p2) } _sendLogPayload(0x1c, 0xe4); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -2619,8 +2458,7 @@ library safeconsole { bytes32 m3; bytes32 m4; bytes32 m5; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } @@ -2642,8 +2480,7 @@ library safeconsole { writeString(0x80, p0) } _sendLogPayload(0x1c, 0xa4); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -2660,8 +2497,7 @@ library safeconsole { bytes32 m3; bytes32 m4; bytes32 m5; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } @@ -2683,8 +2519,7 @@ library safeconsole { writeString(0x80, p0) } _sendLogPayload(0x1c, 0xa4); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -2701,8 +2536,7 @@ library safeconsole { bytes32 m3; bytes32 m4; bytes32 m5; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } @@ -2724,8 +2558,7 @@ library safeconsole { writeString(0x80, p0) } _sendLogPayload(0x1c, 0xa4); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -2744,8 +2577,7 @@ library safeconsole { bytes32 m5; bytes32 m6; bytes32 m7; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } @@ -2770,8 +2602,7 @@ library safeconsole { writeString(0xc0, p2) } _sendLogPayload(0x1c, 0xe4); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -2792,8 +2623,7 @@ library safeconsole { bytes32 m5; bytes32 m6; bytes32 m7; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } @@ -2818,8 +2648,7 @@ library safeconsole { writeString(0xc0, p1) } _sendLogPayload(0x1c, 0xe4); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -2840,8 +2669,7 @@ library safeconsole { bytes32 m5; bytes32 m6; bytes32 m7; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } @@ -2866,8 +2694,7 @@ library safeconsole { writeString(0xc0, p1) } _sendLogPayload(0x1c, 0xe4); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -2888,8 +2715,7 @@ library safeconsole { bytes32 m5; bytes32 m6; bytes32 m7; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } @@ -2914,8 +2740,7 @@ library safeconsole { writeString(0xc0, p1) } _sendLogPayload(0x1c, 0xe4); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -2938,8 +2763,7 @@ library safeconsole { bytes32 m7; bytes32 m8; bytes32 m9; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } @@ -2967,8 +2791,7 @@ library safeconsole { writeString(0x100, p2) } _sendLogPayload(0x1c, 0x124); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -2988,8 +2811,7 @@ library safeconsole { bytes32 m2; bytes32 m3; bytes32 m4; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) @@ -3003,8 +2825,7 @@ library safeconsole { mstore(0x80, p3) } _sendLogPayload(0x1c, 0x84); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -3019,8 +2840,7 @@ library safeconsole { bytes32 m2; bytes32 m3; bytes32 m4; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) @@ -3034,8 +2854,7 @@ library safeconsole { mstore(0x80, p3) } _sendLogPayload(0x1c, 0x84); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -3050,8 +2869,7 @@ library safeconsole { bytes32 m2; bytes32 m3; bytes32 m4; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) @@ -3065,8 +2883,7 @@ library safeconsole { mstore(0x80, p3) } _sendLogPayload(0x1c, 0x84); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -3083,8 +2900,7 @@ library safeconsole { bytes32 m4; bytes32 m5; bytes32 m6; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } @@ -3108,8 +2924,7 @@ library safeconsole { writeString(0xa0, p3) } _sendLogPayload(0x1c, 0xc4); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -3126,8 +2941,7 @@ library safeconsole { bytes32 m2; bytes32 m3; bytes32 m4; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) @@ -3141,8 +2955,7 @@ library safeconsole { mstore(0x80, p3) } _sendLogPayload(0x1c, 0x84); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -3157,8 +2970,7 @@ library safeconsole { bytes32 m2; bytes32 m3; bytes32 m4; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) @@ -3172,8 +2984,7 @@ library safeconsole { mstore(0x80, p3) } _sendLogPayload(0x1c, 0x84); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -3188,8 +2999,7 @@ library safeconsole { bytes32 m2; bytes32 m3; bytes32 m4; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) @@ -3203,8 +3013,7 @@ library safeconsole { mstore(0x80, p3) } _sendLogPayload(0x1c, 0x84); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -3221,8 +3030,7 @@ library safeconsole { bytes32 m4; bytes32 m5; bytes32 m6; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } @@ -3246,8 +3054,7 @@ library safeconsole { writeString(0xa0, p3) } _sendLogPayload(0x1c, 0xc4); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -3264,8 +3071,7 @@ library safeconsole { bytes32 m2; bytes32 m3; bytes32 m4; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) @@ -3279,8 +3085,7 @@ library safeconsole { mstore(0x80, p3) } _sendLogPayload(0x1c, 0x84); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -3295,8 +3100,7 @@ library safeconsole { bytes32 m2; bytes32 m3; bytes32 m4; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) @@ -3310,8 +3114,7 @@ library safeconsole { mstore(0x80, p3) } _sendLogPayload(0x1c, 0x84); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -3326,8 +3129,7 @@ library safeconsole { bytes32 m2; bytes32 m3; bytes32 m4; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) @@ -3341,8 +3143,7 @@ library safeconsole { mstore(0x80, p3) } _sendLogPayload(0x1c, 0x84); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -3359,8 +3160,7 @@ library safeconsole { bytes32 m4; bytes32 m5; bytes32 m6; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } @@ -3384,8 +3184,7 @@ library safeconsole { writeString(0xa0, p3) } _sendLogPayload(0x1c, 0xc4); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -3404,8 +3203,7 @@ library safeconsole { bytes32 m4; bytes32 m5; bytes32 m6; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } @@ -3429,8 +3227,7 @@ library safeconsole { writeString(0xa0, p2) } _sendLogPayload(0x1c, 0xc4); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -3449,8 +3246,7 @@ library safeconsole { bytes32 m4; bytes32 m5; bytes32 m6; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } @@ -3474,8 +3270,7 @@ library safeconsole { writeString(0xa0, p2) } _sendLogPayload(0x1c, 0xc4); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -3494,8 +3289,7 @@ library safeconsole { bytes32 m4; bytes32 m5; bytes32 m6; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } @@ -3519,8 +3313,7 @@ library safeconsole { writeString(0xa0, p2) } _sendLogPayload(0x1c, 0xc4); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -3541,8 +3334,7 @@ library safeconsole { bytes32 m6; bytes32 m7; bytes32 m8; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } @@ -3569,8 +3361,7 @@ library safeconsole { writeString(0xe0, p3) } _sendLogPayload(0x1c, 0x104); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -3589,8 +3380,7 @@ library safeconsole { bytes32 m2; bytes32 m3; bytes32 m4; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) @@ -3604,8 +3394,7 @@ library safeconsole { mstore(0x80, p3) } _sendLogPayload(0x1c, 0x84); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -3620,8 +3409,7 @@ library safeconsole { bytes32 m2; bytes32 m3; bytes32 m4; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) @@ -3635,8 +3423,7 @@ library safeconsole { mstore(0x80, p3) } _sendLogPayload(0x1c, 0x84); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -3651,8 +3438,7 @@ library safeconsole { bytes32 m2; bytes32 m3; bytes32 m4; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) @@ -3666,8 +3452,7 @@ library safeconsole { mstore(0x80, p3) } _sendLogPayload(0x1c, 0x84); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -3684,8 +3469,7 @@ library safeconsole { bytes32 m4; bytes32 m5; bytes32 m6; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } @@ -3709,8 +3493,7 @@ library safeconsole { writeString(0xa0, p3) } _sendLogPayload(0x1c, 0xc4); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -3727,8 +3510,7 @@ library safeconsole { bytes32 m2; bytes32 m3; bytes32 m4; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) @@ -3742,8 +3524,7 @@ library safeconsole { mstore(0x80, p3) } _sendLogPayload(0x1c, 0x84); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -3758,8 +3539,7 @@ library safeconsole { bytes32 m2; bytes32 m3; bytes32 m4; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) @@ -3773,8 +3553,7 @@ library safeconsole { mstore(0x80, p3) } _sendLogPayload(0x1c, 0x84); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -3789,8 +3568,7 @@ library safeconsole { bytes32 m2; bytes32 m3; bytes32 m4; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) @@ -3804,8 +3582,7 @@ library safeconsole { mstore(0x80, p3) } _sendLogPayload(0x1c, 0x84); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -3822,8 +3599,7 @@ library safeconsole { bytes32 m4; bytes32 m5; bytes32 m6; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } @@ -3847,8 +3623,7 @@ library safeconsole { writeString(0xa0, p3) } _sendLogPayload(0x1c, 0xc4); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -3865,8 +3640,7 @@ library safeconsole { bytes32 m2; bytes32 m3; bytes32 m4; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) @@ -3880,8 +3654,7 @@ library safeconsole { mstore(0x80, p3) } _sendLogPayload(0x1c, 0x84); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -3896,8 +3669,7 @@ library safeconsole { bytes32 m2; bytes32 m3; bytes32 m4; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) @@ -3911,8 +3683,7 @@ library safeconsole { mstore(0x80, p3) } _sendLogPayload(0x1c, 0x84); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -3927,8 +3698,7 @@ library safeconsole { bytes32 m2; bytes32 m3; bytes32 m4; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) @@ -3942,8 +3712,7 @@ library safeconsole { mstore(0x80, p3) } _sendLogPayload(0x1c, 0x84); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -3960,8 +3729,7 @@ library safeconsole { bytes32 m4; bytes32 m5; bytes32 m6; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } @@ -3985,8 +3753,7 @@ library safeconsole { writeString(0xa0, p3) } _sendLogPayload(0x1c, 0xc4); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -4005,8 +3772,7 @@ library safeconsole { bytes32 m4; bytes32 m5; bytes32 m6; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } @@ -4030,8 +3796,7 @@ library safeconsole { writeString(0xa0, p2) } _sendLogPayload(0x1c, 0xc4); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -4050,8 +3815,7 @@ library safeconsole { bytes32 m4; bytes32 m5; bytes32 m6; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } @@ -4075,8 +3839,7 @@ library safeconsole { writeString(0xa0, p2) } _sendLogPayload(0x1c, 0xc4); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -4095,8 +3858,7 @@ library safeconsole { bytes32 m4; bytes32 m5; bytes32 m6; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } @@ -4120,8 +3882,7 @@ library safeconsole { writeString(0xa0, p2) } _sendLogPayload(0x1c, 0xc4); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -4142,8 +3903,7 @@ library safeconsole { bytes32 m6; bytes32 m7; bytes32 m8; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } @@ -4170,8 +3930,7 @@ library safeconsole { writeString(0xe0, p3) } _sendLogPayload(0x1c, 0x104); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -4190,8 +3949,7 @@ library safeconsole { bytes32 m2; bytes32 m3; bytes32 m4; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) @@ -4205,8 +3963,7 @@ library safeconsole { mstore(0x80, p3) } _sendLogPayload(0x1c, 0x84); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -4221,8 +3978,7 @@ library safeconsole { bytes32 m2; bytes32 m3; bytes32 m4; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) @@ -4236,8 +3992,7 @@ library safeconsole { mstore(0x80, p3) } _sendLogPayload(0x1c, 0x84); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -4252,8 +4007,7 @@ library safeconsole { bytes32 m2; bytes32 m3; bytes32 m4; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) @@ -4267,8 +4021,7 @@ library safeconsole { mstore(0x80, p3) } _sendLogPayload(0x1c, 0x84); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -4285,8 +4038,7 @@ library safeconsole { bytes32 m4; bytes32 m5; bytes32 m6; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } @@ -4310,8 +4062,7 @@ library safeconsole { writeString(0xa0, p3) } _sendLogPayload(0x1c, 0xc4); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -4328,8 +4079,7 @@ library safeconsole { bytes32 m2; bytes32 m3; bytes32 m4; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) @@ -4343,8 +4093,7 @@ library safeconsole { mstore(0x80, p3) } _sendLogPayload(0x1c, 0x84); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -4359,8 +4108,7 @@ library safeconsole { bytes32 m2; bytes32 m3; bytes32 m4; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) @@ -4374,8 +4122,7 @@ library safeconsole { mstore(0x80, p3) } _sendLogPayload(0x1c, 0x84); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -4390,8 +4137,7 @@ library safeconsole { bytes32 m2; bytes32 m3; bytes32 m4; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) @@ -4405,8 +4151,7 @@ library safeconsole { mstore(0x80, p3) } _sendLogPayload(0x1c, 0x84); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -4423,8 +4168,7 @@ library safeconsole { bytes32 m4; bytes32 m5; bytes32 m6; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } @@ -4448,8 +4192,7 @@ library safeconsole { writeString(0xa0, p3) } _sendLogPayload(0x1c, 0xc4); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -4466,8 +4209,7 @@ library safeconsole { bytes32 m2; bytes32 m3; bytes32 m4; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) @@ -4481,8 +4223,7 @@ library safeconsole { mstore(0x80, p3) } _sendLogPayload(0x1c, 0x84); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -4497,8 +4238,7 @@ library safeconsole { bytes32 m2; bytes32 m3; bytes32 m4; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) @@ -4512,8 +4252,7 @@ library safeconsole { mstore(0x80, p3) } _sendLogPayload(0x1c, 0x84); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -4528,8 +4267,7 @@ library safeconsole { bytes32 m2; bytes32 m3; bytes32 m4; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) @@ -4543,8 +4281,7 @@ library safeconsole { mstore(0x80, p3) } _sendLogPayload(0x1c, 0x84); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -4561,8 +4298,7 @@ library safeconsole { bytes32 m4; bytes32 m5; bytes32 m6; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } @@ -4586,8 +4322,7 @@ library safeconsole { writeString(0xa0, p3) } _sendLogPayload(0x1c, 0xc4); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -4606,8 +4341,7 @@ library safeconsole { bytes32 m4; bytes32 m5; bytes32 m6; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } @@ -4631,8 +4365,7 @@ library safeconsole { writeString(0xa0, p2) } _sendLogPayload(0x1c, 0xc4); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -4651,8 +4384,7 @@ library safeconsole { bytes32 m4; bytes32 m5; bytes32 m6; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } @@ -4676,8 +4408,7 @@ library safeconsole { writeString(0xa0, p2) } _sendLogPayload(0x1c, 0xc4); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -4696,8 +4427,7 @@ library safeconsole { bytes32 m4; bytes32 m5; bytes32 m6; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } @@ -4721,8 +4451,7 @@ library safeconsole { writeString(0xa0, p2) } _sendLogPayload(0x1c, 0xc4); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -4743,8 +4472,7 @@ library safeconsole { bytes32 m6; bytes32 m7; bytes32 m8; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } @@ -4771,8 +4499,7 @@ library safeconsole { writeString(0xe0, p3) } _sendLogPayload(0x1c, 0x104); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -4793,8 +4520,7 @@ library safeconsole { bytes32 m4; bytes32 m5; bytes32 m6; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } @@ -4818,8 +4544,7 @@ library safeconsole { writeString(0xa0, p1) } _sendLogPayload(0x1c, 0xc4); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -4838,8 +4563,7 @@ library safeconsole { bytes32 m4; bytes32 m5; bytes32 m6; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } @@ -4863,8 +4587,7 @@ library safeconsole { writeString(0xa0, p1) } _sendLogPayload(0x1c, 0xc4); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -4883,8 +4606,7 @@ library safeconsole { bytes32 m4; bytes32 m5; bytes32 m6; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } @@ -4908,8 +4630,7 @@ library safeconsole { writeString(0xa0, p1) } _sendLogPayload(0x1c, 0xc4); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -4930,8 +4651,7 @@ library safeconsole { bytes32 m6; bytes32 m7; bytes32 m8; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } @@ -4958,8 +4678,7 @@ library safeconsole { writeString(0xe0, p3) } _sendLogPayload(0x1c, 0x104); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -4980,8 +4699,7 @@ library safeconsole { bytes32 m4; bytes32 m5; bytes32 m6; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } @@ -5005,8 +4723,7 @@ library safeconsole { writeString(0xa0, p1) } _sendLogPayload(0x1c, 0xc4); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -5025,8 +4742,7 @@ library safeconsole { bytes32 m4; bytes32 m5; bytes32 m6; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } @@ -5050,8 +4766,7 @@ library safeconsole { writeString(0xa0, p1) } _sendLogPayload(0x1c, 0xc4); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -5070,8 +4785,7 @@ library safeconsole { bytes32 m4; bytes32 m5; bytes32 m6; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } @@ -5095,8 +4809,7 @@ library safeconsole { writeString(0xa0, p1) } _sendLogPayload(0x1c, 0xc4); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -5117,8 +4830,7 @@ library safeconsole { bytes32 m6; bytes32 m7; bytes32 m8; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } @@ -5145,8 +4857,7 @@ library safeconsole { writeString(0xe0, p3) } _sendLogPayload(0x1c, 0x104); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -5167,8 +4878,7 @@ library safeconsole { bytes32 m4; bytes32 m5; bytes32 m6; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } @@ -5192,8 +4902,7 @@ library safeconsole { writeString(0xa0, p1) } _sendLogPayload(0x1c, 0xc4); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -5212,8 +4921,7 @@ library safeconsole { bytes32 m4; bytes32 m5; bytes32 m6; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } @@ -5237,8 +4945,7 @@ library safeconsole { writeString(0xa0, p1) } _sendLogPayload(0x1c, 0xc4); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -5257,8 +4964,7 @@ library safeconsole { bytes32 m4; bytes32 m5; bytes32 m6; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } @@ -5282,8 +4988,7 @@ library safeconsole { writeString(0xa0, p1) } _sendLogPayload(0x1c, 0xc4); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -5304,8 +5009,7 @@ library safeconsole { bytes32 m6; bytes32 m7; bytes32 m8; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } @@ -5332,8 +5036,7 @@ library safeconsole { writeString(0xe0, p3) } _sendLogPayload(0x1c, 0x104); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -5356,8 +5059,7 @@ library safeconsole { bytes32 m6; bytes32 m7; bytes32 m8; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } @@ -5384,8 +5086,7 @@ library safeconsole { writeString(0xe0, p2) } _sendLogPayload(0x1c, 0x104); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -5408,8 +5109,7 @@ library safeconsole { bytes32 m6; bytes32 m7; bytes32 m8; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } @@ -5436,8 +5136,7 @@ library safeconsole { writeString(0xe0, p2) } _sendLogPayload(0x1c, 0x104); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -5460,8 +5159,7 @@ library safeconsole { bytes32 m6; bytes32 m7; bytes32 m8; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } @@ -5488,8 +5186,7 @@ library safeconsole { writeString(0xe0, p2) } _sendLogPayload(0x1c, 0x104); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -5514,8 +5211,7 @@ library safeconsole { bytes32 m8; bytes32 m9; bytes32 m10; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } @@ -5545,8 +5241,7 @@ library safeconsole { writeString(0x120, p3) } _sendLogPayload(0x1c, 0x144); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -5567,8 +5262,7 @@ library safeconsole { bytes32 m2; bytes32 m3; bytes32 m4; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) @@ -5582,8 +5276,7 @@ library safeconsole { mstore(0x80, p3) } _sendLogPayload(0x1c, 0x84); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -5598,8 +5291,7 @@ library safeconsole { bytes32 m2; bytes32 m3; bytes32 m4; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) @@ -5613,8 +5305,7 @@ library safeconsole { mstore(0x80, p3) } _sendLogPayload(0x1c, 0x84); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -5629,8 +5320,7 @@ library safeconsole { bytes32 m2; bytes32 m3; bytes32 m4; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) @@ -5644,8 +5334,7 @@ library safeconsole { mstore(0x80, p3) } _sendLogPayload(0x1c, 0x84); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -5662,8 +5351,7 @@ library safeconsole { bytes32 m4; bytes32 m5; bytes32 m6; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } @@ -5687,8 +5375,7 @@ library safeconsole { writeString(0xa0, p3) } _sendLogPayload(0x1c, 0xc4); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -5705,8 +5392,7 @@ library safeconsole { bytes32 m2; bytes32 m3; bytes32 m4; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) @@ -5720,8 +5406,7 @@ library safeconsole { mstore(0x80, p3) } _sendLogPayload(0x1c, 0x84); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -5736,8 +5421,7 @@ library safeconsole { bytes32 m2; bytes32 m3; bytes32 m4; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) @@ -5751,8 +5435,7 @@ library safeconsole { mstore(0x80, p3) } _sendLogPayload(0x1c, 0x84); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -5767,8 +5450,7 @@ library safeconsole { bytes32 m2; bytes32 m3; bytes32 m4; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) @@ -5782,8 +5464,7 @@ library safeconsole { mstore(0x80, p3) } _sendLogPayload(0x1c, 0x84); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -5800,8 +5481,7 @@ library safeconsole { bytes32 m4; bytes32 m5; bytes32 m6; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } @@ -5825,8 +5505,7 @@ library safeconsole { writeString(0xa0, p3) } _sendLogPayload(0x1c, 0xc4); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -5843,8 +5522,7 @@ library safeconsole { bytes32 m2; bytes32 m3; bytes32 m4; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) @@ -5858,8 +5536,7 @@ library safeconsole { mstore(0x80, p3) } _sendLogPayload(0x1c, 0x84); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -5874,8 +5551,7 @@ library safeconsole { bytes32 m2; bytes32 m3; bytes32 m4; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) @@ -5889,8 +5565,7 @@ library safeconsole { mstore(0x80, p3) } _sendLogPayload(0x1c, 0x84); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -5905,8 +5580,7 @@ library safeconsole { bytes32 m2; bytes32 m3; bytes32 m4; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) @@ -5920,8 +5594,7 @@ library safeconsole { mstore(0x80, p3) } _sendLogPayload(0x1c, 0x84); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -5938,8 +5611,7 @@ library safeconsole { bytes32 m4; bytes32 m5; bytes32 m6; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } @@ -5963,8 +5635,7 @@ library safeconsole { writeString(0xa0, p3) } _sendLogPayload(0x1c, 0xc4); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -5983,8 +5654,7 @@ library safeconsole { bytes32 m4; bytes32 m5; bytes32 m6; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } @@ -6008,8 +5678,7 @@ library safeconsole { writeString(0xa0, p2) } _sendLogPayload(0x1c, 0xc4); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -6028,8 +5697,7 @@ library safeconsole { bytes32 m4; bytes32 m5; bytes32 m6; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } @@ -6053,8 +5721,7 @@ library safeconsole { writeString(0xa0, p2) } _sendLogPayload(0x1c, 0xc4); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -6073,8 +5740,7 @@ library safeconsole { bytes32 m4; bytes32 m5; bytes32 m6; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } @@ -6098,8 +5764,7 @@ library safeconsole { writeString(0xa0, p2) } _sendLogPayload(0x1c, 0xc4); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -6120,8 +5785,7 @@ library safeconsole { bytes32 m6; bytes32 m7; bytes32 m8; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } @@ -6148,8 +5812,7 @@ library safeconsole { writeString(0xe0, p3) } _sendLogPayload(0x1c, 0x104); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -6168,8 +5831,7 @@ library safeconsole { bytes32 m2; bytes32 m3; bytes32 m4; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) @@ -6183,8 +5845,7 @@ library safeconsole { mstore(0x80, p3) } _sendLogPayload(0x1c, 0x84); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -6199,8 +5860,7 @@ library safeconsole { bytes32 m2; bytes32 m3; bytes32 m4; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) @@ -6214,8 +5874,7 @@ library safeconsole { mstore(0x80, p3) } _sendLogPayload(0x1c, 0x84); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -6230,8 +5889,7 @@ library safeconsole { bytes32 m2; bytes32 m3; bytes32 m4; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) @@ -6245,8 +5903,7 @@ library safeconsole { mstore(0x80, p3) } _sendLogPayload(0x1c, 0x84); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -6263,8 +5920,7 @@ library safeconsole { bytes32 m4; bytes32 m5; bytes32 m6; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } @@ -6288,8 +5944,7 @@ library safeconsole { writeString(0xa0, p3) } _sendLogPayload(0x1c, 0xc4); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -6306,8 +5961,7 @@ library safeconsole { bytes32 m2; bytes32 m3; bytes32 m4; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) @@ -6321,8 +5975,7 @@ library safeconsole { mstore(0x80, p3) } _sendLogPayload(0x1c, 0x84); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -6337,8 +5990,7 @@ library safeconsole { bytes32 m2; bytes32 m3; bytes32 m4; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) @@ -6352,8 +6004,7 @@ library safeconsole { mstore(0x80, p3) } _sendLogPayload(0x1c, 0x84); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -6368,8 +6019,7 @@ library safeconsole { bytes32 m2; bytes32 m3; bytes32 m4; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) @@ -6383,8 +6033,7 @@ library safeconsole { mstore(0x80, p3) } _sendLogPayload(0x1c, 0x84); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -6401,8 +6050,7 @@ library safeconsole { bytes32 m4; bytes32 m5; bytes32 m6; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } @@ -6426,8 +6074,7 @@ library safeconsole { writeString(0xa0, p3) } _sendLogPayload(0x1c, 0xc4); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -6444,8 +6091,7 @@ library safeconsole { bytes32 m2; bytes32 m3; bytes32 m4; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) @@ -6459,8 +6105,7 @@ library safeconsole { mstore(0x80, p3) } _sendLogPayload(0x1c, 0x84); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -6475,8 +6120,7 @@ library safeconsole { bytes32 m2; bytes32 m3; bytes32 m4; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) @@ -6490,8 +6134,7 @@ library safeconsole { mstore(0x80, p3) } _sendLogPayload(0x1c, 0x84); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -6506,8 +6149,7 @@ library safeconsole { bytes32 m2; bytes32 m3; bytes32 m4; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) @@ -6521,8 +6163,7 @@ library safeconsole { mstore(0x80, p3) } _sendLogPayload(0x1c, 0x84); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -6539,8 +6180,7 @@ library safeconsole { bytes32 m4; bytes32 m5; bytes32 m6; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } @@ -6564,8 +6204,7 @@ library safeconsole { writeString(0xa0, p3) } _sendLogPayload(0x1c, 0xc4); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -6584,8 +6223,7 @@ library safeconsole { bytes32 m4; bytes32 m5; bytes32 m6; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } @@ -6609,8 +6247,7 @@ library safeconsole { writeString(0xa0, p2) } _sendLogPayload(0x1c, 0xc4); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -6629,8 +6266,7 @@ library safeconsole { bytes32 m4; bytes32 m5; bytes32 m6; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } @@ -6654,8 +6290,7 @@ library safeconsole { writeString(0xa0, p2) } _sendLogPayload(0x1c, 0xc4); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -6674,8 +6309,7 @@ library safeconsole { bytes32 m4; bytes32 m5; bytes32 m6; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } @@ -6699,8 +6333,7 @@ library safeconsole { writeString(0xa0, p2) } _sendLogPayload(0x1c, 0xc4); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -6721,8 +6354,7 @@ library safeconsole { bytes32 m6; bytes32 m7; bytes32 m8; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } @@ -6749,8 +6381,7 @@ library safeconsole { writeString(0xe0, p3) } _sendLogPayload(0x1c, 0x104); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -6769,8 +6400,7 @@ library safeconsole { bytes32 m2; bytes32 m3; bytes32 m4; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) @@ -6784,8 +6414,7 @@ library safeconsole { mstore(0x80, p3) } _sendLogPayload(0x1c, 0x84); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -6800,8 +6429,7 @@ library safeconsole { bytes32 m2; bytes32 m3; bytes32 m4; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) @@ -6815,8 +6443,7 @@ library safeconsole { mstore(0x80, p3) } _sendLogPayload(0x1c, 0x84); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -6831,8 +6458,7 @@ library safeconsole { bytes32 m2; bytes32 m3; bytes32 m4; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) @@ -6846,8 +6472,7 @@ library safeconsole { mstore(0x80, p3) } _sendLogPayload(0x1c, 0x84); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -6864,8 +6489,7 @@ library safeconsole { bytes32 m4; bytes32 m5; bytes32 m6; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } @@ -6889,8 +6513,7 @@ library safeconsole { writeString(0xa0, p3) } _sendLogPayload(0x1c, 0xc4); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -6907,8 +6530,7 @@ library safeconsole { bytes32 m2; bytes32 m3; bytes32 m4; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) @@ -6922,8 +6544,7 @@ library safeconsole { mstore(0x80, p3) } _sendLogPayload(0x1c, 0x84); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -6938,8 +6559,7 @@ library safeconsole { bytes32 m2; bytes32 m3; bytes32 m4; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) @@ -6953,8 +6573,7 @@ library safeconsole { mstore(0x80, p3) } _sendLogPayload(0x1c, 0x84); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -6969,8 +6588,7 @@ library safeconsole { bytes32 m2; bytes32 m3; bytes32 m4; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) @@ -6984,8 +6602,7 @@ library safeconsole { mstore(0x80, p3) } _sendLogPayload(0x1c, 0x84); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -7002,8 +6619,7 @@ library safeconsole { bytes32 m4; bytes32 m5; bytes32 m6; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } @@ -7027,8 +6643,7 @@ library safeconsole { writeString(0xa0, p3) } _sendLogPayload(0x1c, 0xc4); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -7045,8 +6660,7 @@ library safeconsole { bytes32 m2; bytes32 m3; bytes32 m4; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) @@ -7060,8 +6674,7 @@ library safeconsole { mstore(0x80, p3) } _sendLogPayload(0x1c, 0x84); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -7076,8 +6689,7 @@ library safeconsole { bytes32 m2; bytes32 m3; bytes32 m4; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) @@ -7091,8 +6703,7 @@ library safeconsole { mstore(0x80, p3) } _sendLogPayload(0x1c, 0x84); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -7107,8 +6718,7 @@ library safeconsole { bytes32 m2; bytes32 m3; bytes32 m4; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) @@ -7122,8 +6732,7 @@ library safeconsole { mstore(0x80, p3) } _sendLogPayload(0x1c, 0x84); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -7140,8 +6749,7 @@ library safeconsole { bytes32 m4; bytes32 m5; bytes32 m6; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } @@ -7165,8 +6773,7 @@ library safeconsole { writeString(0xa0, p3) } _sendLogPayload(0x1c, 0xc4); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -7185,8 +6792,7 @@ library safeconsole { bytes32 m4; bytes32 m5; bytes32 m6; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } @@ -7210,8 +6816,7 @@ library safeconsole { writeString(0xa0, p2) } _sendLogPayload(0x1c, 0xc4); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -7230,8 +6835,7 @@ library safeconsole { bytes32 m4; bytes32 m5; bytes32 m6; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } @@ -7255,8 +6859,7 @@ library safeconsole { writeString(0xa0, p2) } _sendLogPayload(0x1c, 0xc4); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -7275,8 +6878,7 @@ library safeconsole { bytes32 m4; bytes32 m5; bytes32 m6; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } @@ -7300,8 +6902,7 @@ library safeconsole { writeString(0xa0, p2) } _sendLogPayload(0x1c, 0xc4); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -7322,8 +6923,7 @@ library safeconsole { bytes32 m6; bytes32 m7; bytes32 m8; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } @@ -7350,8 +6950,7 @@ library safeconsole { writeString(0xe0, p3) } _sendLogPayload(0x1c, 0x104); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -7372,8 +6971,7 @@ library safeconsole { bytes32 m4; bytes32 m5; bytes32 m6; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } @@ -7397,8 +6995,7 @@ library safeconsole { writeString(0xa0, p1) } _sendLogPayload(0x1c, 0xc4); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -7417,8 +7014,7 @@ library safeconsole { bytes32 m4; bytes32 m5; bytes32 m6; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } @@ -7442,8 +7038,7 @@ library safeconsole { writeString(0xa0, p1) } _sendLogPayload(0x1c, 0xc4); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -7462,8 +7057,7 @@ library safeconsole { bytes32 m4; bytes32 m5; bytes32 m6; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } @@ -7487,8 +7081,7 @@ library safeconsole { writeString(0xa0, p1) } _sendLogPayload(0x1c, 0xc4); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -7509,8 +7102,7 @@ library safeconsole { bytes32 m6; bytes32 m7; bytes32 m8; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } @@ -7537,8 +7129,7 @@ library safeconsole { writeString(0xe0, p3) } _sendLogPayload(0x1c, 0x104); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -7559,8 +7150,7 @@ library safeconsole { bytes32 m4; bytes32 m5; bytes32 m6; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } @@ -7584,8 +7174,7 @@ library safeconsole { writeString(0xa0, p1) } _sendLogPayload(0x1c, 0xc4); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -7604,8 +7193,7 @@ library safeconsole { bytes32 m4; bytes32 m5; bytes32 m6; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } @@ -7629,8 +7217,7 @@ library safeconsole { writeString(0xa0, p1) } _sendLogPayload(0x1c, 0xc4); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -7649,8 +7236,7 @@ library safeconsole { bytes32 m4; bytes32 m5; bytes32 m6; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } @@ -7674,8 +7260,7 @@ library safeconsole { writeString(0xa0, p1) } _sendLogPayload(0x1c, 0xc4); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -7696,8 +7281,7 @@ library safeconsole { bytes32 m6; bytes32 m7; bytes32 m8; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } @@ -7724,8 +7308,7 @@ library safeconsole { writeString(0xe0, p3) } _sendLogPayload(0x1c, 0x104); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -7746,8 +7329,7 @@ library safeconsole { bytes32 m4; bytes32 m5; bytes32 m6; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } @@ -7771,8 +7353,7 @@ library safeconsole { writeString(0xa0, p1) } _sendLogPayload(0x1c, 0xc4); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -7791,8 +7372,7 @@ library safeconsole { bytes32 m4; bytes32 m5; bytes32 m6; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } @@ -7816,8 +7396,7 @@ library safeconsole { writeString(0xa0, p1) } _sendLogPayload(0x1c, 0xc4); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -7836,8 +7415,7 @@ library safeconsole { bytes32 m4; bytes32 m5; bytes32 m6; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } @@ -7861,8 +7439,7 @@ library safeconsole { writeString(0xa0, p1) } _sendLogPayload(0x1c, 0xc4); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -7883,8 +7460,7 @@ library safeconsole { bytes32 m6; bytes32 m7; bytes32 m8; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } @@ -7911,8 +7487,7 @@ library safeconsole { writeString(0xe0, p3) } _sendLogPayload(0x1c, 0x104); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -7935,8 +7510,7 @@ library safeconsole { bytes32 m6; bytes32 m7; bytes32 m8; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } @@ -7963,8 +7537,7 @@ library safeconsole { writeString(0xe0, p2) } _sendLogPayload(0x1c, 0x104); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -7987,8 +7560,7 @@ library safeconsole { bytes32 m6; bytes32 m7; bytes32 m8; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } @@ -8015,8 +7587,7 @@ library safeconsole { writeString(0xe0, p2) } _sendLogPayload(0x1c, 0x104); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -8039,8 +7610,7 @@ library safeconsole { bytes32 m6; bytes32 m7; bytes32 m8; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } @@ -8067,8 +7637,7 @@ library safeconsole { writeString(0xe0, p2) } _sendLogPayload(0x1c, 0x104); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -8093,8 +7662,7 @@ library safeconsole { bytes32 m8; bytes32 m9; bytes32 m10; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } @@ -8124,8 +7692,7 @@ library safeconsole { writeString(0x120, p3) } _sendLogPayload(0x1c, 0x144); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -8146,8 +7713,7 @@ library safeconsole { bytes32 m2; bytes32 m3; bytes32 m4; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) @@ -8161,8 +7727,7 @@ library safeconsole { mstore(0x80, p3) } _sendLogPayload(0x1c, 0x84); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -8177,8 +7742,7 @@ library safeconsole { bytes32 m2; bytes32 m3; bytes32 m4; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) @@ -8192,8 +7756,7 @@ library safeconsole { mstore(0x80, p3) } _sendLogPayload(0x1c, 0x84); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -8208,8 +7771,7 @@ library safeconsole { bytes32 m2; bytes32 m3; bytes32 m4; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) @@ -8223,8 +7785,7 @@ library safeconsole { mstore(0x80, p3) } _sendLogPayload(0x1c, 0x84); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -8241,8 +7802,7 @@ library safeconsole { bytes32 m4; bytes32 m5; bytes32 m6; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } @@ -8266,8 +7826,7 @@ library safeconsole { writeString(0xa0, p3) } _sendLogPayload(0x1c, 0xc4); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -8284,8 +7843,7 @@ library safeconsole { bytes32 m2; bytes32 m3; bytes32 m4; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) @@ -8299,8 +7857,7 @@ library safeconsole { mstore(0x80, p3) } _sendLogPayload(0x1c, 0x84); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -8315,8 +7872,7 @@ library safeconsole { bytes32 m2; bytes32 m3; bytes32 m4; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) @@ -8330,8 +7886,7 @@ library safeconsole { mstore(0x80, p3) } _sendLogPayload(0x1c, 0x84); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -8346,8 +7901,7 @@ library safeconsole { bytes32 m2; bytes32 m3; bytes32 m4; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) @@ -8361,8 +7915,7 @@ library safeconsole { mstore(0x80, p3) } _sendLogPayload(0x1c, 0x84); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -8379,8 +7932,7 @@ library safeconsole { bytes32 m4; bytes32 m5; bytes32 m6; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } @@ -8404,8 +7956,7 @@ library safeconsole { writeString(0xa0, p3) } _sendLogPayload(0x1c, 0xc4); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -8422,8 +7973,7 @@ library safeconsole { bytes32 m2; bytes32 m3; bytes32 m4; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) @@ -8437,8 +7987,7 @@ library safeconsole { mstore(0x80, p3) } _sendLogPayload(0x1c, 0x84); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -8453,8 +8002,7 @@ library safeconsole { bytes32 m2; bytes32 m3; bytes32 m4; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) @@ -8468,8 +8016,7 @@ library safeconsole { mstore(0x80, p3) } _sendLogPayload(0x1c, 0x84); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -8484,8 +8031,7 @@ library safeconsole { bytes32 m2; bytes32 m3; bytes32 m4; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) @@ -8499,8 +8045,7 @@ library safeconsole { mstore(0x80, p3) } _sendLogPayload(0x1c, 0x84); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -8517,8 +8062,7 @@ library safeconsole { bytes32 m4; bytes32 m5; bytes32 m6; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } @@ -8542,8 +8086,7 @@ library safeconsole { writeString(0xa0, p3) } _sendLogPayload(0x1c, 0xc4); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -8562,8 +8105,7 @@ library safeconsole { bytes32 m4; bytes32 m5; bytes32 m6; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } @@ -8587,8 +8129,7 @@ library safeconsole { writeString(0xa0, p2) } _sendLogPayload(0x1c, 0xc4); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -8607,8 +8148,7 @@ library safeconsole { bytes32 m4; bytes32 m5; bytes32 m6; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } @@ -8632,8 +8172,7 @@ library safeconsole { writeString(0xa0, p2) } _sendLogPayload(0x1c, 0xc4); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -8652,8 +8191,7 @@ library safeconsole { bytes32 m4; bytes32 m5; bytes32 m6; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } @@ -8677,8 +8215,7 @@ library safeconsole { writeString(0xa0, p2) } _sendLogPayload(0x1c, 0xc4); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -8699,8 +8236,7 @@ library safeconsole { bytes32 m6; bytes32 m7; bytes32 m8; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } @@ -8727,8 +8263,7 @@ library safeconsole { writeString(0xe0, p3) } _sendLogPayload(0x1c, 0x104); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -8747,8 +8282,7 @@ library safeconsole { bytes32 m2; bytes32 m3; bytes32 m4; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) @@ -8762,8 +8296,7 @@ library safeconsole { mstore(0x80, p3) } _sendLogPayload(0x1c, 0x84); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -8778,8 +8311,7 @@ library safeconsole { bytes32 m2; bytes32 m3; bytes32 m4; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) @@ -8793,8 +8325,7 @@ library safeconsole { mstore(0x80, p3) } _sendLogPayload(0x1c, 0x84); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -8809,8 +8340,7 @@ library safeconsole { bytes32 m2; bytes32 m3; bytes32 m4; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) @@ -8824,8 +8354,7 @@ library safeconsole { mstore(0x80, p3) } _sendLogPayload(0x1c, 0x84); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -8842,8 +8371,7 @@ library safeconsole { bytes32 m4; bytes32 m5; bytes32 m6; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } @@ -8867,8 +8395,7 @@ library safeconsole { writeString(0xa0, p3) } _sendLogPayload(0x1c, 0xc4); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -8885,8 +8412,7 @@ library safeconsole { bytes32 m2; bytes32 m3; bytes32 m4; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) @@ -8900,8 +8426,7 @@ library safeconsole { mstore(0x80, p3) } _sendLogPayload(0x1c, 0x84); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -8916,8 +8441,7 @@ library safeconsole { bytes32 m2; bytes32 m3; bytes32 m4; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) @@ -8931,8 +8455,7 @@ library safeconsole { mstore(0x80, p3) } _sendLogPayload(0x1c, 0x84); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -8947,8 +8470,7 @@ library safeconsole { bytes32 m2; bytes32 m3; bytes32 m4; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) @@ -8962,8 +8484,7 @@ library safeconsole { mstore(0x80, p3) } _sendLogPayload(0x1c, 0x84); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -8980,8 +8501,7 @@ library safeconsole { bytes32 m4; bytes32 m5; bytes32 m6; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } @@ -9005,8 +8525,7 @@ library safeconsole { writeString(0xa0, p3) } _sendLogPayload(0x1c, 0xc4); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -9023,8 +8542,7 @@ library safeconsole { bytes32 m2; bytes32 m3; bytes32 m4; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) @@ -9038,8 +8556,7 @@ library safeconsole { mstore(0x80, p3) } _sendLogPayload(0x1c, 0x84); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -9054,8 +8571,7 @@ library safeconsole { bytes32 m2; bytes32 m3; bytes32 m4; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) @@ -9069,8 +8585,7 @@ library safeconsole { mstore(0x80, p3) } _sendLogPayload(0x1c, 0x84); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -9085,8 +8600,7 @@ library safeconsole { bytes32 m2; bytes32 m3; bytes32 m4; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) @@ -9100,8 +8614,7 @@ library safeconsole { mstore(0x80, p3) } _sendLogPayload(0x1c, 0x84); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -9118,8 +8631,7 @@ library safeconsole { bytes32 m4; bytes32 m5; bytes32 m6; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } @@ -9143,8 +8655,7 @@ library safeconsole { writeString(0xa0, p3) } _sendLogPayload(0x1c, 0xc4); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -9163,8 +8674,7 @@ library safeconsole { bytes32 m4; bytes32 m5; bytes32 m6; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } @@ -9188,8 +8698,7 @@ library safeconsole { writeString(0xa0, p2) } _sendLogPayload(0x1c, 0xc4); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -9208,8 +8717,7 @@ library safeconsole { bytes32 m4; bytes32 m5; bytes32 m6; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } @@ -9233,8 +8741,7 @@ library safeconsole { writeString(0xa0, p2) } _sendLogPayload(0x1c, 0xc4); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -9253,8 +8760,7 @@ library safeconsole { bytes32 m4; bytes32 m5; bytes32 m6; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } @@ -9278,8 +8784,7 @@ library safeconsole { writeString(0xa0, p2) } _sendLogPayload(0x1c, 0xc4); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -9300,8 +8805,7 @@ library safeconsole { bytes32 m6; bytes32 m7; bytes32 m8; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } @@ -9328,8 +8832,7 @@ library safeconsole { writeString(0xe0, p3) } _sendLogPayload(0x1c, 0x104); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -9348,8 +8851,7 @@ library safeconsole { bytes32 m2; bytes32 m3; bytes32 m4; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) @@ -9363,8 +8865,7 @@ library safeconsole { mstore(0x80, p3) } _sendLogPayload(0x1c, 0x84); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -9379,8 +8880,7 @@ library safeconsole { bytes32 m2; bytes32 m3; bytes32 m4; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) @@ -9394,8 +8894,7 @@ library safeconsole { mstore(0x80, p3) } _sendLogPayload(0x1c, 0x84); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -9410,8 +8909,7 @@ library safeconsole { bytes32 m2; bytes32 m3; bytes32 m4; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) @@ -9425,8 +8923,7 @@ library safeconsole { mstore(0x80, p3) } _sendLogPayload(0x1c, 0x84); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -9443,8 +8940,7 @@ library safeconsole { bytes32 m4; bytes32 m5; bytes32 m6; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } @@ -9468,8 +8964,7 @@ library safeconsole { writeString(0xa0, p3) } _sendLogPayload(0x1c, 0xc4); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -9486,8 +8981,7 @@ library safeconsole { bytes32 m2; bytes32 m3; bytes32 m4; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) @@ -9501,8 +8995,7 @@ library safeconsole { mstore(0x80, p3) } _sendLogPayload(0x1c, 0x84); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -9517,8 +9010,7 @@ library safeconsole { bytes32 m2; bytes32 m3; bytes32 m4; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) @@ -9532,8 +9024,7 @@ library safeconsole { mstore(0x80, p3) } _sendLogPayload(0x1c, 0x84); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -9548,8 +9039,7 @@ library safeconsole { bytes32 m2; bytes32 m3; bytes32 m4; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) @@ -9563,8 +9053,7 @@ library safeconsole { mstore(0x80, p3) } _sendLogPayload(0x1c, 0x84); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -9581,8 +9070,7 @@ library safeconsole { bytes32 m4; bytes32 m5; bytes32 m6; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } @@ -9606,8 +9094,7 @@ library safeconsole { writeString(0xa0, p3) } _sendLogPayload(0x1c, 0xc4); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -9624,8 +9111,7 @@ library safeconsole { bytes32 m2; bytes32 m3; bytes32 m4; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) @@ -9639,8 +9125,7 @@ library safeconsole { mstore(0x80, p3) } _sendLogPayload(0x1c, 0x84); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -9655,8 +9140,7 @@ library safeconsole { bytes32 m2; bytes32 m3; bytes32 m4; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) @@ -9670,8 +9154,7 @@ library safeconsole { mstore(0x80, p3) } _sendLogPayload(0x1c, 0x84); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -9686,8 +9169,7 @@ library safeconsole { bytes32 m2; bytes32 m3; bytes32 m4; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) @@ -9701,8 +9183,7 @@ library safeconsole { mstore(0x80, p3) } _sendLogPayload(0x1c, 0x84); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -9719,8 +9200,7 @@ library safeconsole { bytes32 m4; bytes32 m5; bytes32 m6; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } @@ -9744,8 +9224,7 @@ library safeconsole { writeString(0xa0, p3) } _sendLogPayload(0x1c, 0xc4); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -9764,8 +9243,7 @@ library safeconsole { bytes32 m4; bytes32 m5; bytes32 m6; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } @@ -9789,8 +9267,7 @@ library safeconsole { writeString(0xa0, p2) } _sendLogPayload(0x1c, 0xc4); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -9809,8 +9286,7 @@ library safeconsole { bytes32 m4; bytes32 m5; bytes32 m6; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } @@ -9834,8 +9310,7 @@ library safeconsole { writeString(0xa0, p2) } _sendLogPayload(0x1c, 0xc4); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -9854,8 +9329,7 @@ library safeconsole { bytes32 m4; bytes32 m5; bytes32 m6; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } @@ -9879,8 +9353,7 @@ library safeconsole { writeString(0xa0, p2) } _sendLogPayload(0x1c, 0xc4); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -9901,8 +9374,7 @@ library safeconsole { bytes32 m6; bytes32 m7; bytes32 m8; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } @@ -9929,8 +9401,7 @@ library safeconsole { writeString(0xe0, p3) } _sendLogPayload(0x1c, 0x104); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -9951,8 +9422,7 @@ library safeconsole { bytes32 m4; bytes32 m5; bytes32 m6; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } @@ -9976,8 +9446,7 @@ library safeconsole { writeString(0xa0, p1) } _sendLogPayload(0x1c, 0xc4); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -9996,8 +9465,7 @@ library safeconsole { bytes32 m4; bytes32 m5; bytes32 m6; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } @@ -10021,8 +9489,7 @@ library safeconsole { writeString(0xa0, p1) } _sendLogPayload(0x1c, 0xc4); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -10041,8 +9508,7 @@ library safeconsole { bytes32 m4; bytes32 m5; bytes32 m6; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } @@ -10066,8 +9532,7 @@ library safeconsole { writeString(0xa0, p1) } _sendLogPayload(0x1c, 0xc4); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -10088,8 +9553,7 @@ library safeconsole { bytes32 m6; bytes32 m7; bytes32 m8; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } @@ -10116,8 +9580,7 @@ library safeconsole { writeString(0xe0, p3) } _sendLogPayload(0x1c, 0x104); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -10138,8 +9601,7 @@ library safeconsole { bytes32 m4; bytes32 m5; bytes32 m6; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } @@ -10163,8 +9625,7 @@ library safeconsole { writeString(0xa0, p1) } _sendLogPayload(0x1c, 0xc4); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -10183,8 +9644,7 @@ library safeconsole { bytes32 m4; bytes32 m5; bytes32 m6; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } @@ -10208,8 +9668,7 @@ library safeconsole { writeString(0xa0, p1) } _sendLogPayload(0x1c, 0xc4); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -10228,8 +9687,7 @@ library safeconsole { bytes32 m4; bytes32 m5; bytes32 m6; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } @@ -10253,8 +9711,7 @@ library safeconsole { writeString(0xa0, p1) } _sendLogPayload(0x1c, 0xc4); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -10275,8 +9732,7 @@ library safeconsole { bytes32 m6; bytes32 m7; bytes32 m8; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } @@ -10303,8 +9759,7 @@ library safeconsole { writeString(0xe0, p3) } _sendLogPayload(0x1c, 0x104); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -10325,8 +9780,7 @@ library safeconsole { bytes32 m4; bytes32 m5; bytes32 m6; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } @@ -10350,8 +9804,7 @@ library safeconsole { writeString(0xa0, p1) } _sendLogPayload(0x1c, 0xc4); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -10370,8 +9823,7 @@ library safeconsole { bytes32 m4; bytes32 m5; bytes32 m6; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } @@ -10395,8 +9847,7 @@ library safeconsole { writeString(0xa0, p1) } _sendLogPayload(0x1c, 0xc4); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -10415,8 +9866,7 @@ library safeconsole { bytes32 m4; bytes32 m5; bytes32 m6; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } @@ -10440,8 +9890,7 @@ library safeconsole { writeString(0xa0, p1) } _sendLogPayload(0x1c, 0xc4); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -10462,8 +9911,7 @@ library safeconsole { bytes32 m6; bytes32 m7; bytes32 m8; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } @@ -10490,8 +9938,7 @@ library safeconsole { writeString(0xe0, p3) } _sendLogPayload(0x1c, 0x104); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -10514,8 +9961,7 @@ library safeconsole { bytes32 m6; bytes32 m7; bytes32 m8; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } @@ -10542,8 +9988,7 @@ library safeconsole { writeString(0xe0, p2) } _sendLogPayload(0x1c, 0x104); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -10566,8 +10011,7 @@ library safeconsole { bytes32 m6; bytes32 m7; bytes32 m8; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } @@ -10594,8 +10038,7 @@ library safeconsole { writeString(0xe0, p2) } _sendLogPayload(0x1c, 0x104); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -10618,8 +10061,7 @@ library safeconsole { bytes32 m6; bytes32 m7; bytes32 m8; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } @@ -10646,8 +10088,7 @@ library safeconsole { writeString(0xe0, p2) } _sendLogPayload(0x1c, 0x104); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -10672,8 +10113,7 @@ library safeconsole { bytes32 m8; bytes32 m9; bytes32 m10; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } @@ -10703,8 +10143,7 @@ library safeconsole { writeString(0x120, p3) } _sendLogPayload(0x1c, 0x144); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -10727,8 +10166,7 @@ library safeconsole { bytes32 m4; bytes32 m5; bytes32 m6; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } @@ -10752,8 +10190,7 @@ library safeconsole { writeString(0xa0, p0) } _sendLogPayload(0x1c, 0xc4); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -10772,8 +10209,7 @@ library safeconsole { bytes32 m4; bytes32 m5; bytes32 m6; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } @@ -10797,8 +10233,7 @@ library safeconsole { writeString(0xa0, p0) } _sendLogPayload(0x1c, 0xc4); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -10817,8 +10252,7 @@ library safeconsole { bytes32 m4; bytes32 m5; bytes32 m6; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } @@ -10842,8 +10276,7 @@ library safeconsole { writeString(0xa0, p0) } _sendLogPayload(0x1c, 0xc4); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -10864,8 +10297,7 @@ library safeconsole { bytes32 m6; bytes32 m7; bytes32 m8; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } @@ -10892,8 +10324,7 @@ library safeconsole { writeString(0xe0, p3) } _sendLogPayload(0x1c, 0x104); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -10914,8 +10345,7 @@ library safeconsole { bytes32 m4; bytes32 m5; bytes32 m6; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } @@ -10939,8 +10369,7 @@ library safeconsole { writeString(0xa0, p0) } _sendLogPayload(0x1c, 0xc4); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -10959,8 +10388,7 @@ library safeconsole { bytes32 m4; bytes32 m5; bytes32 m6; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } @@ -10984,8 +10412,7 @@ library safeconsole { writeString(0xa0, p0) } _sendLogPayload(0x1c, 0xc4); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -11004,8 +10431,7 @@ library safeconsole { bytes32 m4; bytes32 m5; bytes32 m6; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } @@ -11029,8 +10455,7 @@ library safeconsole { writeString(0xa0, p0) } _sendLogPayload(0x1c, 0xc4); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -11051,8 +10476,7 @@ library safeconsole { bytes32 m6; bytes32 m7; bytes32 m8; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } @@ -11079,8 +10503,7 @@ library safeconsole { writeString(0xe0, p3) } _sendLogPayload(0x1c, 0x104); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -11101,8 +10524,7 @@ library safeconsole { bytes32 m4; bytes32 m5; bytes32 m6; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } @@ -11126,8 +10548,7 @@ library safeconsole { writeString(0xa0, p0) } _sendLogPayload(0x1c, 0xc4); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -11146,8 +10567,7 @@ library safeconsole { bytes32 m4; bytes32 m5; bytes32 m6; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } @@ -11171,8 +10591,7 @@ library safeconsole { writeString(0xa0, p0) } _sendLogPayload(0x1c, 0xc4); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -11191,8 +10610,7 @@ library safeconsole { bytes32 m4; bytes32 m5; bytes32 m6; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } @@ -11216,8 +10634,7 @@ library safeconsole { writeString(0xa0, p0) } _sendLogPayload(0x1c, 0xc4); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -11238,8 +10655,7 @@ library safeconsole { bytes32 m6; bytes32 m7; bytes32 m8; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } @@ -11266,8 +10682,7 @@ library safeconsole { writeString(0xe0, p3) } _sendLogPayload(0x1c, 0x104); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -11290,8 +10705,7 @@ library safeconsole { bytes32 m6; bytes32 m7; bytes32 m8; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } @@ -11318,8 +10732,7 @@ library safeconsole { writeString(0xe0, p2) } _sendLogPayload(0x1c, 0x104); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -11342,8 +10755,7 @@ library safeconsole { bytes32 m6; bytes32 m7; bytes32 m8; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } @@ -11370,8 +10782,7 @@ library safeconsole { writeString(0xe0, p2) } _sendLogPayload(0x1c, 0x104); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -11394,8 +10805,7 @@ library safeconsole { bytes32 m6; bytes32 m7; bytes32 m8; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } @@ -11422,8 +10832,7 @@ library safeconsole { writeString(0xe0, p2) } _sendLogPayload(0x1c, 0x104); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -11448,8 +10857,7 @@ library safeconsole { bytes32 m8; bytes32 m9; bytes32 m10; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } @@ -11479,8 +10887,7 @@ library safeconsole { writeString(0x120, p3) } _sendLogPayload(0x1c, 0x144); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -11503,8 +10910,7 @@ library safeconsole { bytes32 m4; bytes32 m5; bytes32 m6; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } @@ -11528,8 +10934,7 @@ library safeconsole { writeString(0xa0, p0) } _sendLogPayload(0x1c, 0xc4); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -11548,8 +10953,7 @@ library safeconsole { bytes32 m4; bytes32 m5; bytes32 m6; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } @@ -11573,8 +10977,7 @@ library safeconsole { writeString(0xa0, p0) } _sendLogPayload(0x1c, 0xc4); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -11593,8 +10996,7 @@ library safeconsole { bytes32 m4; bytes32 m5; bytes32 m6; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } @@ -11618,8 +11020,7 @@ library safeconsole { writeString(0xa0, p0) } _sendLogPayload(0x1c, 0xc4); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -11640,8 +11041,7 @@ library safeconsole { bytes32 m6; bytes32 m7; bytes32 m8; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } @@ -11668,8 +11068,7 @@ library safeconsole { writeString(0xe0, p3) } _sendLogPayload(0x1c, 0x104); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -11690,8 +11089,7 @@ library safeconsole { bytes32 m4; bytes32 m5; bytes32 m6; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } @@ -11715,8 +11113,7 @@ library safeconsole { writeString(0xa0, p0) } _sendLogPayload(0x1c, 0xc4); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -11735,8 +11132,7 @@ library safeconsole { bytes32 m4; bytes32 m5; bytes32 m6; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } @@ -11760,8 +11156,7 @@ library safeconsole { writeString(0xa0, p0) } _sendLogPayload(0x1c, 0xc4); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -11780,8 +11175,7 @@ library safeconsole { bytes32 m4; bytes32 m5; bytes32 m6; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } @@ -11805,8 +11199,7 @@ library safeconsole { writeString(0xa0, p0) } _sendLogPayload(0x1c, 0xc4); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -11827,8 +11220,7 @@ library safeconsole { bytes32 m6; bytes32 m7; bytes32 m8; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } @@ -11855,8 +11247,7 @@ library safeconsole { writeString(0xe0, p3) } _sendLogPayload(0x1c, 0x104); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -11877,8 +11268,7 @@ library safeconsole { bytes32 m4; bytes32 m5; bytes32 m6; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } @@ -11902,8 +11292,7 @@ library safeconsole { writeString(0xa0, p0) } _sendLogPayload(0x1c, 0xc4); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -11922,8 +11311,7 @@ library safeconsole { bytes32 m4; bytes32 m5; bytes32 m6; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } @@ -11947,8 +11335,7 @@ library safeconsole { writeString(0xa0, p0) } _sendLogPayload(0x1c, 0xc4); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -11967,8 +11354,7 @@ library safeconsole { bytes32 m4; bytes32 m5; bytes32 m6; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } @@ -11992,8 +11378,7 @@ library safeconsole { writeString(0xa0, p0) } _sendLogPayload(0x1c, 0xc4); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -12014,8 +11399,7 @@ library safeconsole { bytes32 m6; bytes32 m7; bytes32 m8; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } @@ -12042,8 +11426,7 @@ library safeconsole { writeString(0xe0, p3) } _sendLogPayload(0x1c, 0x104); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -12066,8 +11449,7 @@ library safeconsole { bytes32 m6; bytes32 m7; bytes32 m8; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } @@ -12094,8 +11476,7 @@ library safeconsole { writeString(0xe0, p2) } _sendLogPayload(0x1c, 0x104); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -12118,8 +11499,7 @@ library safeconsole { bytes32 m6; bytes32 m7; bytes32 m8; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } @@ -12146,8 +11526,7 @@ library safeconsole { writeString(0xe0, p2) } _sendLogPayload(0x1c, 0x104); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -12170,8 +11549,7 @@ library safeconsole { bytes32 m6; bytes32 m7; bytes32 m8; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } @@ -12198,8 +11576,7 @@ library safeconsole { writeString(0xe0, p2) } _sendLogPayload(0x1c, 0x104); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -12224,8 +11601,7 @@ library safeconsole { bytes32 m8; bytes32 m9; bytes32 m10; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } @@ -12255,8 +11631,7 @@ library safeconsole { writeString(0x120, p3) } _sendLogPayload(0x1c, 0x144); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -12279,8 +11654,7 @@ library safeconsole { bytes32 m4; bytes32 m5; bytes32 m6; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } @@ -12304,8 +11678,7 @@ library safeconsole { writeString(0xa0, p0) } _sendLogPayload(0x1c, 0xc4); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -12324,8 +11697,7 @@ library safeconsole { bytes32 m4; bytes32 m5; bytes32 m6; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } @@ -12349,8 +11721,7 @@ library safeconsole { writeString(0xa0, p0) } _sendLogPayload(0x1c, 0xc4); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -12369,8 +11740,7 @@ library safeconsole { bytes32 m4; bytes32 m5; bytes32 m6; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } @@ -12394,8 +11764,7 @@ library safeconsole { writeString(0xa0, p0) } _sendLogPayload(0x1c, 0xc4); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -12416,8 +11785,7 @@ library safeconsole { bytes32 m6; bytes32 m7; bytes32 m8; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } @@ -12444,8 +11812,7 @@ library safeconsole { writeString(0xe0, p3) } _sendLogPayload(0x1c, 0x104); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -12466,8 +11833,7 @@ library safeconsole { bytes32 m4; bytes32 m5; bytes32 m6; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } @@ -12491,8 +11857,7 @@ library safeconsole { writeString(0xa0, p0) } _sendLogPayload(0x1c, 0xc4); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -12511,8 +11876,7 @@ library safeconsole { bytes32 m4; bytes32 m5; bytes32 m6; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } @@ -12536,8 +11900,7 @@ library safeconsole { writeString(0xa0, p0) } _sendLogPayload(0x1c, 0xc4); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -12556,8 +11919,7 @@ library safeconsole { bytes32 m4; bytes32 m5; bytes32 m6; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } @@ -12581,8 +11943,7 @@ library safeconsole { writeString(0xa0, p0) } _sendLogPayload(0x1c, 0xc4); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -12603,8 +11964,7 @@ library safeconsole { bytes32 m6; bytes32 m7; bytes32 m8; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } @@ -12631,8 +11991,7 @@ library safeconsole { writeString(0xe0, p3) } _sendLogPayload(0x1c, 0x104); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -12653,8 +12012,7 @@ library safeconsole { bytes32 m4; bytes32 m5; bytes32 m6; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } @@ -12678,8 +12036,7 @@ library safeconsole { writeString(0xa0, p0) } _sendLogPayload(0x1c, 0xc4); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -12698,8 +12055,7 @@ library safeconsole { bytes32 m4; bytes32 m5; bytes32 m6; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } @@ -12723,8 +12079,7 @@ library safeconsole { writeString(0xa0, p0) } _sendLogPayload(0x1c, 0xc4); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -12743,8 +12098,7 @@ library safeconsole { bytes32 m4; bytes32 m5; bytes32 m6; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } @@ -12768,8 +12122,7 @@ library safeconsole { writeString(0xa0, p0) } _sendLogPayload(0x1c, 0xc4); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -12790,8 +12143,7 @@ library safeconsole { bytes32 m6; bytes32 m7; bytes32 m8; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } @@ -12818,8 +12170,7 @@ library safeconsole { writeString(0xe0, p3) } _sendLogPayload(0x1c, 0x104); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -12842,8 +12193,7 @@ library safeconsole { bytes32 m6; bytes32 m7; bytes32 m8; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } @@ -12870,8 +12220,7 @@ library safeconsole { writeString(0xe0, p2) } _sendLogPayload(0x1c, 0x104); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -12894,8 +12243,7 @@ library safeconsole { bytes32 m6; bytes32 m7; bytes32 m8; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } @@ -12922,8 +12270,7 @@ library safeconsole { writeString(0xe0, p2) } _sendLogPayload(0x1c, 0x104); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -12946,8 +12293,7 @@ library safeconsole { bytes32 m6; bytes32 m7; bytes32 m8; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } @@ -12974,8 +12320,7 @@ library safeconsole { writeString(0xe0, p2) } _sendLogPayload(0x1c, 0x104); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -13000,8 +12345,7 @@ library safeconsole { bytes32 m8; bytes32 m9; bytes32 m10; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } @@ -13031,8 +12375,7 @@ library safeconsole { writeString(0x120, p3) } _sendLogPayload(0x1c, 0x144); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -13057,8 +12400,7 @@ library safeconsole { bytes32 m6; bytes32 m7; bytes32 m8; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } @@ -13085,8 +12427,7 @@ library safeconsole { writeString(0xe0, p1) } _sendLogPayload(0x1c, 0x104); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -13109,8 +12450,7 @@ library safeconsole { bytes32 m6; bytes32 m7; bytes32 m8; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } @@ -13137,8 +12477,7 @@ library safeconsole { writeString(0xe0, p1) } _sendLogPayload(0x1c, 0x104); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -13161,8 +12500,7 @@ library safeconsole { bytes32 m6; bytes32 m7; bytes32 m8; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } @@ -13189,8 +12527,7 @@ library safeconsole { writeString(0xe0, p1) } _sendLogPayload(0x1c, 0x104); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -13215,8 +12552,7 @@ library safeconsole { bytes32 m8; bytes32 m9; bytes32 m10; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } @@ -13246,8 +12582,7 @@ library safeconsole { writeString(0x120, p3) } _sendLogPayload(0x1c, 0x144); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -13272,8 +12607,7 @@ library safeconsole { bytes32 m6; bytes32 m7; bytes32 m8; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } @@ -13300,8 +12634,7 @@ library safeconsole { writeString(0xe0, p1) } _sendLogPayload(0x1c, 0x104); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -13324,8 +12657,7 @@ library safeconsole { bytes32 m6; bytes32 m7; bytes32 m8; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } @@ -13352,8 +12684,7 @@ library safeconsole { writeString(0xe0, p1) } _sendLogPayload(0x1c, 0x104); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -13376,8 +12707,7 @@ library safeconsole { bytes32 m6; bytes32 m7; bytes32 m8; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } @@ -13404,8 +12734,7 @@ library safeconsole { writeString(0xe0, p1) } _sendLogPayload(0x1c, 0x104); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -13430,8 +12759,7 @@ library safeconsole { bytes32 m8; bytes32 m9; bytes32 m10; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } @@ -13461,8 +12789,7 @@ library safeconsole { writeString(0x120, p3) } _sendLogPayload(0x1c, 0x144); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -13487,8 +12814,7 @@ library safeconsole { bytes32 m6; bytes32 m7; bytes32 m8; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } @@ -13515,8 +12841,7 @@ library safeconsole { writeString(0xe0, p1) } _sendLogPayload(0x1c, 0x104); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -13539,8 +12864,7 @@ library safeconsole { bytes32 m6; bytes32 m7; bytes32 m8; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } @@ -13567,8 +12891,7 @@ library safeconsole { writeString(0xe0, p1) } _sendLogPayload(0x1c, 0x104); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -13591,8 +12914,7 @@ library safeconsole { bytes32 m6; bytes32 m7; bytes32 m8; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } @@ -13619,8 +12941,7 @@ library safeconsole { writeString(0xe0, p1) } _sendLogPayload(0x1c, 0x104); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -13645,8 +12966,7 @@ library safeconsole { bytes32 m8; bytes32 m9; bytes32 m10; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } @@ -13676,8 +12996,7 @@ library safeconsole { writeString(0x120, p3) } _sendLogPayload(0x1c, 0x144); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -13704,8 +13023,7 @@ library safeconsole { bytes32 m8; bytes32 m9; bytes32 m10; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } @@ -13735,8 +13053,7 @@ library safeconsole { writeString(0x120, p2) } _sendLogPayload(0x1c, 0x144); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -13763,8 +13080,7 @@ library safeconsole { bytes32 m8; bytes32 m9; bytes32 m10; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } @@ -13794,8 +13110,7 @@ library safeconsole { writeString(0x120, p2) } _sendLogPayload(0x1c, 0x144); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -13822,8 +13137,7 @@ library safeconsole { bytes32 m8; bytes32 m9; bytes32 m10; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } @@ -13853,8 +13167,7 @@ library safeconsole { writeString(0x120, p2) } _sendLogPayload(0x1c, 0x144); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) @@ -13883,8 +13196,7 @@ library safeconsole { bytes32 m10; bytes32 m11; bytes32 m12; - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } @@ -13917,8 +13229,7 @@ library safeconsole { writeString(0x160, p3) } _sendLogPayload(0x1c, 0x184); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) diff --git a/dependencies/forge-std-1.11.0/test/CommonBase.t.sol b/dependencies/forge-std-1.16.2/test/CommonBase.t.sol similarity index 94% rename from dependencies/forge-std-1.11.0/test/CommonBase.t.sol rename to dependencies/forge-std-1.16.2/test/CommonBase.t.sol index 4a6eb34..28c91a9 100644 --- a/dependencies/forge-std-1.11.0/test/CommonBase.t.sol +++ b/dependencies/forge-std-1.16.2/test/CommonBase.t.sol @@ -1,5 +1,5 @@ -// SPDX-License-Identifier: MIT -pragma solidity >=0.7.0 <0.9.0; +// SPDX-License-Identifier: MIT OR Apache-2.0 +pragma solidity >=0.8.13 <0.9.0; import {CommonBase} from "../src/Base.sol"; import {StdConstants} from "../src/StdConstants.sol"; diff --git a/dependencies/forge-std-1.11.0/test/Config.t.sol b/dependencies/forge-std-1.16.2/test/Config.t.sol similarity index 92% rename from dependencies/forge-std-1.11.0/test/Config.t.sol rename to dependencies/forge-std-1.16.2/test/Config.t.sol index 8e2342c..00af755 100644 --- a/dependencies/forge-std-1.11.0/test/Config.t.sol +++ b/dependencies/forge-std-1.16.2/test/Config.t.sol @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: MIT +// SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity ^0.8.13; import {Test} from "../src/Test.sol"; @@ -7,7 +7,7 @@ import {StdConfig} from "../src/StdConfig.sol"; contract ConfigTest is Test, Config { function setUp() public { - vm.setEnv("MAINNET_RPC", "https://eth.llamarpc.com"); + vm.setEnv("MAINNET_RPC", "https://ethereum.reth.rs/rpc"); vm.setEnv("WETH_MAINNET", "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2"); vm.setEnv("OPTIMISM_RPC", "https://mainnet.optimism.io"); vm.setEnv("WETH_OPTIMISM", "0x4200000000000000000000000000000000000006"); @@ -20,7 +20,7 @@ contract ConfigTest is Test, Config { // -- MAINNET -------------------------------------------------------------- // Read and assert RPC URL for Mainnet (chain ID 1) - assertEq(config.getRpcUrl(1), "https://eth.llamarpc.com"); + assertEq(config.getRpcUrl(1), "https://ethereum.reth.rs/rpc"); // Read and assert boolean values assertTrue(config.get(1, "is_live").toBool()); @@ -125,6 +125,35 @@ contract ConfigTest is Test, Config { assertEq(vm.getChainId(), 10); } + function test_configExists() public { + _loadConfig("./test/fixtures/config.toml", false); + + string[] memory keys = new string[](7); + keys[0] = "is_live"; + keys[1] = "weth"; + keys[2] = "word"; + keys[3] = "number"; + keys[4] = "signed_number"; + keys[5] = "b"; + keys[6] = "str"; + + // Read and assert RPC URL for Mainnet (chain ID 1) + assertEq(config.getRpcUrl(1), "https://ethereum.reth.rs/rpc"); + + for (uint256 i = 0; i < keys.length; ++i) { + assertTrue(config.exists(1, keys[i])); + assertFalse(config.exists(1, string.concat(keys[i], "_"))); + } + + // Assert RPC URL for Optimism (chain ID 10) + assertEq(config.getRpcUrl(10), "https://mainnet.optimism.io"); + + for (uint256 i = 0; i < keys.length; ++i) { + assertTrue(config.exists(10, keys[i])); + assertFalse(config.exists(10, string.concat(keys[i], "_"))); + } + } + function test_writeConfig() public { // Create a temporary copy of the config file to avoid modifying the original. string memory originalConfig = "./test/fixtures/config.toml"; @@ -301,7 +330,7 @@ contract ConfigTest is Test, Config { invalidChainConfig, string.concat( "[mainnet]\n", - "endpoint_url = \"https://eth.llamarpc.com\"\n", + "endpoint_url = \"https://ethereum.reth.rs/rpc\"\n", "\n", "[mainnet.uint]\n", "valid_number = 123\n", @@ -338,7 +367,7 @@ contract ConfigTest is Test, Config { badParseConfig, string.concat( "[mainnet]\n", - "endpoint_url = \"https://eth.llamarpc.com\"\n", + "endpoint_url = \"https://ethereum.reth.rs/rpc\"\n", "\n", "[mainnet.uint]\n", "bad_value = \"not_a_number\"\n" diff --git a/dependencies/forge-std-1.11.0/test/LibVariable.t.sol b/dependencies/forge-std-1.16.2/test/LibVariable.t.sol similarity index 96% rename from dependencies/forge-std-1.11.0/test/LibVariable.t.sol rename to dependencies/forge-std-1.16.2/test/LibVariable.t.sol index 2fc00a9..abd515c 100644 --- a/dependencies/forge-std-1.11.0/test/LibVariable.t.sol +++ b/dependencies/forge-std-1.16.2/test/LibVariable.t.sol @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: MIT +// SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity ^0.8.13; import {Test} from "../src/Test.sol"; @@ -141,6 +141,24 @@ contract LibVariableTest is Test { assertEq(strings.length, 2); assertEq(strings[0], "one"); assertEq(strings[1], "two"); + + // Bytes32 array + bytes32[] memory b32s = helper.toBytes32Array(bytes32ArrayVar); + assertEq(b32s.length, 2); + assertEq(b32s[0], bytes32(uint256(1))); + assertEq(b32s[1], bytes32(uint256(2))); + + // Int array + int256[] memory ints = helper.toInt256Array(intArrayVar); + assertEq(ints.length, 2); + assertEq(ints[0], -1); + assertEq(ints[1], 2); + + // Bytes array + bytes[] memory b = helper.toBytesArray(bytesArrayVar); + assertEq(b.length, 2); + assertEq(b[0], hex"01"); + assertEq(b[1], hex"02"); } function test_Downcasting() public view { diff --git a/dependencies/forge-std-1.11.0/test/StdAssertions.t.sol b/dependencies/forge-std-1.16.2/test/StdAssertions.t.sol similarity index 98% rename from dependencies/forge-std-1.11.0/test/StdAssertions.t.sol rename to dependencies/forge-std-1.16.2/test/StdAssertions.t.sol index acc0c1e..3d670cb 100644 --- a/dependencies/forge-std-1.11.0/test/StdAssertions.t.sol +++ b/dependencies/forge-std-1.16.2/test/StdAssertions.t.sol @@ -1,5 +1,5 @@ -// SPDX-License-Identifier: MIT -pragma solidity >=0.7.0 <0.9.0; +// SPDX-License-Identifier: MIT OR Apache-2.0 +pragma solidity >=0.8.13 <0.9.0; import {StdAssertions} from "../src/StdAssertions.sol"; import {Vm} from "../src/Vm.sol"; diff --git a/dependencies/forge-std-1.11.0/test/StdChains.t.sol b/dependencies/forge-std-1.16.2/test/StdChains.t.sol similarity index 83% rename from dependencies/forge-std-1.11.0/test/StdChains.t.sol rename to dependencies/forge-std-1.16.2/test/StdChains.t.sol index 9522b37..bee1f99 100644 --- a/dependencies/forge-std-1.11.0/test/StdChains.t.sol +++ b/dependencies/forge-std-1.16.2/test/StdChains.t.sol @@ -1,22 +1,22 @@ -// SPDX-License-Identifier: MIT -pragma solidity >=0.7.0 <0.9.0; +// SPDX-License-Identifier: MIT OR Apache-2.0 +pragma solidity >=0.8.13 <0.9.0; import {Test} from "../src/Test.sol"; contract StdChainsMock is Test { - function exposed_getChain(string memory chainAlias) public returns (Chain memory) { + function exposedGetChain(string memory chainAlias) public returns (Chain memory) { return getChain(chainAlias); } - function exposed_getChain(uint256 chainId) public returns (Chain memory) { + function exposedGetChain(uint256 chainId) public returns (Chain memory) { return getChain(chainId); } - function exposed_setChain(string memory chainAlias, ChainData memory chainData) public { + function exposedSetChain(string memory chainAlias, ChainData memory chainData) public { setChain(chainAlias, chainData); } - function exposed_setFallbackToDefaultRpcUrls(bool useDefault) public { + function exposedSetFallbackToDefaultRpcUrls(bool useDefault) public { setFallbackToDefaultRpcUrls(useDefault); } } @@ -24,7 +24,7 @@ contract StdChainsMock is Test { contract StdChainsTest is Test { function test_ChainRpcInitialization() public { // RPCs specified in `foundry.toml` should be updated. - assertEq(getChain(1).rpcUrl, "https://eth.merkle.io"); + assertEq(getChain(1).rpcUrl, "https://ethereum.reth.rs/rpc"); assertEq(getChain("optimism_sepolia").rpcUrl, "https://sepolia.optimism.io/"); assertEq(getChain("arbitrum_one_sepolia").rpcUrl, "https://sepolia-rollup.arbitrum.io/rpc/"); @@ -36,7 +36,7 @@ contract StdChainsTest is Test { // Cannot override RPCs defined in `foundry.toml` vm.setEnv("MAINNET_RPC_URL", "myoverride2"); - assertEq(getChain("mainnet").rpcUrl, "https://eth.merkle.io"); + assertEq(getChain("mainnet").rpcUrl, "https://ethereum.reth.rs/rpc"); // Other RPCs should remain unchanged. assertEq(getChain(31337).rpcUrl, "http://127.0.0.1:8545"); @@ -89,7 +89,7 @@ contract StdChainsTest is Test { StdChainsMock stdChainsMock = new StdChainsMock(); vm.expectRevert("StdChains getChain(string): Chain with alias \"does_not_exist\" not found."); - stdChainsMock.exposed_getChain("does_not_exist"); + stdChainsMock.exposedGetChain("does_not_exist"); } function test_RevertIf_SetChain_ChainIdExist_FirstTest() public { @@ -97,28 +97,28 @@ contract StdChainsTest is Test { StdChainsMock stdChainsMock = new StdChainsMock(); vm.expectRevert("StdChains setChain(string,ChainData): Chain ID 31337 already used by \"anvil\"."); - stdChainsMock.exposed_setChain("anvil2", ChainData("Anvil", 31337, "URL")); + stdChainsMock.exposedSetChain("anvil2", ChainData("Anvil", 31337, "URL")); } function test_RevertIf_ChainBubbleUp() public { // We deploy a mock to properly test the revert. StdChainsMock stdChainsMock = new StdChainsMock(); - stdChainsMock.exposed_setChain("needs_undefined_env_var", ChainData("", 123456789, "")); + stdChainsMock.exposedSetChain("needs_undefined_env_var", ChainData("", 123456789, "")); // Forge environment variable error. vm.expectRevert(); - stdChainsMock.exposed_getChain("needs_undefined_env_var"); + stdChainsMock.exposedGetChain("needs_undefined_env_var"); } function test_RevertIf_SetChain_ChainIdExists_SecondTest() public { // We deploy a mock to properly test the revert. StdChainsMock stdChainsMock = new StdChainsMock(); - stdChainsMock.exposed_setChain("custom_chain", ChainData("Custom Chain", 123456789, "https://custom.chain/")); + stdChainsMock.exposedSetChain("custom_chain", ChainData("Custom Chain", 123456789, "https://custom.chain/")); vm.expectRevert('StdChains setChain(string,ChainData): Chain ID 123456789 already used by "custom_chain".'); - stdChainsMock.exposed_setChain("another_custom_chain", ChainData("", 123456789, "")); + stdChainsMock.exposedSetChain("another_custom_chain", ChainData("", 123456789, "")); } function test_SetChain() public { @@ -152,7 +152,7 @@ contract StdChainsTest is Test { StdChainsMock stdChainsMock = new StdChainsMock(); vm.expectRevert("StdChains setChain(string,ChainData): Chain alias cannot be the empty string."); - stdChainsMock.exposed_setChain("", ChainData("", 123456789, "")); + stdChainsMock.exposedSetChain("", ChainData("", 123456789, "")); } function test_RevertIf_SetNoChainId0() public { @@ -160,7 +160,7 @@ contract StdChainsTest is Test { StdChainsMock stdChainsMock = new StdChainsMock(); vm.expectRevert("StdChains setChain(string,ChainData): Chain ID cannot be 0."); - stdChainsMock.exposed_setChain("alias", ChainData("", 0, "")); + stdChainsMock.exposedSetChain("alias", ChainData("", 0, "")); } function test_RevertIf_GetNoChainId0() public { @@ -168,7 +168,7 @@ contract StdChainsTest is Test { StdChainsMock stdChainsMock = new StdChainsMock(); vm.expectRevert("StdChains getChain(uint256): Chain ID cannot be 0."); - stdChainsMock.exposed_getChain(0); + stdChainsMock.exposedGetChain(0); } function test_RevertIf_GetNoEmptyAlias() public { @@ -176,7 +176,7 @@ contract StdChainsTest is Test { StdChainsMock stdChainsMock = new StdChainsMock(); vm.expectRevert("StdChains getChain(string): Chain alias cannot be the empty string."); - stdChainsMock.exposed_getChain(""); + stdChainsMock.exposedGetChain(""); } function test_RevertIf_ChainNotInitialized() public { @@ -184,7 +184,7 @@ contract StdChainsTest is Test { StdChainsMock stdChainsMock = new StdChainsMock(); vm.expectRevert("StdChains getChain(string): Chain with alias \"no_such_alias\" not found."); - stdChainsMock.exposed_getChain("no_such_alias"); + stdChainsMock.exposedGetChain("no_such_alias"); } function test_RevertIf_ChainAliasNotFound() public { @@ -193,7 +193,7 @@ contract StdChainsTest is Test { vm.expectRevert("StdChains getChain(uint256): Chain with ID 321 not found."); - stdChainsMock.exposed_getChain(321); + stdChainsMock.exposedGetChain(321); } function test_SetChain_ExistingOne() public { @@ -205,7 +205,7 @@ contract StdChainsTest is Test { setChain("custom_chain", ChainData("Modified Chain", 9999999999999999999, "https://modified.chain/")); vm.expectRevert("StdChains getChain(uint256): Chain with ID 123456789 not found."); - stdChainsMock.exposed_getChain(123456789); + stdChainsMock.exposedGetChain(123456789); Chain memory modifiedChain = getChain(9999999999999999999); assertEq(modifiedChain.name, "Modified Chain"); @@ -218,10 +218,10 @@ contract StdChainsTest is Test { StdChainsMock stdChainsMock = new StdChainsMock(); // Should error if default RPCs flag is set to false. - stdChainsMock.exposed_setFallbackToDefaultRpcUrls(false); + stdChainsMock.exposedSetFallbackToDefaultRpcUrls(false); vm.expectRevert(); - stdChainsMock.exposed_getChain(31337); + stdChainsMock.exposedGetChain(31337); vm.expectRevert(); - stdChainsMock.exposed_getChain("sepolia"); + stdChainsMock.exposedGetChain("sepolia"); } } diff --git a/dependencies/forge-std-1.11.0/test/StdCheats.t.sol b/dependencies/forge-std-1.16.2/test/StdCheats.t.sol similarity index 85% rename from dependencies/forge-std-1.11.0/test/StdCheats.t.sol rename to dependencies/forge-std-1.16.2/test/StdCheats.t.sol index 57dbcc2..868829d 100644 --- a/dependencies/forge-std-1.11.0/test/StdCheats.t.sol +++ b/dependencies/forge-std-1.16.2/test/StdCheats.t.sol @@ -1,5 +1,5 @@ -// SPDX-License-Identifier: MIT -pragma solidity >=0.7.0 <0.9.0; +// SPDX-License-Identifier: MIT OR Apache-2.0 +pragma solidity >=0.8.13 <0.9.0; import {StdCheats} from "../src/StdCheats.sol"; import {Test} from "../src/Test.sol"; @@ -211,8 +211,7 @@ contract StdCheatsTest is Test { } function getCode(address who) internal view returns (bytes memory o_code) { - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { // retrieve the size of the code, this needs assembly let size := extcodesize(who) // allocate output byte array - this could also be done without assembly @@ -352,24 +351,24 @@ contract StdCheatsTest is Test { // VM address vm.expectRevert(); - stdCheatsMock.exposed_assumePayable(0x7109709ECfa91a80626fF3989D68f67F5b1DD12D); + stdCheatsMock.exposedAssumePayable(0x7109709ECfa91a80626fF3989D68f67F5b1DD12D); // Console address vm.expectRevert(); - stdCheatsMock.exposed_assumePayable(0x000000000000000000636F6e736F6c652e6c6f67); + stdCheatsMock.exposedAssumePayable(0x000000000000000000636F6e736F6c652e6c6f67); // Create2Deployer vm.expectRevert(); - stdCheatsMock.exposed_assumePayable(0x4e59b44847b379578588920cA78FbF26c0B4956C); + stdCheatsMock.exposedAssumePayable(0x4e59b44847b379578588920cA78FbF26c0B4956C); // all should pass since these addresses are payable // vitalik.eth - stdCheatsMock.exposed_assumePayable(0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045); + stdCheatsMock.exposedAssumePayable(0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045); // mock payable contract MockContractPayable cp = new MockContractPayable(); - stdCheatsMock.exposed_assumePayable(address(cp)); + stdCheatsMock.exposedAssumePayable(address(cp)); } function test_AssumeNotPayable() external { @@ -379,24 +378,24 @@ contract StdCheatsTest is Test { // all should pass since these addresses are not payable // VM address - stdCheatsMock.exposed_assumeNotPayable(0x7109709ECfa91a80626fF3989D68f67F5b1DD12D); + stdCheatsMock.exposedAssumeNotPayable(0x7109709ECfa91a80626fF3989D68f67F5b1DD12D); // Console address - stdCheatsMock.exposed_assumeNotPayable(0x000000000000000000636F6e736F6c652e6c6f67); + stdCheatsMock.exposedAssumeNotPayable(0x000000000000000000636F6e736F6c652e6c6f67); // Create2Deployer - stdCheatsMock.exposed_assumeNotPayable(0x4e59b44847b379578588920cA78FbF26c0B4956C); + stdCheatsMock.exposedAssumeNotPayable(0x4e59b44847b379578588920cA78FbF26c0B4956C); // all should revert since these addresses are payable // vitalik.eth vm.expectRevert(); - stdCheatsMock.exposed_assumeNotPayable(0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045); + stdCheatsMock.exposedAssumeNotPayable(0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045); // mock payable contract MockContractPayable cp = new MockContractPayable(); vm.expectRevert(); - stdCheatsMock.exposed_assumeNotPayable(address(cp)); + stdCheatsMock.exposedAssumeNotPayable(address(cp)); } function testFuzz_AssumeNotPrecompile(address addr) external { @@ -441,19 +440,72 @@ contract StdCheatsTest is Test { assertTrue(ct.y()); assertEq(ct.z(), bytes20(arbitraryAddress)); } + + function test_ExpectAndMockCall() public { + bytes memory data = abi.encodeWithSignature("balanceOf(address)", address(this)); + bytes memory returnData = abi.encode(uint256(100)); + expectAndMockCall(address(test), data, returnData); + + assertEq(test.balanceOf(address(this)), 100); + } + + function test_ExpectAndMockCall_Count() public { + bytes memory data = abi.encodeWithSignature("balanceOf(address)", address(this)); + bytes memory returnData = abi.encode(uint256(100)); + expectAndMockCall(address(test), data, 2, returnData); + + assertEq(test.balanceOf(address(this)), 100); + assertEq(test.balanceOf(address(this)), 100); + } + + function test_ExpectAndMockCall_MsgValue() public { + bytes memory data = abi.encodeWithSignature("payableBar()"); + bytes memory returnData = abi.encode(uint256(100)); + expectAndMockCall(address(test), 1 ether, data, returnData); + + assertEq(test.payableBar{value: 1 ether}(), 100); + } + + function test_ExpectAndMockCall_MsgValueAndCount() public { + bytes memory data = abi.encodeWithSignature("payableBar()"); + bytes memory returnData = abi.encode(uint256(100)); + expectAndMockCall(address(test), 1 ether, data, 2, returnData); + + assertEq(test.payableBar{value: 1 ether}(), 100); + assertEq(test.payableBar{value: 1 ether}(), 100); + } + + function test_ExpectAndMockCall_Gas() public { + bytes memory data = abi.encodeWithSignature("payableBar()"); + bytes memory returnData = abi.encode(uint256(100)); + uint64 gas = 30_000; + expectAndMockCall(address(test), 1 ether, gas, data, returnData); + + assertEq(test.payableBar{value: 1 ether, gas: gas}(), 100); + } + + function test_ExpectAndMockCall_GasAndCount() public { + bytes memory data = abi.encodeWithSignature("payableBar()"); + bytes memory returnData = abi.encode(uint256(100)); + uint64 gas = 30_000; + expectAndMockCall(address(test), 1 ether, gas, data, 2, returnData); + + assertEq(test.payableBar{value: 1 ether, gas: gas}(), 100); + assertEq(test.payableBar{value: 1 ether, gas: gas}(), 100); + } } contract StdCheatsMock is StdCheats { - function exposed_assumePayable(address addr) external { + function exposedAssumePayable(address addr) external { assumePayable(addr); } - function exposed_assumeNotPayable(address addr) external { + function exposedAssumeNotPayable(address addr) external { assumeNotPayable(addr); } // We deploy a mock version so we can properly test expected reverts. - function exposed_assumeNotBlacklisted(address token, address addr) external view { + function exposedAssumeNotBlacklisted(address token, address addr) external view { return assumeNotBlacklisted(token, addr); } } @@ -478,7 +530,7 @@ contract StdCheatsForkTest is Test { StdCheatsMock stdCheatsMock = new StdCheatsMock(); address eoa = vm.addr({privateKey: 1}); vm.expectRevert("StdCheats assumeNotBlacklisted(address,address): Token address is not a contract."); - stdCheatsMock.exposed_assumeNotBlacklisted(eoa, address(0)); + stdCheatsMock.exposedAssumeNotBlacklisted(eoa, address(0)); } function testFuzz_AssumeNotBlacklisted_TokenWithoutBlacklist(address addr) external view { @@ -491,7 +543,7 @@ contract StdCheatsForkTest is Test { // We deploy a mock version so we can properly test the revert. StdCheatsMock stdCheatsMock = new StdCheatsMock(); vm.expectRevert(); - stdCheatsMock.exposed_assumeNotBlacklisted(address(USDC), USDC_BLACKLISTED_USER); + stdCheatsMock.exposedAssumeNotBlacklisted(address(USDC), USDC_BLACKLISTED_USER); } function testFuzz_AssumeNotBlacklisted_USDC(address addr) external view { @@ -503,7 +555,7 @@ contract StdCheatsForkTest is Test { // We deploy a mock version so we can properly test the revert. StdCheatsMock stdCheatsMock = new StdCheatsMock(); vm.expectRevert(); - stdCheatsMock.exposed_assumeNotBlacklisted(address(USDT), USDT_BLACKLISTED_USER); + stdCheatsMock.exposedAssumeNotBlacklisted(address(USDT), USDT_BLACKLISTED_USER); } function testFuzz_AssumeNotBlacklisted_USDT(address addr) external view { @@ -568,6 +620,10 @@ contract Bar { require(tx.origin == expectedOrigin, "!prank"); } + function payableBar() public payable returns (uint256) { + return 0; + } + /// `DEAL` STDCHEAT mapping(address => uint256) public balanceOf; uint256 public totalSupply; diff --git a/dependencies/forge-std-1.11.0/test/StdConstants.t.sol b/dependencies/forge-std-1.16.2/test/StdConstants.t.sol similarity index 94% rename from dependencies/forge-std-1.11.0/test/StdConstants.t.sol rename to dependencies/forge-std-1.16.2/test/StdConstants.t.sol index 7a00530..8ed524e 100644 --- a/dependencies/forge-std-1.11.0/test/StdConstants.t.sol +++ b/dependencies/forge-std-1.16.2/test/StdConstants.t.sol @@ -1,5 +1,5 @@ -// SPDX-License-Identifier: MIT -pragma solidity >=0.7.0 <0.9.0; +// SPDX-License-Identifier: MIT OR Apache-2.0 +pragma solidity >=0.8.13 <0.9.0; import {StdConstants} from "../src/StdConstants.sol"; import {Test} from "../src/Test.sol"; diff --git a/dependencies/forge-std-1.11.0/test/StdError.t.sol b/dependencies/forge-std-1.16.2/test/StdError.t.sol similarity index 95% rename from dependencies/forge-std-1.11.0/test/StdError.t.sol rename to dependencies/forge-std-1.16.2/test/StdError.t.sol index 29803d5..7553ce4 100644 --- a/dependencies/forge-std-1.11.0/test/StdError.t.sol +++ b/dependencies/forge-std-1.16.2/test/StdError.t.sol @@ -1,5 +1,5 @@ -// SPDX-License-Identifier: MIT -pragma solidity >=0.8.0 <0.9.0; +// SPDX-License-Identifier: MIT OR Apache-2.0 +pragma solidity >=0.8.13 <0.9.0; import {stdError} from "../src/StdError.sol"; import {Test} from "../src/Test.sol"; @@ -91,8 +91,7 @@ contract ErrorsTest { } function encodeStgError() public { - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { sstore(someBytes.slot, 1) } keccak256(someBytes); diff --git a/dependencies/forge-std-1.11.0/test/StdJson.t.sol b/dependencies/forge-std-1.16.2/test/StdJson.t.sol similarity index 93% rename from dependencies/forge-std-1.11.0/test/StdJson.t.sol rename to dependencies/forge-std-1.16.2/test/StdJson.t.sol index 6bedfcc..5594a54 100644 --- a/dependencies/forge-std-1.11.0/test/StdJson.t.sol +++ b/dependencies/forge-std-1.16.2/test/StdJson.t.sol @@ -1,5 +1,5 @@ -// SPDX-License-Identifier: MIT -pragma solidity >=0.7.0 <0.9.0; +// SPDX-License-Identifier: MIT OR Apache-2.0 +pragma solidity >=0.8.13 <0.9.0; import {Test, stdJson} from "../src/Test.sol"; diff --git a/dependencies/forge-std-1.11.0/test/StdMath.t.sol b/dependencies/forge-std-1.16.2/test/StdMath.t.sol similarity index 93% rename from dependencies/forge-std-1.11.0/test/StdMath.t.sol rename to dependencies/forge-std-1.16.2/test/StdMath.t.sol index d1269a0..c7a36ed 100644 --- a/dependencies/forge-std-1.11.0/test/StdMath.t.sol +++ b/dependencies/forge-std-1.16.2/test/StdMath.t.sol @@ -1,15 +1,15 @@ -// SPDX-License-Identifier: MIT -pragma solidity >=0.8.0 <0.9.0; +// SPDX-License-Identifier: MIT OR Apache-2.0 +pragma solidity >=0.8.13 <0.9.0; import {stdMath} from "../src/StdMath.sol"; import {Test, stdError} from "../src/Test.sol"; contract StdMathMock is Test { - function exposed_percentDelta(uint256 a, uint256 b) public pure returns (uint256) { + function exposedPercentDelta(uint256 a, uint256 b) public pure returns (uint256) { return stdMath.percentDelta(a, b); } - function exposed_percentDelta(int256 a, int256 b) public pure returns (uint256) { + function exposedPercentDelta(int256 a, int256 b) public pure returns (uint256) { return stdMath.percentDelta(a, b); } } @@ -125,8 +125,8 @@ contract StdMathTest is Test { assertEq(stdMath.percentDelta(5000, uint256(2500)), 1e18); assertEq(stdMath.percentDelta(7500, uint256(2500)), 2e18); - vm.expectRevert(stdError.divisionError); - stdMathMock.exposed_percentDelta(uint256(1), 0); + vm.expectRevert("stdMath percentDelta(uint256,uint256): Divisor is zero"); + stdMathMock.exposedPercentDelta(uint256(1), 0); } function testFuzz_GetPercentDelta_Uint(uint192 a, uint192 b) external pure { @@ -163,8 +163,8 @@ contract StdMathTest is Test { assertEq(stdMath.percentDelta(5000, int256(2500)), 1e18); assertEq(stdMath.percentDelta(7500, int256(2500)), 2e18); - vm.expectRevert(stdError.divisionError); - stdMathMock.exposed_percentDelta(int256(1), 0); + vm.expectRevert("stdMath percentDelta(int256,int256): Divisor is zero"); + stdMathMock.exposedPercentDelta(int256(1), 0); } function testFuzz_GetPercentDelta_Int(int192 a, int192 b) external pure { diff --git a/dependencies/forge-std-1.11.0/test/StdStorage.t.sol b/dependencies/forge-std-1.16.2/test/StdStorage.t.sol similarity index 85% rename from dependencies/forge-std-1.11.0/test/StdStorage.t.sol rename to dependencies/forge-std-1.16.2/test/StdStorage.t.sol index 46604f8..ab87da3 100644 --- a/dependencies/forge-std-1.11.0/test/StdStorage.t.sol +++ b/dependencies/forge-std-1.16.2/test/StdStorage.t.sol @@ -1,5 +1,5 @@ -// SPDX-License-Identifier: MIT -pragma solidity >=0.7.0 <0.9.0; +// SPDX-License-Identifier: MIT OR Apache-2.0 +pragma solidity >=0.8.13 <0.9.0; import {stdStorage, StdStorage} from "../src/StdStorage.sol"; import {Test} from "../src/Test.sol"; @@ -58,9 +58,8 @@ contract StdStorageTest is Test { } function test_StorageDeepMap() public { - uint256 slot = stdstore.target(address(test)).sig(test.deep_map.selector).with_key(address(this)).with_key( - address(this) - ).find(); + uint256 slot = stdstore.target(address(test)).sig(test.deep_map.selector).with_key(address(this)) + .with_key(address(this)).find(); assertEq(uint256(keccak256(abi.encode(address(this), keccak256(abi.encode(address(this), uint256(5)))))), slot); } @@ -74,7 +73,9 @@ contract StdStorageTest is Test { uint256 slot = stdstore.target(address(test)).sig(test.deep_map_struct.selector).with_key(address(this)) .with_key(address(this)).depth(0).find(); assertEq( - bytes32(uint256(keccak256(abi.encode(address(this), keccak256(abi.encode(address(this), uint256(6)))))) + 0), + bytes32( + uint256(keccak256(abi.encode(address(this), keccak256(abi.encode(address(this), uint256(6)))))) + 0 + ), bytes32(slot) ); } @@ -83,24 +84,24 @@ contract StdStorageTest is Test { uint256 slot = stdstore.target(address(test)).sig(test.deep_map_struct.selector).with_key(address(this)) .with_key(address(this)).depth(1).find(); assertEq( - bytes32(uint256(keccak256(abi.encode(address(this), keccak256(abi.encode(address(this), uint256(6)))))) + 1), + bytes32( + uint256(keccak256(abi.encode(address(this), keccak256(abi.encode(address(this), uint256(6)))))) + 1 + ), bytes32(slot) ); } function test_StorageCheckedWriteDeepMapStructA() public { - stdstore.target(address(test)).sig(test.deep_map_struct.selector).with_key(address(this)).with_key( - address(this) - ).depth(0).checked_write(100); + stdstore.target(address(test)).sig(test.deep_map_struct.selector).with_key(address(this)) + .with_key(address(this)).depth(0).checked_write(100); (uint256 a, uint256 b) = test.deep_map_struct(address(this), address(this)); assertEq(100, a); assertEq(0, b); } function test_StorageCheckedWriteDeepMapStructB() public { - stdstore.target(address(test)).sig(test.deep_map_struct.selector).with_key(address(this)).with_key( - address(this) - ).depth(1).checked_write(100); + stdstore.target(address(test)).sig(test.deep_map_struct.selector).with_key(address(this)) + .with_key(address(this)).depth(1).checked_write(100); (uint256 a, uint256 b) = test.deep_map_struct(address(this), address(this)); assertEq(0, a); assertEq(100, b); @@ -192,9 +193,8 @@ contract StdStorageTest is Test { uint256 full = test.map_packed(address(1337)); // keep upper 128, set lower 128 to 1337 full = (full & (uint256((1 << 128) - 1) << 128)) | 1337; - stdstore.target(address(test)).sig(test.map_packed.selector).with_key(address(uint160(1337))).checked_write( - full - ); + stdstore.target(address(test)).sig(test.map_packed.selector).with_key(address(uint160(1337))) + .checked_write(full); assertEq(1337, test.read_struct_lower(address(1337))); } @@ -290,9 +290,9 @@ contract StdStorageTest is Test { // clear left bits, then clear right bits and realign uint256 expectedValToRead = (val << leftBits) >> (leftBits + rightBits); - uint256 readVal = stdstore.target(address(test)).enable_packed_slots().sig( - "getRandomPacked(uint8,uint8[],uint8)" - ).with_calldata(abi.encode(shifts, shiftSizes, elemToGet)).read_uint(); + uint256 readVal = stdstore.target(address(test)).enable_packed_slots() + .sig("getRandomPacked(uint8,uint8[],uint8)").with_calldata(abi.encode(shifts, shiftSizes, elemToGet)) + .read_uint(); assertEq(readVal, expectedValToRead); } @@ -330,16 +330,14 @@ contract StdStorageTest is Test { // Pack all values into the slot. for (uint256 i = 0; i < nvars; i++) { - stdstore.enable_packed_slots().target(address(test)).sig("getRandomPacked(uint256,uint256)").with_key( - sizes[i] - ).with_key(offsets[i]).checked_write(vals[i]); + stdstore.enable_packed_slots().target(address(test)).sig("getRandomPacked(uint256,uint256)") + .with_key(sizes[i]).with_key(offsets[i]).checked_write(vals[i]); } // Verify the read data matches. for (uint256 i = 0; i < nvars; i++) { - uint256 readVal = stdstore.enable_packed_slots().target(address(test)).sig( - "getRandomPacked(uint256,uint256)" - ).with_key(sizes[i]).with_key(offsets[i]).read_uint(); + uint256 readVal = stdstore.enable_packed_slots().target(address(test)) + .sig("getRandomPacked(uint256,uint256)").with_key(sizes[i]).with_key(offsets[i]).read_uint(); uint256 retVal = test.getRandomPacked(sizes[i], offsets[i]); @@ -352,6 +350,16 @@ contract StdStorageTest is Test { stdstore.target(address(test)).sig("edgeCaseArray(uint256)").with_key(uint256(0)).checked_write(1); assertEq(test.edgeCaseArray(0), 1); } + + // Regression test for https://github.com/foundry-rs/forge-std/issues/740 + // `find()` used to infinite-loop on tokens whose `balanceOf` reads multiple + // storage slots and returns a derived value (reflection tokens). + function test_RevertFindOnReflectionToken() public { + MockReflectionToken token = new MockReflectionToken(); + ReflectionTokenTarget target = new ReflectionTokenTarget(token); + vm.expectRevert("stdStorage find(StdStorage): Slot(s) not found."); + target.findBalanceOf(address(this)); + } } contract StorageTestTarget { @@ -369,6 +377,21 @@ contract StorageTestTarget { } } +contract ReflectionTokenTarget { + using stdStorage for StdStorage; + + StdStorage internal stdstore; + MockReflectionToken internal token; + + constructor(MockReflectionToken token_) { + token = token_; + } + + function findBalanceOf(address who) public { + stdstore.target(address(token)).sig("balanceOf(address)").with_key(who).find(); + } +} + contract StorageTest { uint256 public exists = 1; mapping(address => uint256) public map_addr; @@ -421,8 +444,7 @@ contract StorageTest { function hidden() public view returns (bytes32 t) { bytes32 slot = keccak256("my.random.var"); - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { t := sload(slot) } } @@ -486,3 +508,25 @@ contract StorageTest { return (randomPacking << leftBits) >> (leftBits + rightBits); } } + +// Minimal mock of a reflection token: `balanceOf` reads many storage slots +// and always returns a constant, so no single slot mutation can change its +// return value and stdStorage can never find a matching slot. +contract MockReflectionToken { + uint256 internal _a = 1; + uint256 internal _b = 2; + uint256 internal _c = 3; + mapping(address => uint256) internal _balances; + + constructor() { + _balances[msg.sender] = 1000 ether; + } + + // Reads _a, _b, _c, and _balances[account] but always returns a constant. + // This means mutating any single slot won't change the return value. + function balanceOf(address account) public view returns (uint256) { + uint256 x = _a + _b + _c + _balances[account]; + x; // suppress unused warning + return 42; + } +} diff --git a/dependencies/forge-std-1.11.0/test/StdStyle.t.sol b/dependencies/forge-std-1.16.2/test/StdStyle.t.sol similarity index 98% rename from dependencies/forge-std-1.11.0/test/StdStyle.t.sol rename to dependencies/forge-std-1.16.2/test/StdStyle.t.sol index 974e756..1146a8d 100644 --- a/dependencies/forge-std-1.11.0/test/StdStyle.t.sol +++ b/dependencies/forge-std-1.16.2/test/StdStyle.t.sol @@ -1,5 +1,5 @@ -// SPDX-License-Identifier: MIT -pragma solidity >=0.7.0 <0.9.0; +// SPDX-License-Identifier: MIT OR Apache-2.0 +pragma solidity >=0.8.13 <0.9.0; import {Test, console2, StdStyle} from "../src/Test.sol"; diff --git a/dependencies/forge-std-1.11.0/test/StdToml.t.sol b/dependencies/forge-std-1.16.2/test/StdToml.t.sol similarity index 93% rename from dependencies/forge-std-1.11.0/test/StdToml.t.sol rename to dependencies/forge-std-1.16.2/test/StdToml.t.sol index 5a45f4f..306dda9 100644 --- a/dependencies/forge-std-1.11.0/test/StdToml.t.sol +++ b/dependencies/forge-std-1.16.2/test/StdToml.t.sol @@ -1,5 +1,5 @@ -// SPDX-License-Identifier: MIT -pragma solidity >=0.7.0 <0.9.0; +// SPDX-License-Identifier: MIT OR Apache-2.0 +pragma solidity >=0.8.13 <0.9.0; import {Test, stdToml} from "../src/Test.sol"; diff --git a/dependencies/forge-std-1.11.0/test/StdUtils.t.sol b/dependencies/forge-std-1.16.2/test/StdUtils.t.sol similarity index 94% rename from dependencies/forge-std-1.11.0/test/StdUtils.t.sol rename to dependencies/forge-std-1.16.2/test/StdUtils.t.sol index aee801b..c0a3d3a 100644 --- a/dependencies/forge-std-1.11.0/test/StdUtils.t.sol +++ b/dependencies/forge-std-1.16.2/test/StdUtils.t.sol @@ -1,26 +1,26 @@ -// SPDX-License-Identifier: MIT -pragma solidity >=0.7.0 <0.9.0; +// SPDX-License-Identifier: MIT OR Apache-2.0 +pragma solidity >=0.8.13 <0.9.0; import {Test, StdUtils} from "../src/Test.sol"; contract StdUtilsMock is StdUtils { // We deploy a mock version so we can properly test expected reverts. - function exposed_getTokenBalances(address token, address[] memory addresses) + function exposedGetTokenBalances(address token, address[] memory addresses) external returns (uint256[] memory balances) { return getTokenBalances(token, addresses); } - function exposed_bound(int256 num, int256 min, int256 max) external pure returns (int256) { + function exposedBound(int256 num, int256 min, int256 max) external pure returns (int256) { return bound(num, min, max); } - function exposed_bound(uint256 num, uint256 min, uint256 max) external pure returns (uint256) { + function exposedBound(uint256 num, uint256 min, uint256 max) external pure returns (uint256) { return bound(num, min, max); } - function exposed_bytesToUint(bytes memory b) external pure returns (uint256) { + function exposedBytesToUint(bytes memory b) external pure returns (uint256) { return bytesToUint(b); } } @@ -94,7 +94,7 @@ contract StdUtilsTest is Test { StdUtilsMock stdUtils = new StdUtilsMock(); vm.expectRevert(bytes("StdUtils bound(uint256,uint256,uint256): Max is less than min.")); - stdUtils.exposed_bound(uint256(5), 100, 10); + stdUtils.exposedBound(uint256(5), 100, 10); } function testFuzz_RevertIf_BoundMaxLessThanMin(uint256 num, uint256 min, uint256 max) public { @@ -103,7 +103,7 @@ contract StdUtilsTest is Test { vm.assume(min > max); vm.expectRevert(bytes("StdUtils bound(uint256,uint256,uint256): Max is less than min.")); - stdUtils.exposed_bound(num, min, max); + stdUtils.exposedBound(num, min, max); } /*////////////////////////////////////////////////////////////////////////// @@ -188,7 +188,7 @@ contract StdUtilsTest is Test { StdUtilsMock stdUtils = new StdUtilsMock(); vm.expectRevert(bytes("StdUtils bound(int256,int256,int256): Max is less than min.")); - stdUtils.exposed_bound(-5, 100, 10); + stdUtils.exposedBound(-5, 100, 10); } function testFuzz_RevertIf_BoundIntMaxLessThanMin(int256 num, int256 min, int256 max) public { @@ -197,7 +197,7 @@ contract StdUtilsTest is Test { vm.assume(min > max); vm.expectRevert(bytes("StdUtils bound(int256,int256,int256): Max is less than min.")); - stdUtils.exposed_bound(num, min, max); + stdUtils.exposedBound(num, min, max); } /*////////////////////////////////////////////////////////////////////////// @@ -235,7 +235,7 @@ contract StdUtilsTest is Test { bytes memory thirty3Bytes = hex"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"; vm.expectRevert("StdUtils bytesToUint(bytes): Bytes length exceeds 32."); - stdUtils.exposed_bytesToUint(thirty3Bytes); + stdUtils.exposedBytesToUint(thirty3Bytes); } /*////////////////////////////////////////////////////////////////////////// @@ -300,7 +300,7 @@ contract StdUtilsForkTest is Test { addresses[0] = USDC_HOLDER_0; vm.expectRevert("Multicall3: call failed"); - stdUtils.exposed_getTokenBalances(token, addresses); + stdUtils.exposedGetTokenBalances(token, addresses); } function test_RevertIf_CannotGetTokenBalances_EOA() external { @@ -311,7 +311,7 @@ contract StdUtilsForkTest is Test { address[] memory addresses = new address[](1); addresses[0] = USDC_HOLDER_0; vm.expectRevert("StdUtils getTokenBalances(address,address[]): Token address is not a contract."); - stdUtils.exposed_getTokenBalances(eoa, addresses); + stdUtils.exposedGetTokenBalances(eoa, addresses); } function test_GetTokenBalances_Empty() external { diff --git a/dependencies/forge-std-1.11.0/test/Vm.t.sol b/dependencies/forge-std-1.16.2/test/Vm.t.sol similarity index 69% rename from dependencies/forge-std-1.11.0/test/Vm.t.sol rename to dependencies/forge-std-1.16.2/test/Vm.t.sol index 1b99e3d..1f16485 100644 --- a/dependencies/forge-std-1.11.0/test/Vm.t.sol +++ b/dependencies/forge-std-1.16.2/test/Vm.t.sol @@ -1,5 +1,5 @@ -// SPDX-License-Identifier: MIT -pragma solidity >=0.8.0 <0.9.0; +// SPDX-License-Identifier: MIT OR Apache-2.0 +pragma solidity >=0.8.13 <0.9.0; import {Test} from "../src/Test.sol"; import {Vm, VmSafe} from "../src/Vm.sol"; @@ -9,10 +9,10 @@ import {Vm, VmSafe} from "../src/Vm.sol"; // added to or removed from Vm or VmSafe. contract VmTest is Test { function test_VmInterfaceId() public pure { - assertEq(type(Vm).interfaceId, bytes4(0xe835828d), "Vm"); + assertEq(type(Vm).interfaceId, bytes4(0x23dda1ff), "Vm"); } function test_VmSafeInterfaceId() public pure { - assertEq(type(VmSafe).interfaceId, bytes4(0xe02727c3), "VmSafe"); + assertEq(type(VmSafe).interfaceId, bytes4(0xc784e709), "VmSafe"); } } diff --git a/dependencies/forge-std-1.11.0/test/compilation/CompilationScript.sol b/dependencies/forge-std-1.16.2/test/compilation/CompilationScript.sol similarity index 75% rename from dependencies/forge-std-1.11.0/test/compilation/CompilationScript.sol rename to dependencies/forge-std-1.16.2/test/compilation/CompilationScript.sol index d3d88a0..6efbfa6 100644 --- a/dependencies/forge-std-1.11.0/test/compilation/CompilationScript.sol +++ b/dependencies/forge-std-1.16.2/test/compilation/CompilationScript.sol @@ -1,7 +1,5 @@ -// SPDX-License-Identifier: MIT -pragma solidity >=0.6.2 <0.9.0; - -pragma experimental ABIEncoderV2; +// SPDX-License-Identifier: MIT OR Apache-2.0 +pragma solidity >=0.8.13 <0.9.0; import {Script} from "../../src/Script.sol"; diff --git a/dependencies/forge-std-1.11.0/test/compilation/CompilationScriptBase.sol b/dependencies/forge-std-1.16.2/test/compilation/CompilationScriptBase.sol similarity index 76% rename from dependencies/forge-std-1.11.0/test/compilation/CompilationScriptBase.sol rename to dependencies/forge-std-1.16.2/test/compilation/CompilationScriptBase.sol index 65b5bed..7532973 100644 --- a/dependencies/forge-std-1.11.0/test/compilation/CompilationScriptBase.sol +++ b/dependencies/forge-std-1.16.2/test/compilation/CompilationScriptBase.sol @@ -1,7 +1,5 @@ -// SPDX-License-Identifier: MIT -pragma solidity >=0.6.2 <0.9.0; - -pragma experimental ABIEncoderV2; +// SPDX-License-Identifier: MIT OR Apache-2.0 +pragma solidity >=0.8.13 <0.9.0; import {ScriptBase} from "../../src/Script.sol"; diff --git a/dependencies/forge-std-1.11.0/test/compilation/CompilationTest.sol b/dependencies/forge-std-1.16.2/test/compilation/CompilationTest.sol similarity index 75% rename from dependencies/forge-std-1.11.0/test/compilation/CompilationTest.sol rename to dependencies/forge-std-1.16.2/test/compilation/CompilationTest.sol index 2a9dec5..5ba888e 100644 --- a/dependencies/forge-std-1.11.0/test/compilation/CompilationTest.sol +++ b/dependencies/forge-std-1.16.2/test/compilation/CompilationTest.sol @@ -1,7 +1,5 @@ -// SPDX-License-Identifier: MIT -pragma solidity >=0.6.2 <0.9.0; - -pragma experimental ABIEncoderV2; +// SPDX-License-Identifier: MIT OR Apache-2.0 +pragma solidity >=0.8.13 <0.9.0; import {Test} from "../../src/Test.sol"; diff --git a/dependencies/forge-std-1.11.0/test/compilation/CompilationTestBase.sol b/dependencies/forge-std-1.16.2/test/compilation/CompilationTestBase.sol similarity index 76% rename from dependencies/forge-std-1.11.0/test/compilation/CompilationTestBase.sol rename to dependencies/forge-std-1.16.2/test/compilation/CompilationTestBase.sol index 32b3fc5..9c081f7 100644 --- a/dependencies/forge-std-1.11.0/test/compilation/CompilationTestBase.sol +++ b/dependencies/forge-std-1.16.2/test/compilation/CompilationTestBase.sol @@ -1,7 +1,5 @@ -// SPDX-License-Identifier: MIT -pragma solidity >=0.6.2 <0.9.0; - -pragma experimental ABIEncoderV2; +// SPDX-License-Identifier: MIT OR Apache-2.0 +pragma solidity >=0.8.13 <0.9.0; import {TestBase} from "../../src/Test.sol"; diff --git a/dependencies/forge-std-1.11.0/test/fixtures/broadcast.log.json b/dependencies/forge-std-1.16.2/test/fixtures/broadcast.log.json similarity index 100% rename from dependencies/forge-std-1.11.0/test/fixtures/broadcast.log.json rename to dependencies/forge-std-1.16.2/test/fixtures/broadcast.log.json diff --git a/dependencies/forge-std-1.11.0/test/fixtures/config.toml b/dependencies/forge-std-1.16.2/test/fixtures/config.toml similarity index 100% rename from dependencies/forge-std-1.11.0/test/fixtures/config.toml rename to dependencies/forge-std-1.16.2/test/fixtures/config.toml diff --git a/dependencies/forge-std-1.11.0/test/fixtures/test.json b/dependencies/forge-std-1.16.2/test/fixtures/test.json similarity index 100% rename from dependencies/forge-std-1.11.0/test/fixtures/test.json rename to dependencies/forge-std-1.16.2/test/fixtures/test.json diff --git a/dependencies/forge-std-1.11.0/test/fixtures/test.toml b/dependencies/forge-std-1.16.2/test/fixtures/test.toml similarity index 100% rename from dependencies/forge-std-1.11.0/test/fixtures/test.toml rename to dependencies/forge-std-1.16.2/test/fixtures/test.toml diff --git a/dependencies/halmos-cheatcodes/LICENSE b/dependencies/halmos-cheatcodes/LICENSE new file mode 100644 index 0000000..0ad25db --- /dev/null +++ b/dependencies/halmos-cheatcodes/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/halmos-cheatcodes/README.md b/dependencies/halmos-cheatcodes/README.md new file mode 100644 index 0000000..209c2cf --- /dev/null +++ b/dependencies/halmos-cheatcodes/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/halmos-cheatcodes/src/SVM.sol b/dependencies/halmos-cheatcodes/src/SVM.sol new file mode 100644 index 0000000..5e435cc --- /dev/null +++ b/dependencies/halmos-cheatcodes/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/halmos-cheatcodes/src/SymTest.sol b/dependencies/halmos-cheatcodes/src/SymTest.sol new file mode 100644 index 0000000..96684ed --- /dev/null +++ b/dependencies/halmos-cheatcodes/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/kontrol-cheatcodes/.github/workflows/master-push.yml b/dependencies/kontrol-cheatcodes/.github/workflows/master-push.yml new file mode 100644 index 0000000..53d65bc --- /dev/null +++ b/dependencies/kontrol-cheatcodes/.github/workflows/master-push.yml @@ -0,0 +1,35 @@ +name: 'Master Push' +on: + push: + branches: + - 'master' + +jobs: + + cut-release: + name: 'Cut Release' + runs-on: ubuntu-latest + steps: + - name: 'Install expect' + run: sudo apt-get update && sudo apt-get install -y expect + + - name: Install Foundry + uses: foundry-rs/foundry-toolchain@v1.2.0 + + - name: 'Checkout Code' + uses: actions/checkout@v4 + + - name: 'Run Expect Script' + shell: bash + run: | + pushd src > /dev/null + script -q -c "expect scripts/soldeer_publish.expect ${{ vars.SOLDEER_EMAIL }} ${{ secrets.SOLDEER_PASSWORD }} ${{ github.event.push.head.sha }}" /dev/null + popd > /dev/null + + - name: 'Create release' + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + set -x + short_sha=$(git rev-parse --short ${{ github.sha }}) + gh release create ${short_sha} --target ${{ github.sha }} diff --git a/dependencies/kontrol-cheatcodes/.gitignore b/dependencies/kontrol-cheatcodes/.gitignore new file mode 100644 index 0000000..5f03e6a --- /dev/null +++ b/dependencies/kontrol-cheatcodes/.gitignore @@ -0,0 +1,2 @@ +# Ignore Dry-run artifacts +*.zip diff --git a/dependencies/kontrol-cheatcodes/README.md b/dependencies/kontrol-cheatcodes/README.md new file mode 100644 index 0000000..be180d3 --- /dev/null +++ b/dependencies/kontrol-cheatcodes/README.md @@ -0,0 +1,19 @@ +# Kontrol Cheatcodes + +Kontrol cheatcodes complement [Foundry's cheatcodes](https://book.getfoundry.sh/cheatcodes/) to enhance the expressivity of your symbolic specifications even further. With these cheatcodes, you can, for instance, make the storage of a given address symbolic, create new symbolic values, or expect that no further calls are made. + +Check out our [Kontrol documentation](https://docs.runtimeverification.com/kontrol/overview/readme) to start writing and executing symbolic tests for your project! + +Join our [Discord](https://discord.gg/9nFGwVRfMD) to ask any questions you may have. + +## Installation + +You can install this repository either via `forge` or as a `git` submodule: + +``` +forge install runtimeverification/kontrol-cheatcodes +``` + +``` +git submodule add https://github.com/runtimeverification/kontrol-cheatcodes +``` diff --git a/dependencies/kontrol-cheatcodes/scripts/soldeer_publish.expect b/dependencies/kontrol-cheatcodes/scripts/soldeer_publish.expect new file mode 100755 index 0000000..0904325 --- /dev/null +++ b/dependencies/kontrol-cheatcodes/scripts/soldeer_publish.expect @@ -0,0 +1,57 @@ +#!/usr/bin/expect -f +#################### +# An expect script to handle the manual login and push process for soldeerk +#################### + +# Inherit the user's environment +set env(PATH) $::env(PATH) + +# Check if the correct number of arguments is provided +if { $argc != 2 } { + puts "Usage: $argv0 " + exit 1 +} + +# Assign arguments to variables +set email [lindex $argv 0] +set password [lindex $argv 1] + +# Command to start the login process +set command "forge soldeer login" + +# Full path to the forge command +set command "/home/blueeagle/.foundry/bin/forge soldeer login" + +# Start the login process +spawn bash -c "$command" + +# Wait for the email prompt and send the email +expect "Please enter your email:" +send "$email\r" + +# Wait for the password prompt and send the password +expect "Please enter your password:" +send "$password\r" + +# Wait for the success message +expect { + "Login successful" { + puts "Login successful" + } + "Login failed" { + puts "Login failed" + exit 1 + } +} + +# Wait for the end of the interaction +expect eof + +# Command to push after login +set push_command "forge soldeer push kontrol-cheatcodes~[lindex $argv 2]" + +# Start the push process +spawn bash -c "$push_command" + +# Wait for the end of the push interaction +expect eof \ No newline at end of file diff --git a/dependencies/kontrol-cheatcodes/src/IKontrolCheatsBase.sol b/dependencies/kontrol-cheatcodes/src/IKontrolCheatsBase.sol new file mode 100644 index 0000000..d758669 --- /dev/null +++ b/dependencies/kontrol-cheatcodes/src/IKontrolCheatsBase.sol @@ -0,0 +1,53 @@ +// SPDX-License-Identifier: MIT +pragma solidity >=0.6.2 <0.9.0; +pragma experimental ABIEncoderV2; + +interface KontrolCheatsBase { + enum ComparisonOperator { Equal, NotEqual, LessThanOrEqual, LessThan, GreaterThanOrEqual, GreaterThan } + // Expects a call using the CALL opcode to an address with the specified calldata. + function expectRegularCall(address,bytes calldata) external; + // Expects a call using the CALL opcode to an address with the specified msg.value and calldata. + function expectRegularCall(address,uint256,bytes calldata) external; + // Expects a static call to an address with the specified calldata. + function expectStaticCall(address,bytes calldata) external; + // Expects a delegate call to an address with the specified calldata. + function expectDelegateCall(address,bytes calldata) external; + // Expects that no contract calls are made after invoking the cheatcode. + function expectNoCall() external; + // Expects the given address to deploy a new contract, using the CREATE opcode, with the specified value and bytecode. + function expectCreate(address,uint256,bytes calldata) external; + // Expects the given address to deploy a new contract, using the CREATE2 opcode, with the specified value and bytecode (appended with a bytes32 salt). + function expectCreate2(address,uint256,bytes calldata) external; + // Makes the storage of the given address completely symbolic. + function symbolicStorage(address) external; + // Makes the storage of the given address completely symbolic with specified K variable name. + function symbolicStorage(address, string calldata) external; + // Adds an address to the whitelist. + function allowCallsToAddress(address) external; + // Adds an address and calldata to the whitelist. + function allowCalls(address, bytes calldata) external; + // Adds an address and a storage slot to the whitelist. + function allowChangesToStorage(address,uint256) external; + // Sets the remaining gas to an infinite value. + function infiniteGas() external; + // Sets the current cell to the supplied amount. + function setGas(uint256) external; + // Returns a symbolic unsigned integer + function freshUInt(uint8) external view returns (uint256); + // Returns a symbolic unsigned integer with specified K variable name. + function freshUInt(uint8, string calldata) external view returns (uint256); + // Returns a symbolic boolean value + function freshBool() external view returns (bool); + // Returns a symbolic boolean value with specified K variable name. + function freshBool(string calldata) external view returns (bool); + // Returns a symbolic byte array + function freshBytes(uint256) external view returns (bytes memory); + // Returns a symbolic byte array with specified K variable name. + function freshBytes(uint256, string calldata) external view returns (bytes memory); + // Returns a symbolic address + function freshAddress() external view returns (address); + // Returns a symbolic address with specified K variable name. + function freshAddress(string calldata) external view returns (address); + // Removes a branching condition from the path constraints + function forgetBranch(uint256, ComparisonOperator, uint256) external; +} diff --git a/dependencies/kontrol-cheatcodes/src/KontrolCheats.sol b/dependencies/kontrol-cheatcodes/src/KontrolCheats.sol new file mode 100644 index 0000000..f59ac26 --- /dev/null +++ b/dependencies/kontrol-cheatcodes/src/KontrolCheats.sol @@ -0,0 +1,535 @@ +// SPDX-License-Identifier: MIT +pragma solidity >=0.6.2 <0.9.0; +pragma experimental ABIEncoderV2; + +import "./IKontrolCheatsBase.sol"; + +abstract contract KontrolCheats { + KontrolCheatsBase public constant kevm = KontrolCheatsBase(address(uint160(uint256(keccak256("hevm cheat code"))))); + + // Checks if an address matches one of the built-in addresses. + function notBuiltinAddress(address addr) internal pure returns (bool) { + return (addr != address(645326474426547203313410069153905908525362434349) && + addr != address(728815563385977040452943777879061427756277306518)); + } + + function freshUInt256() internal view returns (uint256) { + return kevm.freshUInt(32); + } + + function freshUInt248() internal view returns (uint248) { + return uint248(kevm.freshUInt(31)); + } + + function freshUInt240() internal view returns (uint240) { + return uint240(kevm.freshUInt(30)); + } + + function freshUInt232() internal view returns (uint232) { + return uint232(kevm.freshUInt(29)); + } + + function freshUInt224() internal view returns (uint224) { + return uint224(kevm.freshUInt(28)); + } + + function freshUInt216() internal view returns (uint216) { + return uint216(kevm.freshUInt(27)); + } + + function freshUInt208() internal view returns (uint208) { + return uint208(kevm.freshUInt(26)); + } + + function freshUInt200() internal view returns (uint200) { + return uint200(kevm.freshUInt(25)); + } + + function freshUInt192() internal view returns (uint192) { + return uint192(kevm.freshUInt(24)); + } + + function freshUInt184() internal view returns (uint184) { + return uint184(kevm.freshUInt(23)); + } + + function freshUInt176() internal view returns (uint176) { + return uint176(kevm.freshUInt(22)); + } + + function freshUInt168() internal view returns (uint168) { + return uint168(kevm.freshUInt(21)); + } + + function freshUInt160() internal view returns (uint160) { + return uint160(kevm.freshUInt(20)); + } + + function freshUInt152() internal view returns (uint152) { + return uint152(kevm.freshUInt(19)); + } + + function freshUInt144() internal view returns (uint144) { + return uint144(kevm.freshUInt(18)); + } + + function freshUInt136() internal view returns (uint136) { + return uint136(kevm.freshUInt(17)); + } + + function freshUInt128() internal view returns (uint128) { + return uint128(kevm.freshUInt(16)); + } + + function freshUInt120() internal view returns (uint120) { + return uint120(kevm.freshUInt(15)); + } + + function freshUInt112() internal view returns (uint112) { + return uint112(kevm.freshUInt(14)); + } + + function freshUInt104() internal view returns (uint104) { + return uint104(kevm.freshUInt(13)); + } + + function freshUInt96() internal view returns (uint96) { + return uint96(kevm.freshUInt(12)); + } + + function freshUInt88() internal view returns (uint88) { + return uint88(kevm.freshUInt(11)); + } + + function freshUInt80() internal view returns (uint80) { + return uint80(kevm.freshUInt(10)); + } + + function freshUInt72() internal view returns (uint72) { + return uint72(kevm.freshUInt(9)); + } + + function freshUInt64() internal view returns (uint64) { + return uint64(kevm.freshUInt(8)); + } + + function freshUInt56() internal view returns (uint56) { + return uint56(kevm.freshUInt(7)); + } + + function freshUInt48() internal view returns (uint48) { + return uint48(kevm.freshUInt(6)); + } + + function freshUInt40() internal view returns (uint40) { + return uint40(kevm.freshUInt(5)); + } + + function freshUInt32() internal view returns (uint32) { + return uint32(kevm.freshUInt(4)); + } + + function freshUInt24() internal view returns (uint24) { + return uint24(kevm.freshUInt(3)); + } + + function freshUInt16() internal view returns (uint16) { + return uint16(kevm.freshUInt(2)); + } + + function freshUInt8() internal view returns (uint8) { + return uint8(kevm.freshUInt(1)); + } + + function freshAddress() internal view returns (address) { + return address(uint160(kevm.freshUInt(20))); + } + + function freshSInt256() internal view returns (int256) { + return int256(kevm.freshUInt(32)); + } + + function freshSInt248() internal view returns (int248) { + return int248(uint248(kevm.freshUInt(31))); + } + + function freshSInt240() internal view returns (int240) { + return int240(uint240(kevm.freshUInt(30))); + } + + function freshSInt232() internal view returns (int232) { + return int232(uint232(kevm.freshUInt(29))); + } + + function freshSInt224() internal view returns (int224) { + return int224(uint224(kevm.freshUInt(28))); + } + + function freshSInt216() internal view returns (int216) { + return int216(uint216(kevm.freshUInt(27))); + } + + function freshSInt208() internal view returns (int208) { + return int208(uint208(kevm.freshUInt(26))); + } + + function freshSInt200() internal view returns (int200) { + return int200(uint200(kevm.freshUInt(25))); + } + + function freshSInt192() internal view returns (int192) { + return int192(uint192(kevm.freshUInt(24))); + } + + function freshSInt184() internal view returns (int184) { + return int184(uint184(kevm.freshUInt(23))); + } + + function freshSInt176() internal view returns (int176) { + return int176(uint176(kevm.freshUInt(22))); + } + + function freshSInt168() internal view returns (int168) { + return int168(uint168(kevm.freshUInt(21))); + } + + function freshSInt160() internal view returns (int160) { + return int160(uint160(kevm.freshUInt(20))); + } + + function freshSInt152() internal view returns (int152) { + return int152(uint152(kevm.freshUInt(19))); + } + + function freshSInt144() internal view returns (int144) { + return int144(uint144(kevm.freshUInt(18))); + } + + function freshSInt136() internal view returns (int136) { + return int136(uint136(kevm.freshUInt(17))); + } + + function freshSInt128() internal view returns (int128) { + return int128(uint128(kevm.freshUInt(16))); + } + + function freshSInt120() internal view returns (int120) { + return int120(uint120(kevm.freshUInt(15))); + } + + function freshSInt112() internal view returns (int112) { + return int112(uint112(kevm.freshUInt(14))); + } + + function freshSInt104() internal view returns (int104) { + return int104(uint104(kevm.freshUInt(13))); + } + + function freshSInt96() internal view returns (int96) { + return int96(uint96(kevm.freshUInt(12))); + } + + function freshSInt88() internal view returns (int88) { + return int88(uint88(kevm.freshUInt(11))); + } + + function freshSInt80() internal view returns (int80) { + return int80(uint80(kevm.freshUInt(10))); + } + + function freshSInt72() internal view returns (int72) { + return int72(uint72(kevm.freshUInt(9))); + } + + function freshSInt64() internal view returns (int64) { + return int64(uint64(kevm.freshUInt(8))); + } + + function freshSInt56() internal view returns (int56) { + return int56(uint56(kevm.freshUInt(7))); + } + + function freshSInt48() internal view returns (int48) { + return int48(uint48(kevm.freshUInt(6))); + } + + function freshSInt40() internal view returns (int40) { + return int40(uint40(kevm.freshUInt(5))); + } + + function freshSInt32() internal view returns (int32) { + return int32(uint32(kevm.freshUInt(4))); + } + + function freshSInt24() internal view returns (int24) { + return int24(uint24(kevm.freshUInt(3))); + } + + function freshSInt16() internal view returns (int16) { + return int16(uint16(kevm.freshUInt(2))); + } + + function freshSInt8() internal view returns (int8) { + return int8(uint8((kevm.freshUInt(1)))); + } + + function freshUInt256(string memory var_name) internal view returns (uint256) { + return kevm.freshUInt(32, var_name); + } + + function freshUInt248(string memory var_name) internal view returns (uint248) { + return uint248(kevm.freshUInt(31, var_name)); + } + + function freshUInt240(string memory var_name) internal view returns (uint240) { + return uint240(kevm.freshUInt(30, var_name)); + } + + function freshUInt232(string memory var_name) internal view returns (uint232) { + return uint232(kevm.freshUInt(29, var_name)); + } + + function freshUInt224(string memory var_name) internal view returns (uint224) { + return uint224(kevm.freshUInt(28, var_name)); + } + + function freshUInt216(string memory var_name) internal view returns (uint216) { + return uint216(kevm.freshUInt(27, var_name)); + } + + function freshUInt208(string memory var_name) internal view returns (uint208) { + return uint208(kevm.freshUInt(26, var_name)); + } + + function freshUInt200(string memory var_name) internal view returns (uint200) { + return uint200(kevm.freshUInt(25, var_name)); + } + + function freshUInt192(string memory var_name) internal view returns (uint192) { + return uint192(kevm.freshUInt(24, var_name)); + } + + function freshUInt184(string memory var_name) internal view returns (uint184) { + return uint184(kevm.freshUInt(23, var_name)); + } + + function freshUInt176(string memory var_name) internal view returns (uint176) { + return uint176(kevm.freshUInt(22, var_name)); + } + + function freshUInt168(string memory var_name) internal view returns (uint168) { + return uint168(kevm.freshUInt(21, var_name)); + } + + function freshUInt160(string memory var_name) internal view returns (uint160) { + return uint160(kevm.freshUInt(20, var_name)); + } + + function freshUInt152(string memory var_name) internal view returns (uint152) { + return uint152(kevm.freshUInt(19, var_name)); + } + + function freshUInt144(string memory var_name) internal view returns (uint144) { + return uint144(kevm.freshUInt(18, var_name)); + } + + function freshUInt136(string memory var_name) internal view returns (uint136) { + return uint136(kevm.freshUInt(17, var_name)); + } + + function freshUInt128(string memory var_name) internal view returns (uint128) { + return uint128(kevm.freshUInt(16, var_name)); + } + + function freshUInt120(string memory var_name) internal view returns (uint120) { + return uint120(kevm.freshUInt(15, var_name)); + } + + function freshUInt112(string memory var_name) internal view returns (uint112) { + return uint112(kevm.freshUInt(14, var_name)); + } + + function freshUInt104(string memory var_name) internal view returns (uint104) { + return uint104(kevm.freshUInt(13, var_name)); + } + + function freshUInt96(string memory var_name) internal view returns (uint96) { + return uint96(kevm.freshUInt(12, var_name)); + } + + function freshUInt88(string memory var_name) internal view returns (uint88) { + return uint88(kevm.freshUInt(11, var_name)); + } + + function freshUInt80(string memory var_name) internal view returns (uint80) { + return uint80(kevm.freshUInt(10, var_name)); + } + + function freshUInt72(string memory var_name) internal view returns (uint72) { + return uint72(kevm.freshUInt(9, var_name)); + } + + function freshUInt64(string memory var_name) internal view returns (uint64) { + return uint64(kevm.freshUInt(8, var_name)); + } + + function freshUInt56(string memory var_name) internal view returns (uint56) { + return uint56(kevm.freshUInt(7, var_name)); + } + + function freshUInt48(string memory var_name) internal view returns (uint48) { + return uint48(kevm.freshUInt(6, var_name)); + } + + function freshUInt40(string memory var_name) internal view returns (uint40) { + return uint40(kevm.freshUInt(5, var_name)); + } + + function freshUInt32(string memory var_name) internal view returns (uint32) { + return uint32(kevm.freshUInt(4, var_name)); + } + + function freshUInt24(string memory var_name) internal view returns (uint24) { + return uint24(kevm.freshUInt(3, var_name)); + } + + function freshUInt16(string memory var_name) internal view returns (uint16) { + return uint16(kevm.freshUInt(2, var_name)); + } + + function freshUInt8(string memory var_name) internal view returns (uint8) { + return uint8(kevm.freshUInt(1, var_name)); + } + + function freshAddress(string memory var_name) internal view returns (address) { + return address(uint160(kevm.freshUInt(20, var_name))); + } + + function freshSInt256(string memory var_name) internal view returns (int256) { + return int256(kevm.freshUInt(32, var_name)); + } + + function freshSInt248(string memory var_name) internal view returns (int248) { + return int248(uint248(kevm.freshUInt(31, var_name))); + } + + function freshSInt240(string memory var_name) internal view returns (int240) { + return int240(uint240(kevm.freshUInt(30, var_name))); + } + + function freshSInt232(string memory var_name) internal view returns (int232) { + return int232(uint232(kevm.freshUInt(29, var_name))); + } + + function freshSInt224(string memory var_name) internal view returns (int224) { + return int224(uint224(kevm.freshUInt(28, var_name))); + } + + function freshSInt216(string memory var_name) internal view returns (int216) { + return int216(uint216(kevm.freshUInt(27, var_name))); + } + + function freshSInt208(string memory var_name) internal view returns (int208) { + return int208(uint208(kevm.freshUInt(26, var_name))); + } + + function freshSInt200(string memory var_name) internal view returns (int200) { + return int200(uint200(kevm.freshUInt(25, var_name))); + } + + function freshSInt192(string memory var_name) internal view returns (int192) { + return int192(uint192(kevm.freshUInt(24, var_name))); + } + + function freshSInt184(string memory var_name) internal view returns (int184) { + return int184(uint184(kevm.freshUInt(23, var_name))); + } + + function freshSInt176(string memory var_name) internal view returns (int176) { + return int176(uint176(kevm.freshUInt(22, var_name))); + } + + function freshSInt168(string memory var_name) internal view returns (int168) { + return int168(uint168(kevm.freshUInt(21, var_name))); + } + + function freshSInt160(string memory var_name) internal view returns (int160) { + return int160(uint160(kevm.freshUInt(20, var_name))); + } + + function freshSInt152(string memory var_name) internal view returns (int152) { + return int152(uint152(kevm.freshUInt(19, var_name))); + } + + function freshSInt144(string memory var_name) internal view returns (int144) { + return int144(uint144(kevm.freshUInt(18, var_name))); + } + + function freshSInt136(string memory var_name) internal view returns (int136) { + return int136(uint136(kevm.freshUInt(17, var_name))); + } + + function freshSInt128(string memory var_name) internal view returns (int128) { + return int128(uint128(kevm.freshUInt(16, var_name))); + } + + function freshSInt120(string memory var_name) internal view returns (int120) { + return int120(uint120(kevm.freshUInt(15, var_name))); + } + + function freshSInt112(string memory var_name) internal view returns (int112) { + return int112(uint112(kevm.freshUInt(14, var_name))); + } + + function freshSInt104(string memory var_name) internal view returns (int104) { + return int104(uint104(kevm.freshUInt(13, var_name))); + } + + function freshSInt96(string memory var_name) internal view returns (int96) { + return int96(uint96(kevm.freshUInt(12, var_name))); + } + + function freshSInt88(string memory var_name) internal view returns (int88) { + return int88(uint88(kevm.freshUInt(11, var_name))); + } + + function freshSInt80(string memory var_name) internal view returns (int80) { + return int80(uint80(kevm.freshUInt(10, var_name))); + } + + function freshSInt72(string memory var_name) internal view returns (int72) { + return int72(uint72(kevm.freshUInt(9, var_name))); + } + + function freshSInt64(string memory var_name) internal view returns (int64) { + return int64(uint64(kevm.freshUInt(8, var_name))); + } + + function freshSInt56(string memory var_name) internal view returns (int56) { + return int56(uint56(kevm.freshUInt(7, var_name))); + } + + function freshSInt48(string memory var_name) internal view returns (int48) { + return int48(uint48(kevm.freshUInt(6, var_name))); + } + + function freshSInt40(string memory var_name) internal view returns (int40) { + return int40(uint40(kevm.freshUInt(5, var_name))); + } + + function freshSInt32(string memory var_name) internal view returns (int32) { + return int32(uint32(kevm.freshUInt(4, var_name))); + } + + function freshSInt24(string memory var_name) internal view returns (int24) { + return int24(uint24(kevm.freshUInt(3, var_name))); + } + + function freshSInt16(string memory var_name) internal view returns (int16) { + return int16(uint16(kevm.freshUInt(2, var_name))); + } + + function freshSInt8(string memory var_name) internal view returns (int8) { + return int8(uint8((kevm.freshUInt(1, var_name)))); + } +} diff --git a/foundry.toml b/foundry.toml index 27f3dbb..a3f8a2f 100644 --- a/foundry.toml +++ b/foundry.toml @@ -6,12 +6,13 @@ via_ir = true solc_version = "0.8.30" optimizer = true optimizer_runs = 20_000 - +ast = true # halmos needs AST; default profile is what halmos's internal `forge build` uses +dynamic_test_linking = false # halmos can't execute vm.deployCode; keep `new X()` bytecode inline [dependencies] -eth-infinitism-account-abstraction = "0.8.0" +eth-infinitism-account-abstraction = "0.9.0" solady = "0.1.26" -forge-std = "1.11.0" -"@openzeppelin-contracts" = "5.5.0" +forge-std = "1.16.2" +"@openzeppelin-contracts" = "5.7.0" # See more config options https://github.com/foundry-rs/foundry/blob/master/crates/config/README.md#all-options diff --git a/remappings.txt b/remappings.txt index 0130bfe..d4d92fd 100644 --- a/remappings.txt +++ b/remappings.txt @@ -1,4 +1,6 @@ -openzeppelin-contracts/contracts/=dependencies/@openzeppelin-contracts-5.5.0/ -account-abstraction/=dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/ -forge-std/=dependencies/forge-std-1.11.0/src/ +openzeppelin-contracts/contracts/=dependencies/@openzeppelin-contracts-5.7.0/ +account-abstraction/=dependencies/eth-infinitism-account-abstraction-0.9.0/contracts/ +forge-std/=dependencies/forge-std-1.16.2/src/ solady/=dependencies/solady-0.1.26/src/ +halmos-cheatcodes/=dependencies/halmos-cheatcodes/src/ +kontrol-cheatcodes/=dependencies/kontrol-cheatcodes/src/ diff --git a/soldeer.lock b/soldeer.lock index 51ee56e..aac57b8 100644 --- a/soldeer.lock +++ b/soldeer.lock @@ -1,23 +1,23 @@ [[dependencies]] name = "@openzeppelin-contracts" -version = "5.5.0" -url = "https://soldeer-revisions.s3.amazonaws.com/@openzeppelin-contracts/5_5_0_01-11-2025_09:56:40_contracts.zip" -checksum = "2ee78837130cf06b456d9ef7ab70753685d9c1c9c2c5b70f24bd4c16695d0337" -integrity = "da8336cf949f0e0667ae8360af849681e3a3e76d7e61e7a86b1a3414a158aeea" +version = "5.7.0" +url = "https://soldeer-revisions.s3.amazonaws.com/@openzeppelin-contracts/5_7_0_29-07-2026_19:34:46_contracts.zip" +checksum = "fe08a24bc34334b2976c6ad69a0d74bdfa63de8a5c8528579060f25a11fb5cd5" +integrity = "3e13bc4d96bdef6e35f6b1e0dc0e455843a958edc597750dff20ca50295b767d" [[dependencies]] name = "eth-infinitism-account-abstraction" -version = "0.8.0" -url = "https://soldeer-revisions.s3.amazonaws.com/eth-infinitism-account-abstraction/0_8_0_24-03-2025_13:49:05_eth-infinitism-account-abstraction-0.8.zip" -checksum = "305f34048fe928dacefb31a61baecae18eed43959f892d6a1b428eb46bb6afc9" -integrity = "8ffcb24a9c6089aef86df243251501b42928ace5cacfa3e47bb17e521ae67a1b" +version = "0.9.0" +url = "https://soldeer-revisions.s3.amazonaws.com/eth-infinitism-account-abstraction/0_9_0_20-11-2025_00:23:28_eth-infinitism-account-abstraction-0.9.zip" +checksum = "2c10595b73d49df58e02a9413931652e62a6ecf9b9e11f2177392d55783c5a3b" +integrity = "a1e9e10b53563327b0bd696c4030e53d194008cd5ce6e2a3ae2388032cc83666" [[dependencies]] name = "forge-std" -version = "1.11.0" -url = "https://soldeer-revisions.s3.amazonaws.com/forge-std/1_11_0_09-10-2025_06:23:22_forge-std-1.11.zip" -checksum = "0290ef84c693dc9086f98f6a9b4a69dc5c2b6aa1cfe10a989bd1def1a456c099" -integrity = "84aa7d32f8c7329468cf16f31f0f74e68072e634fdbde98f3bb00c6b136103b2" +version = "1.16.2" +url = "https://soldeer-revisions.s3.amazonaws.com/forge-std/1_16_2_03-07-2026_07:37:45_forge-std-1.16.zip" +checksum = "405dccc9d60d753f6abc412b4adf0359f4390f65dbadbbb277a12b4946ed8969" +integrity = "5fb4325b60d7d4194bd0481e2f94398cf1d9c6561dd12a66fb2748ef4a68205f" [[dependencies]] name = "solady" diff --git a/specs/DefaultSecurityHook.spec.md b/specs/DefaultSecurityHook.spec.md new file mode 100644 index 0000000..ea11efc --- /dev/null +++ b/specs/DefaultSecurityHook.spec.md @@ -0,0 +1,135 @@ +--- +title: DefaultSecurityHook — Spec (Invariants / FV trust surface) +project: kernel-7579-plugins +contract: src/hooks/DefaultSecurityHook.sol +branch: feat/restore-dropped-modules +author: taek +--- + +# DefaultSecurityHook — Invariants (FV trust surface) + +> Confirmed by taek on 2026-07-14 via /fv-invariants. This is the trust surface for +> formal verification — sc-formal-verify proves code against THESE claims, nothing else. +> Written to the repo-local `specs/` because `~/Documents/Obsidian` was TCC-blocked from +> the session; sync into `projects/kernel-7579-plugins/specs/` when Documents access is granted. + +## Trusted assumptions (named preconditions) + +All invariants below hold only within these boundaries, confirmed in the completeness pass: + +- **P1 — Honest account.** The ERC-7579 account invokes `preCheck` before executing the + batch/single call and aborts the execution if `preCheck` reverts. A non-conforming account + that skips or ignores the hook bypasses every invariant here. (Off-chain / account-implementation trust.) +- **P2 — Standard execute calldata layout.** `preCheck` decodes `msgData` as + `execute(bytes32 mode, bytes executionData)` via a hardcoded offset (`:112-131`). A different + entrypoint calldata shape mis-decodes; invariants assume the standard layout. +- **P3 — Honest `isModuleType`.** Module detection (`INV-04`) assumes targets implement + `isModuleType` truthfully. Adversarial bytecode that reverts/lies is out of scope — see SG-B. + +## Invariants + +### INV-01 — Blocked token-transfer selectors always revert (unless allowlisted) +A non-allowlisted call carrying any of the 10 blocked ERC-20/721/1155 transfer/approval selectors +reverts `TokenTransferNotAllowed(target, selector)`. +- **Severity:** Critical +- **Source:** code `src/hooks/DefaultSecurityHook.sol:204,214-219` / FV `DSH-ALLOW-01` +- **Form:** observable outcome (exact iff over symbolic `bytes4`; oracle = 10 spec hex literals enumerated independently of `_isBlockedSelector`) +- **Preconditions / trusted assumptions:** P1, P2 +- **Out of FV scope?:** no — **double-proven, TCB-independent** (Halmos + Certora; shared residual solc 0.8.30 via_ir) + +### INV-02 — Delegatecall execution always reverts +Any execution whose call type is `CALLTYPE_DELEGATECALL` reverts `DelegateCallNotAllowed` in `preCheck`. +- **Severity:** High +- **Source:** code `:117-119` +- **Form:** observable outcome +- **Preconditions / trusted assumptions:** P1, P2 +- **Out of FV scope?:** no + +### INV-03 — Self-call reverts +A non-allowlisted call whose `target == msg.sender` (the account) reverts `SelfCallNotAllowed`. +- **Severity:** High +- **Source:** code `:193` +- **Form:** observable outcome +- **Preconditions / trusted assumptions:** P1, P2 +- **Out of FV scope?:** no + +### INV-04 — Call to a module-typed target reverts +A non-allowlisted call to a target for which the `isModuleType` staticcall succeeds reverts +`ModuleCallNotAllowed(target)`. +- **Severity:** High +- **Source:** code `:196,208-212` / FV `DSH-DENY-MODULE-01` +- **Form:** observable outcome (conditional deny branch only) +- **Preconditions / trusted assumptions:** P1, P2, **P3** (heuristic soundness is SG-B, NOT covered by this proof) +- **Out of FV scope?:** no (branch); soundness of the heuristic itself → SG-B (out of scope) + +### INV-05 — ETH transfer to non-allowlisted target reverts +A non-allowlisted, non-self, non-module call with `value > 0` reverts `ETHTransferNotAllowed(target, value)`. +- **Severity:** Medium +- **Source:** code `:199` / FV `DSH-DENY-ETH-01::symbolic-target` +- **Form:** observable outcome +- **Preconditions / trusted assumptions:** P1, P2 +- **Out of FV scope?:** no — proven (symbolic target concretizes to deployed code; codeless targets excluded by the contract itself) + +### INV-06 — Allowlisted (target, selector) bypasses every deny check +If `(msg.sender, target)` is allowlisted and either `allSelectorsAllowed` or the call selector is +in the allowed set, `_checkCall` returns without reverting — no deny check fires. +- **Severity:** High +- **Source:** code `:187-190` +- **Form:** observable outcome (converse of INV-01; proven allowlisted-never-reverts leg of DSH-ALLOW-01) +- **Preconditions / trusted assumptions:** P1, P2 +- **Out of FV scope?:** no + +### INV-07 — Install lifecycle: double-install reverts; management gated on init +`onInstall` on an already-initialized account reverts `AlreadyInitialized`; `setAllowlist` / +`removeAllowlist` revert `Unauthorized` when the caller is not initialized. +- **Severity:** High +- **Source:** code `:79,154,160` / FV legs (a) `DSH-INSTALL-DOUBLE-01`, (b,c) `check_{Set,Remove}AllowlistRevertsWhenUninitialized` +- **Form:** observable outcome +- **Preconditions / trusted assumptions:** none +- **Out of FV scope?:** no — proven (leg a double-install; legs b,c management-gating) +- **Leg (d) — `onUninstall` NotInitialized guard** (`:93`): the symmetric guard that `onUninstall` + on a non-initialized account reverts `NotInitialized`. **Severity Low; Out of FV scope = yes (accepted, + not proven, taek 2026-07-14).** Below the bar where a proof earns its keep — caller is the account, + a broken guard deletes already-empty state (no attacker gain). Trivially provable from the + double-install template if ever wanted. See report SG-G. + +### INV-08 — Uninstall clears all state; no stale-selector leak on re-install +After `onUninstall`, no target remains allowlisted for the account, and no previously-allowed +selector survives to be honored after a later re-install (S-01 stale-selector + S-03 target-cleanup fix). +- **Severity:** High +- **Source:** code `:92-104,229-256` / FV `DSH-REMOVE-ALLOWLIST-01` / Certora S01/S02/S03 +- **Form:** observable outcome (removal restores deny; re-set clears stale selectors) +- **Preconditions / trusted assumptions:** none +- **Out of FV scope?:** no + +### INV-09 — Batch: every element is checked through the real decoder +In a `CALLTYPE_BATCH` execution, `_checkCall` runs on every decoded element; the batch reverts if +any element would revert on the single path — the real `decodeBatch`/`getExecution` calldata decode +introduces no bypass. +- **Severity:** Medium +- **Source:** code `:136-141` / FV `DSH-BATCH-DECODER-01` +- **Form:** observable outcome (iff proven in both directions through the real decoder; closes the + prior Certora `Call[]`-struct-model caveat — decode path now inside the proof, not the TCB) +- **Preconditions / trusted assumptions:** P1, P2 +- **Out of FV scope?:** no — proven (coverage bound: batch length concrete at 2, element values/selectors symbolic) + +## Out-of-FV-scope (recorded, accepted — not proof gaps) + +Naming these is the honest analog of "to be end-to-end you'd have to verify everything." Each was +explicitly accepted by taek on 2026-07-14; none is a covering-claim failure. + +- **SG-A (Medium) — blocklist non-exhaustive.** The 10 blocked selectors do not include ERC-777 + `send`, `transferAndCall` (`0x4000aea0`), EIP-3009 `transferWithAuthorization` (`0xe3ee160e`), or + permit-based pulls — all pass the hook. "Did we enumerate every dangerous selector" is not + FV-decidable. **Accepted as documented scope** (best-effort blocklist; allowlisting is the real + protection). Revisit spec §4.8 + re-run /fv-invariants if the blocklist is expanded. +- **SG-B (Medium) — `_isModule` heuristic soundness.** A target whose `isModuleType` reverts + bypasses the module gate; a benign contract with a permissive fallback is DoS'd. Depends on + arbitrary external bytecode — not FV-decidable. **Accepted; routed to sc-invariant-fuzz-tester** + with adversarial target mocks. INV-04 proves only the conditional branch, not the heuristic. +- **SG-C — flows the hook never sees.** ERC-2612/Permit2/ERC-1271 signature approvals, pre-existing + token approvals, inbound `receive()`/`fallback()` ETH, and `executeFromExecutor` routing are + invisible to `preCheck`. No hook-level covering claim possible. **Accepted trust model** (spec §11.1). +- **SG-D (Low) — blanket-allowlist self/module defeats all protections.** The allowlist-first return + at `:188` precedes every deny check, so allowlisting the account itself or a module with empty + selectors disables protection. **Accepted by design** (owner-trust boundary, spec §5.2/§11.3). diff --git a/src/actions/RecoveryAction.sol b/src/actions/RecoveryAction.sol new file mode 100644 index 0000000..28fda0d --- /dev/null +++ b/src/actions/RecoveryAction.sol @@ -0,0 +1,16 @@ +pragma solidity ^0.8.0; + +import {IValidator} from "src/interfaces/IERC7579Modules.sol"; + +/** + * @title RecoveryAction + * @notice Executor action that re-initializes a validator with new configuration data. + * @dev Called via the account to swap a validator's owner/config by uninstalling then + * reinstalling it in a single call. + */ +contract RecoveryAction { + function doRecovery(address _validator, bytes calldata _data) external { + IValidator(_validator).onUninstall(hex""); + IValidator(_validator).onInstall(_data); + } +} diff --git a/src/base/WeightedThresholdBase.sol b/src/base/WeightedThresholdBase.sol new file mode 100644 index 0000000..c3e0e32 --- /dev/null +++ b/src/base/WeightedThresholdBase.sol @@ -0,0 +1,177 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import {ECDSA} from "solady/utils/ECDSA.sol"; + +/// @title WeightedThresholdBase +/// @author taek +/// @notice Single, shared copy of the weighted-threshold signature-aggregation logic used by +/// both WeightedECDSASigner and WeightedECDSAValidator. Ported verbatim from the +/// (correct, EC-01-fixed) logic that previously lived in WeightedECDSASigner. +/// @dev Weight lookups are indirected through `_guardianWeight` so each adapter can plug in +/// its own storage layout (id-keyed for the signer, single-config for the validator) +/// without duplicating the aggregation invariants. +abstract contract WeightedThresholdBase { + // ZeroWeightSigner() / SignersNotSorted() are declared by each concrete adapter so that + // `.ZeroWeightSigner.selector` resolves in that adapter's test suite (Solidity does + // not expose inherited errors via the derived contract name). The base reverts through the + // hooks below; both hooks MUST revert (the base relies on that to abort aggregation). + + /// @dev Reverts the adapter's ZeroWeightSigner() error. MUST revert. + function _revertZeroWeightSigner() internal pure virtual; + + /// @dev Reverts the adapter's SignersNotSorted() error. MUST revert. + function _revertSignersNotSorted() internal pure virtual; + + /// @notice Returns the weight of `signer` for the given config/account. + /// @param cfg Adapter-specific config key (permission id for the signer, bytes32(0) for the validator). + /// @param account The smart account the guardian set belongs to. + /// @param signer The recovered signer whose weight is requested. + /// @return weight The guardian's weight (0 if not a guardian). + function _guardianWeight(bytes32 cfg, address account, address signer) internal view virtual returns (uint256); + + /// @notice Verify a plain (ERC-1271 style) weighted-threshold signature over a single hash. + /// @dev EXACT mirror of the original WeightedECDSASigner._validateSignature. Signers must be in + /// strictly ASCENDING order; a non-last zero-weight signer REVERTS ZeroWeightSigner; a last + /// zero-weight signer returns false. Threshold reached via `>=`. + /// @return ok True iff the accumulated distinct-signer weight reaches `threshold`. + function _verifySorted(bytes32 cfg, address account, bytes32 hash, bytes calldata sig, uint256 threshold) + internal + view + returns (bool ok) + { + if (threshold == 0) { + return false; + } + + uint256 sigCount = sig.length / 65; + if (sigCount == 0) { + return false; + } + + uint256 totalWeight = 0; + address signer; + address lastSigner = address(0); + + // Process all signatures except the last one + for (uint256 i = 0; i < sigCount - 1; i++) { + signer = ECDSA.tryRecoverCalldata(hash, sig[i * 65:(i + 1) * 65]); + + // Enforce sorted order to prevent signature reuse (EC-01: ordering check BEFORE counting) + if (signer <= lastSigner) { + return false; + } + lastSigner = signer; + + uint256 guardianWeight = _guardianWeight(cfg, account, signer); + // Revert if non-last signer has zero weight (prevents gas griefing) + if (guardianWeight == 0) { + _revertZeroWeightSigner(); + } + totalWeight += guardianWeight; + if (totalWeight >= threshold) { + return true; + } + } + + // Process last signature + signer = ECDSA.tryRecoverCalldata(hash, sig[sig.length - 65:]); + if (signer <= lastSigner) { + return false; + } + uint256 lastWeight = _guardianWeight(cfg, account, signer); + // If last signer has zero weight, return false (don't revert) + if (lastWeight == 0) { + return false; + } + totalWeight += lastWeight; + if (totalWeight >= threshold) { + return true; + } + + return false; + } + + /// @notice Verify a split UserOp weighted-threshold signature. + /// @dev EXACT mirror of the original WeightedECDSASigner._validateUserOpSignature. + /// The first N-1 signatures sign `proposalHash` in strictly ASCENDING order (a non-last + /// zero-weight signer REVERTS ZeroWeightSigner). The LAST signature signs `finalHash` to + /// bind the full UserOp; a last zero-weight signer returns false (no revert). An in-memory + /// de-dup ensures the final signer's weight is counted at most once. Threshold via `>=`. + /// @return ok True iff the accumulated distinct-signer weight reaches `threshold`. + function _verifyUserOp( + bytes32 cfg, + address account, + bytes32 proposalHash, + bytes32 finalHash, + bytes calldata sig, + uint256 threshold + ) internal view returns (bool ok) { + if (threshold == 0) { + return false; + } + + if (sig.length % 65 != 0) { + return false; + } + + uint256 sigCount = sig.length / 65; + if (sigCount == 0) { + return false; + } + + uint256 totalWeight = 0; + address signer; + address lastSigner = address(0); + + // Track proposalHash signers to prevent double-counting with the finalHash signer + address[] memory proposalSigners = new address[](sigCount - 1); + + // Process all signatures except the last one (they sign proposalHash) + // Signers must be in strictly ascending order to prevent reuse + // NOTE: No early return - must always verify the finalHash signature + for (uint256 i = 0; i < sigCount - 1; i++) { + signer = ECDSA.tryRecoverCalldata(proposalHash, sig[i * 65:(i + 1) * 65]); + + // Enforce sorted order to prevent signature reuse (EC-01: ordering check BEFORE counting) + if (signer <= lastSigner) { + _revertSignersNotSorted(); + } + lastSigner = signer; + proposalSigners[i] = signer; + + uint256 guardianWeight = _guardianWeight(cfg, account, signer); + // Revert if non-last signer has zero weight (prevents gas griefing) + if (guardianWeight == 0) { + _revertZeroWeightSigner(); + } + totalWeight += guardianWeight; + // No early return here - must verify finalHash signature + } + + // Last signature MUST verify finalHash to bind the full userOp + signer = ECDSA.tryRecoverCalldata(finalHash, sig[sig.length - 65:]); + + uint256 lastWeight = _guardianWeight(cfg, account, signer); + // If last signer has zero weight, return false (don't revert) + if (lastWeight == 0) { + return false; + } + + // Check if finalHash signer already signed proposalHash (prevent double-counting) + bool alreadySigned = false; + for (uint256 i = 0; i < proposalSigners.length; i++) { + if (proposalSigners[i] == signer) { + alreadySigned = true; + break; + } + } + + // Only add weight if signer hasn't already contributed via proposalHash + if (!alreadySigned) { + totalWeight += lastWeight; + } + + return totalWeight >= threshold; + } +} diff --git a/src/hooks/DefaultSecurityHook.sol b/src/hooks/DefaultSecurityHook.sol new file mode 100644 index 0000000..d65bddc --- /dev/null +++ b/src/hooks/DefaultSecurityHook.sol @@ -0,0 +1,261 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import {IHook, IModule} from "src/interfaces/IERC7579Modules.sol"; +import {MODULE_TYPE_HOOK} from "src/types/Constants.sol"; +import {LibERC7579} from "solady/accounts/LibERC7579.sol"; +import {IERC20} from "openzeppelin-contracts/contracts/token/ERC20/IERC20.sol"; +import {IERC721} from "openzeppelin-contracts/contracts/token/ERC721/IERC721.sol"; +import {IERC1155} from "openzeppelin-contracts/contracts/token/ERC1155/IERC1155.sol"; + +/// @title DefaultSecurityHook +/// @notice A default security hook for ERC-7579 smart accounts that blocks dangerous operations +/// by default and provides a per-account (target, selector[]) allowlisting mechanism. +/// @author taek +contract DefaultSecurityHook is IHook { + // ========== Errors ========== + + error DelegateCallNotAllowed(); + error SelfCallNotAllowed(); + error ModuleCallNotAllowed(address target); + error ETHTransferNotAllowed(address target, uint256 value); + error TokenTransferNotAllowed(address target, bytes4 selector); + error Unauthorized(); + error UnsupportedCallType(); + + // ========== Events ========== + + event AllowlistSet(address indexed account, address indexed target, bytes4[] selectors); + event AllowlistRemoved(address indexed account, address indexed target); + event Initialized(address indexed account); + event Uninitialized(address indexed account); + + // ========== Types ========== + + struct AllowlistConfig { + address target; + bytes4[] selectors; + } + + struct AllowlistEntry { + bool allowed; + bool allSelectorsAllowed; + bytes4[] selectorList; + mapping(bytes4 => bool) selectors; + } + + // ========== Storage ========== + + mapping(address account => mapping(address target => AllowlistEntry)) internal allowlist; + mapping(address account => address[]) internal allowlistedTargets; + mapping(address account => bool) internal initialized; + + // ========== Blocked Selectors ========== + + // ERC-20 + bytes4 internal constant TRANSFER = IERC20.transfer.selector; + bytes4 internal constant APPROVE = IERC20.approve.selector; + bytes4 internal constant TRANSFER_FROM = IERC20.transferFrom.selector; + bytes4 internal constant INCREASE_ALLOWANCE = bytes4(keccak256("increaseAllowance(address,uint256)")); + bytes4 internal constant DECREASE_ALLOWANCE = bytes4(keccak256("decreaseAllowance(address,uint256)")); + + // ERC-721 (unique selectors not already covered above) + // safeTransferFrom is overloaded in IERC721, so we compute selectors from signatures directly + bytes4 internal constant SAFE_TRANSFER_FROM = bytes4(keccak256("safeTransferFrom(address,address,uint256)")); + bytes4 internal constant SAFE_TRANSFER_FROM_WITH_DATA = + bytes4(keccak256("safeTransferFrom(address,address,uint256,bytes)")); + bytes4 internal constant SET_APPROVAL_FOR_ALL = IERC721.setApprovalForAll.selector; + + // ERC-1155 + bytes4 internal constant SAFE_TRANSFER_FROM_1155 = IERC1155.safeTransferFrom.selector; + bytes4 internal constant SAFE_BATCH_TRANSFER_FROM = IERC1155.safeBatchTransferFrom.selector; + + // Gas stipend for isModuleType static call + uint256 internal constant MODULE_CHECK_GAS = 30_000; + + // ========== IModule ========== + + function onInstall(bytes calldata data) external payable override { + if (initialized[msg.sender]) revert AlreadyInitialized(msg.sender); + initialized[msg.sender] = true; + + if (data.length > 0) { + AllowlistConfig[] memory configs = abi.decode(data, (AllowlistConfig[])); + for (uint256 i; i < configs.length; i++) { + _setAllowlist(msg.sender, configs[i].target, configs[i].selectors); + } + } + + emit Initialized(msg.sender); + } + + function onUninstall(bytes calldata) external payable override { + if (!initialized[msg.sender]) revert NotInitialized(msg.sender); + + // Clear ALL allowlisted targets for the account + address[] storage targets = allowlistedTargets[msg.sender]; + for (uint256 i; i < targets.length; i++) { + _clearAllowlist(msg.sender, targets[i]); + } + delete allowlistedTargets[msg.sender]; + + initialized[msg.sender] = false; + emit Uninitialized(msg.sender); + } + + function isModuleType(uint256 moduleTypeId) external pure override returns (bool) { + return moduleTypeId == MODULE_TYPE_HOOK; + } + + // ========== IHook ========== + + function preCheck(address, uint256, bytes calldata msgData) external payable override returns (bytes memory) { + // msgData layout: [0:4] execute selector, [4:36] mode, [36:..] executionData + bytes32 mode = bytes32(msgData[4:36]); + bytes1 callType = LibERC7579.getCallType(mode); + + if (callType == LibERC7579.CALLTYPE_DELEGATECALL) { + revert DelegateCallNotAllowed(); + } + + // Extract executionData from the ABI-encoded msgData + // msgData[4:] is (bytes32 mode, bytes executionData) + // The bytes param is ABI-encoded with an offset at [36:68] then length + data + bytes calldata executionData; + assembly { + let offsetPos := add(msgData.offset, 36) + let offset := calldataload(offsetPos) + let dataStart := add(add(msgData.offset, 4), offset) + executionData.length := calldataload(dataStart) + executionData.offset := add(dataStart, 0x20) + } + + if (callType == LibERC7579.CALLTYPE_SINGLE) { + (address target, uint256 value, bytes calldata data) = LibERC7579.decodeSingle(executionData); + _checkCall(target, value, data); + } else if (callType == LibERC7579.CALLTYPE_BATCH) { + bytes32[] calldata pointers = LibERC7579.decodeBatch(executionData); + for (uint256 i; i < pointers.length; i++) { + (address target, uint256 value, bytes calldata data) = LibERC7579.getExecution(pointers, i); + _checkCall(target, value, data); + } + } else { + revert UnsupportedCallType(); + } + + return hex""; + } + + function postCheck(bytes calldata) external payable override {} + + // ========== Allowlist Management ========== + + function setAllowlist(address target, bytes4[] calldata selectors) external { + if (!initialized[msg.sender]) revert Unauthorized(); + _setAllowlist(msg.sender, target, selectors); + emit AllowlistSet(msg.sender, target, selectors); + } + + function removeAllowlist(address target) external { + if (!initialized[msg.sender]) revert Unauthorized(); + _clearAllowlist(msg.sender, target); + emit AllowlistRemoved(msg.sender, target); + } + + // ========== View ========== + + function isInitialized(address account) external view returns (bool) { + return initialized[account]; + } + + function isAllowlisted(address account, address target) external view returns (bool) { + return allowlist[account][target].allowed; + } + + function isSelectorAllowed(address account, address target, bytes4 selector) external view returns (bool) { + AllowlistEntry storage entry = allowlist[account][target]; + if (!entry.allowed) return false; + if (entry.allSelectorsAllowed) return true; + return entry.selectors[selector]; + } + + // ========== Internal ========== + + function _checkCall(address target, uint256 value, bytes calldata data) internal view { + // Check allowlist first + AllowlistEntry storage entry = allowlist[msg.sender][target]; + if (entry.allowed) { + if (entry.allSelectorsAllowed) return; + if (data.length >= 4 && entry.selectors[bytes4(data[:4])]) return; + } + + // Self-call check + if (target == msg.sender) revert SelfCallNotAllowed(); + + // Module check + if (_isModule(target)) revert ModuleCallNotAllowed(target); + + // ETH transfer check + if (value > 0) revert ETHTransferNotAllowed(target, value); + + // Blocked selector check + if (data.length >= 4) { + bytes4 selector = bytes4(data[:4]); + if (_isBlockedSelector(selector)) revert TokenTransferNotAllowed(target, selector); + } + } + + function _isModule(address target) internal view returns (bool) { + (bool success,) = + target.staticcall{gas: MODULE_CHECK_GAS}(abi.encodeWithSelector(IModule.isModuleType.selector, uint256(0))); + return success; + } + + function _isBlockedSelector(bytes4 selector) internal pure returns (bool) { + return selector == TRANSFER || selector == APPROVE || selector == TRANSFER_FROM + || selector == INCREASE_ALLOWANCE || selector == DECREASE_ALLOWANCE || selector == SAFE_TRANSFER_FROM + || selector == SAFE_TRANSFER_FROM_WITH_DATA || selector == SET_APPROVAL_FOR_ALL + || selector == SAFE_TRANSFER_FROM_1155 || selector == SAFE_BATCH_TRANSFER_FROM; + } + + function _setAllowlist(address account, address target, bytes4[] memory selectors) internal { + AllowlistEntry storage entry = allowlist[account][target]; + + // Track target for cleanup on uninstall (S-03) + if (!entry.allowed) { + allowlistedTargets[account].push(target); + } + + // Clear stale selectors from the mapping (S-01) + bytes4[] storage oldSelectors = entry.selectorList; + for (uint256 i; i < oldSelectors.length; i++) { + entry.selectors[oldSelectors[i]] = false; + } + delete entry.selectorList; + + entry.allowed = true; + if (selectors.length == 0) { + entry.allSelectorsAllowed = true; + } else { + entry.allSelectorsAllowed = false; + for (uint256 i; i < selectors.length; i++) { + entry.selectors[selectors[i]] = true; + entry.selectorList.push(selectors[i]); + } + } + } + + function _clearAllowlist(address account, address target) internal { + AllowlistEntry storage entry = allowlist[account][target]; + + // Clear all tracked selectors from the mapping + bytes4[] storage oldSelectors = entry.selectorList; + for (uint256 i; i < oldSelectors.length; i++) { + entry.selectors[oldSelectors[i]] = false; + } + delete entry.selectorList; + + entry.allowed = false; + entry.allSelectorsAllowed = false; + } +} diff --git a/src/policies/GasPolicy.sol b/src/policies/GasPolicy.sol new file mode 100644 index 0000000..5b8a56e --- /dev/null +++ b/src/policies/GasPolicy.sol @@ -0,0 +1,80 @@ +pragma solidity ^0.8.0; + +import {PackedUserOperation} from "account-abstraction/interfaces/PackedUserOperation.sol"; +import {PolicyBase} from "src/base/PolicyBase.sol"; +import {SIG_VALIDATION_SUCCESS_UINT, SIG_VALIDATION_FAILED_UINT} from "src/types/Constants.sol"; + +enum Status { + NA, + Live, + Deprecated +} + +struct GasPolicyConfig { + uint128 allowed; + bool enforcePaymaster; + address allowedPaymaster; +} + +/** + * @title GasPolicy + * @notice Caps the cumulative gas cost a permission may spend, optionally restricted to a paymaster. + * @dev Per-(id, wallet) budget decremented on each user operation. + */ +contract GasPolicy is PolicyBase { + error PolicyNotLive(); + error PolicyAlreadyInstalled(); + + mapping(bytes32 id => mapping(address => Status)) public status; + mapping(bytes32 id => mapping(address => GasPolicyConfig)) public gasPolicyConfig; + + function checkUserOpPolicy(bytes32 id, PackedUserOperation calldata userOp) + external + payable + override + returns (uint256) + { + require(status[id][msg.sender] == Status.Live, PolicyNotLive()); + (uint256 verificationGasLimit, uint256 callGasLimit) = + (uint128(bytes16(userOp.accountGasLimits)), uint128(uint256(userOp.accountGasLimits))); + uint256 maxFeePerGas = uint128(uint256(userOp.gasFees)); + uint256 maxAmount = (userOp.preVerificationGas + verificationGasLimit + callGasLimit) * maxFeePerGas; + if (gasPolicyConfig[id][msg.sender].enforcePaymaster) { + address allowedPaymaster = gasPolicyConfig[id][msg.sender].allowedPaymaster; + if ( + allowedPaymaster != address(0) + && (userOp.paymasterAndData.length < 20 + || address(bytes20(userOp.paymasterAndData[0:20])) != allowedPaymaster) + ) { + return SIG_VALIDATION_FAILED_UINT; + } + } + if (maxAmount > gasPolicyConfig[id][msg.sender].allowed) { + return SIG_VALIDATION_FAILED_UINT; + } + gasPolicyConfig[id][msg.sender].allowed = uint128(gasPolicyConfig[id][msg.sender].allowed - maxAmount); + return SIG_VALIDATION_SUCCESS_UINT; + } + + function checkSignaturePolicy(bytes32 id, address, bytes32, bytes calldata) + external + view + override + returns (uint256) + { + require(status[id][msg.sender] == Status.Live, PolicyNotLive()); + return SIG_VALIDATION_SUCCESS_UINT; + } + + function _policyOninstall(bytes32 id, bytes calldata _data) internal override { + require(status[id][msg.sender] == Status.NA, PolicyAlreadyInstalled()); + (uint128 allowed, bool enforcePaymaster, address allowedPaymaster) = abi.decode(_data, (uint128, bool, address)); + gasPolicyConfig[id][msg.sender] = GasPolicyConfig(allowed, enforcePaymaster, allowedPaymaster); + status[id][msg.sender] = Status.Live; + } + + function _policyOnUninstall(bytes32 id, bytes calldata) internal override { + require(status[id][msg.sender] == Status.Live, PolicyNotLive()); + status[id][msg.sender] = Status.Deprecated; + } +} diff --git a/src/policies/RateLimitPolicy.sol b/src/policies/RateLimitPolicy.sol new file mode 100644 index 0000000..17748b5 --- /dev/null +++ b/src/policies/RateLimitPolicy.sol @@ -0,0 +1,105 @@ +pragma solidity ^0.8.0; + +import {PackedUserOperation} from "account-abstraction/interfaces/PackedUserOperation.sol"; +import {PolicyBase} from "src/base/PolicyBase.sol"; +import {SIG_VALIDATION_SUCCESS_UINT} from "src/types/Constants.sol"; +import {packValidationData, ValidAfter, ValidUntil} from "src/types/Types.sol"; + +enum Status { + NA, + Live, + Deprecated +} + +/// @notice Configuration for the fixed-window rate limiter. +struct RateLimitConfig { + uint48 interval; // Time window in seconds. + uint48 initialCount; // Maximum number of operations allowed in each window. +} + +/// @notice The current state for the fixed-window rate limiter. +struct RateLimitState { + uint48 storedCount; // Remaining allowed operations in the current window. + uint48 resetDate; // Timestamp at which the current window ends. +} + +/** + * @title RateLimitPolicy + * @notice Allows up to `initialCount` user operations per `interval`, refilling each window. + * @dev When the window elapses the counter resets to `initialCount` and the window is pushed forward. + */ +contract RateLimitPolicy is PolicyBase { + error RateLimited(); + error PolicyNotLive(); + error PolicyAlreadyInstalled(); + error InvalidInstallData(); + + mapping(bytes32 id => mapping(address => Status)) public status; + /// @notice Maps each policy id and wallet to its rate limiting configuration. + mapping(bytes32 => mapping(address => RateLimitConfig)) public rateLimitConfigs; + /// @notice Maps each policy id and wallet to its current rate limiting state. + mapping(bytes32 => mapping(address => RateLimitState)) public rateLimitState; + + /// @notice Installs the policy with encoded configuration data. + /// @dev Expects `_data` to be at least 12 bytes: + /// - first 6 bytes: uint48 interval, + /// - next 6 bytes: uint48 initialCount. + function _policyOninstall(bytes32 id, bytes calldata _data) internal override { + require(status[id][msg.sender] != Status.Live, PolicyAlreadyInstalled()); + require(_data.length >= 12, InvalidInstallData()); + uint48 interval = uint48(bytes6(_data[0:6])); + uint48 initialCount = uint48(bytes6(_data[6:12])); + rateLimitConfigs[id][msg.sender] = RateLimitConfig(interval, initialCount); + + // Initialize the state: set storedCount to initialCount and resetDate to now + interval. + rateLimitState[id][msg.sender] = + RateLimitState({storedCount: initialCount, resetDate: uint48(block.timestamp) + interval}); + + status[id][msg.sender] = Status.Live; + } + + function _policyOnUninstall(bytes32 id, bytes calldata) internal override { + require(status[id][msg.sender] == Status.Live, PolicyNotLive()); + status[id][msg.sender] = Status.Deprecated; + } + + /// @notice Checks the policy for a user operation. + /// If the current time has passed the resetDate, it resets storedCount and resetDate. + /// Then it decrements storedCount if there is quota remaining. + function checkUserOpPolicy( + bytes32 id, + PackedUserOperation calldata /*userOp*/ + ) + external + payable + override + returns (uint256) + { + RateLimitConfig storage config = rateLimitConfigs[id][msg.sender]; + RateLimitState storage state = rateLimitState[id][msg.sender]; + uint48 currentTime = uint48(block.timestamp); + + // Reset the counter if the current time has passed the window's resetDate. + if (currentTime >= state.resetDate) { + state.storedCount = config.initialCount; + state.resetDate = currentTime + config.interval; + } + + require(state.storedCount > 0, RateLimited()); + // Decrement the allowed count. + state.storedCount--; + + // Return validation data: current time and next reset date. + return packValidationData(ValidAfter.wrap(currentTime), ValidUntil.wrap(state.resetDate)); + } + + /// @notice No signature validation is required for this policy. + function checkSignaturePolicy(bytes32 id, address, bytes32, bytes calldata) + external + view + override + returns (uint256) + { + return SIG_VALIDATION_SUCCESS_UINT; + } +} diff --git a/src/policies/SudoPolicy.sol b/src/policies/SudoPolicy.sol new file mode 100644 index 0000000..7517e7d --- /dev/null +++ b/src/policies/SudoPolicy.sol @@ -0,0 +1,25 @@ +pragma solidity ^0.8.0; + +import {PackedUserOperation} from "account-abstraction/interfaces/PackedUserOperation.sol"; +import {PolicyBase} from "src/base/PolicyBase.sol"; +import {SIG_VALIDATION_SUCCESS_UINT} from "src/types/Constants.sol"; + +/** + * @title SudoPolicy + * @notice A policy that unconditionally approves every user operation and signature. + * @dev Grants unrestricted permission — pair with other policies only when a permission + * genuinely needs no additional constraints. + */ +contract SudoPolicy is PolicyBase { + function checkUserOpPolicy(bytes32, PackedUserOperation calldata) external payable override returns (uint256) { + return SIG_VALIDATION_SUCCESS_UINT; + } + + function checkSignaturePolicy(bytes32, address, bytes32, bytes calldata) external view override returns (uint256) { + return SIG_VALIDATION_SUCCESS_UINT; + } + + function _policyOninstall(bytes32, bytes calldata) internal override {} + + function _policyOnUninstall(bytes32, bytes calldata) internal override {} +} diff --git a/src/policies/ThrottlePolicy.sol b/src/policies/ThrottlePolicy.sol new file mode 100644 index 0000000..252664f --- /dev/null +++ b/src/policies/ThrottlePolicy.sol @@ -0,0 +1,70 @@ +pragma solidity ^0.8.0; + +import {PackedUserOperation} from "account-abstraction/interfaces/PackedUserOperation.sol"; +import {PolicyBase} from "src/base/PolicyBase.sol"; +import {SIG_VALIDATION_SUCCESS_UINT, SIG_VALIDATION_FAILED_UINT} from "src/types/Constants.sol"; +import {packValidationData, ValidAfter, ValidUntil} from "src/types/Types.sol"; + +enum Status { + NA, + Live, + Deprecated +} + +struct ThrottleConfig { + uint48 interval; + uint48 count; + ValidAfter startAt; +} + +/** + * @title ThrottlePolicy + * @notice Limits a permission to a fixed budget of `count` user operations, each spaced at least + * `interval` apart. The budget does not refill. + * @dev Each accepted op decrements the remaining count and pushes the next allowed timestamp + * forward by `interval`, returned as `validAfter`. + */ +contract ThrottlePolicy is PolicyBase { + error PolicyNotLive(); + error PolicyAlreadyInstalled(); + + mapping(bytes32 id => mapping(address => Status)) public status; + mapping(bytes32 id => mapping(address kernel => ThrottleConfig)) public throttleConfigs; + + function checkUserOpPolicy(bytes32 id, PackedUserOperation calldata) external payable override returns (uint256) { + require(status[id][msg.sender] == Status.Live, PolicyNotLive()); + ThrottleConfig memory config = throttleConfigs[id][msg.sender]; + if (config.count == 0) { + return SIG_VALIDATION_FAILED_UINT; + } + uint48 storedStart = ValidAfter.unwrap(config.startAt); + uint48 anchored = uint48(block.timestamp) > storedStart ? uint48(block.timestamp) : storedStart; + throttleConfigs[id][msg.sender].count = config.count - 1; + throttleConfigs[id][msg.sender].startAt = ValidAfter.wrap(anchored + config.interval); + return packValidationData(config.startAt, ValidUntil.wrap(0)); + } + + function checkSignaturePolicy(bytes32 id, address, bytes32, bytes calldata) + external + view + override + returns (uint256) + { + require(status[id][msg.sender] == Status.Live, PolicyNotLive()); + return SIG_VALIDATION_SUCCESS_UINT; + } + + function _policyOninstall(bytes32 id, bytes calldata _data) internal override { + require(status[id][msg.sender] == Status.NA, PolicyAlreadyInstalled()); + uint48 interval = uint48(bytes6(_data[0:6])); + uint48 count = uint48(bytes6(_data[6:12])); + uint48 startAt = uint48(bytes6(_data[12:18])); + throttleConfigs[id][msg.sender] = ThrottleConfig(interval, count, ValidAfter.wrap(startAt)); + status[id][msg.sender] = Status.Live; + } + + function _policyOnUninstall(bytes32 id, bytes calldata) internal override { + require(status[id][msg.sender] == Status.Live, PolicyNotLive()); + status[id][msg.sender] = Status.Deprecated; + } +} diff --git a/src/signers/P256Signer.sol b/src/signers/P256Signer.sol new file mode 100644 index 0000000..5bedf92 --- /dev/null +++ b/src/signers/P256Signer.sol @@ -0,0 +1,120 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.20; + +import {IModule, IStatelessValidator, IStatelessValidatorWithSender} from "src/interfaces/IERC7579Modules.sol"; +import {SignerBase} from "src/base/SignerBase.sol"; +import {PackedUserOperation} from "account-abstraction/interfaces/PackedUserOperation.sol"; +import { + MODULE_TYPE_SIGNER, + MODULE_TYPE_STATELESS_VALIDATOR, + MODULE_TYPE_STATELESS_VALIDATOR_WITH_SENDER, + SIG_VALIDATION_SUCCESS_UINT, + SIG_VALIDATION_FAILED_UINT, + ERC1271_MAGICVALUE, + ERC1271_INVALID +} from "src/types/Constants.sol"; +import {P256Validation} from "src/utils/P256Validation.sol"; + +struct P256SignerData { + uint256 pubKeyX; + uint256 pubKeyY; +} + +/// @title P256Signer +/// @author taek +/// @notice Permission signer for raw P-256 signatures, including stateless dispatch. +/// @dev Requires the RIP-7212 / EIP-7951 precompile at address 0x100. +contract P256Signer is SignerBase, IStatelessValidator, IStatelessValidatorWithSender { + error InvalidDataLength(); + error InvalidPublicKey(); + error P256PrecompileNotAvailable(); + + event PublicKeyRegistered(address indexed account, bytes32 indexed id, uint256 x, uint256 y); + event PublicKeyRemoved(address indexed account, bytes32 indexed id); + + mapping(bytes32 id => mapping(address account => P256SignerData)) public p256SignerStorage; + + constructor() { + if (!P256Validation.isPrecompileAvailable()) revert P256PrecompileNotAvailable(); + } + + function isModuleType(uint256 typeID) external pure override(IModule, SignerBase) returns (bool) { + return typeID == MODULE_TYPE_SIGNER || typeID == MODULE_TYPE_STATELESS_VALIDATOR + || typeID == MODULE_TYPE_STATELESS_VALIDATOR_WITH_SENDER; + } + + function isInitialized(bytes32 id, address account) external view returns (bool) { + return _isInitialized(id, account); + } + + function checkUserOpSignature(bytes32 id, PackedUserOperation calldata userOp, bytes32 userOpHash) + external + payable + override + returns (uint256) + { + P256SignerData storage key = p256SignerStorage[id][msg.sender]; + return P256Validation.verify(userOpHash, userOp.signature, key.pubKeyX, key.pubKeyY) + ? SIG_VALIDATION_SUCCESS_UINT + : SIG_VALIDATION_FAILED_UINT; + } + + function checkSignature(bytes32 id, address, bytes32 hash, bytes calldata signature) + external + view + override + returns (bytes4) + { + P256SignerData storage key = p256SignerStorage[id][msg.sender]; + return P256Validation.verify(hash, signature, key.pubKeyX, key.pubKeyY) ? ERC1271_MAGICVALUE : ERC1271_INVALID; + } + + function validateSignatureWithData(bytes32 hash, bytes calldata signature, bytes calldata data) + external + view + override + returns (bool) + { + return _validateStateless(hash, signature, data); + } + + function validateSignatureWithDataWithSender(address, bytes32 hash, bytes calldata signature, bytes calldata data) + external + view + override + returns (bool) + { + return _validateStateless(hash, signature, data); + } + + function _signerOninstall(bytes32 id, bytes calldata data) internal override { + if (_isInitialized(id, msg.sender)) revert AlreadyInitialized(msg.sender); + if (data.length != 64) revert InvalidDataLength(); + + (uint256 x, uint256 y) = abi.decode(data, (uint256, uint256)); + if (!P256Validation.isValidPublicKey(x, y)) revert InvalidPublicKey(); + + p256SignerStorage[id][msg.sender] = P256SignerData(x, y); + emit PublicKeyRegistered(msg.sender, id, x, y); + } + + function _signerOnUninstall(bytes32 id, bytes calldata) internal override { + if (!_isInitialized(id, msg.sender)) revert NotInitialized(msg.sender); + delete p256SignerStorage[id][msg.sender]; + emit PublicKeyRemoved(msg.sender, id); + } + + function _isInitialized(bytes32 id, address account) internal view returns (bool) { + P256SignerData storage key = p256SignerStorage[id][account]; + return key.pubKeyX != 0 || key.pubKeyY != 0; + } + + function _validateStateless(bytes32 hash, bytes calldata signature, bytes calldata data) + internal + view + returns (bool) + { + (uint256 x, uint256 y, bool validKey) = P256Validation.decodePublicKey(data); + return validKey && P256Validation.verify(hash, signature, x, y); + } +} diff --git a/src/signers/WebAuthnSigner.sol b/src/signers/WebAuthnSigner.sol index c41de7d..b95cef8 100644 --- a/src/signers/WebAuthnSigner.sol +++ b/src/signers/WebAuthnSigner.sol @@ -2,11 +2,18 @@ pragma solidity ^0.8.0; -import "src/base/SignerBase.sol"; -import {SIG_VALIDATION_SUCCESS_UINT, SIG_VALIDATION_FAILED_UINT} from "src/types/Constants.sol"; +import {SignerBase} from "src/base/SignerBase.sol"; +import {IModule, IStatelessValidator, IStatelessValidatorWithSender} from "src/interfaces/IERC7579Modules.sol"; +import { + SIG_VALIDATION_SUCCESS_UINT, + SIG_VALIDATION_FAILED_UINT, + MODULE_TYPE_SIGNER, + MODULE_TYPE_STATELESS_VALIDATOR, + MODULE_TYPE_STATELESS_VALIDATOR_WITH_SENDER +} from "src/types/Constants.sol"; import {PackedUserOperation} from "account-abstraction/interfaces/PackedUserOperation.sol"; import {ERC1271_MAGICVALUE, ERC1271_INVALID} from "src/types/Constants.sol"; -import {WebAuthn} from "src/utils/WebAuthn.sol"; +import {WebAuthn} from "solady/utils/WebAuthn.sol"; struct WebAuthnSignerData { uint256 pubKeyX; @@ -17,10 +24,7 @@ struct WebAuthnSignerData { * @title WebAuthnSigner * @notice This signer uses the P256 curve to validate signatures. */ -contract WebAuthnSigner is SignerBase { - // The location of the challenge in the clientDataJSON - uint256 constant CHALLENGE_LOCATION = 23; - +contract WebAuthnSigner is SignerBase, IStatelessValidator, IStatelessValidatorWithSender { // Emitted when a bad key is provided. error InvalidPublicKey(); @@ -31,6 +35,11 @@ contract WebAuthnSigner is SignerBase { // The P256 public keys of a kernel. mapping(bytes32 id => mapping(address kernel => WebAuthnSignerData)) public webAuthnSignerStorage; + function isModuleType(uint256 typeID) external pure override(IModule, SignerBase) returns (bool) { + return typeID == MODULE_TYPE_SIGNER || typeID == MODULE_TYPE_STATELESS_VALIDATOR + || typeID == MODULE_TYPE_STATELESS_VALIDATOR_WITH_SENDER; + } + function isInitialized(address kernel) external view returns (bool) { return _isInitialized(kernel); } @@ -48,7 +57,7 @@ contract WebAuthnSigner is SignerBase { override returns (uint256) { - return _verifySignature(id, msg.sender, userOpHash, userOp.signature); + return _verifySignature(userOpHash, userOp.signature, webAuthnSignerStorage[id][msg.sender]); } /** @@ -60,45 +69,62 @@ contract WebAuthnSigner is SignerBase { override returns (bytes4) { - return _verifySignature(id, msg.sender, hash, sig) == SIG_VALIDATION_SUCCESS_UINT + return _verifySignature(hash, sig, webAuthnSignerStorage[id][msg.sender]) == SIG_VALIDATION_SUCCESS_UINT ? ERC1271_MAGICVALUE : ERC1271_INVALID; } + function validateSignatureWithData(bytes32 hash, bytes calldata signature, bytes calldata data) + external + view + override + returns (bool) + { + return _verifyStatelessSignature(hash, signature, data); + } + + function validateSignatureWithDataWithSender(address, bytes32 hash, bytes calldata signature, bytes calldata data) + external + view + override + returns (bool) + { + return _verifyStatelessSignature(hash, signature, data); + } + /** * @notice Verify a signature. + * @dev `signature` is `abi.encode(authenticatorData, clientDataJSON, challengeLocation, + * responseTypeLocation, r, s)`. + * @dev Virtual to let formal-verification harnesses model only the cryptographic boundary. */ - function _verifySignature(bytes32 id, address account, bytes32 hash, bytes calldata signature) - private + function _verifySignature(bytes32 hash, bytes calldata signature, WebAuthnSignerData memory webAuthnData) + internal view + virtual returns (uint256) { // decode the signature ( bytes memory authenticatorData, string memory clientDataJSON, + uint256 challengeLocation, uint256 responseTypeLocation, uint256 r, - uint256 s, - bool usePrecompiled - ) = abi.decode(signature, (bytes, string, uint256, uint256, uint256, bool)); - - // get the public key from storage - WebAuthnSignerData memory webAuthnData = webAuthnSignerStorage[id][account]; + uint256 s + ) = abi.decode(signature, (bytes, string, uint256, uint256, uint256, uint256)); - // verify the signature using the signature and the public key - bool isValid = WebAuthn.verifySignature( + bool isValid = WebAuthn.verify( abi.encodePacked(hash), - authenticatorData, true, + authenticatorData, clientDataJSON, - CHALLENGE_LOCATION, + challengeLocation, responseTypeLocation, - r, - s, - webAuthnData.pubKeyX, - webAuthnData.pubKeyY, - usePrecompiled + bytes32(r), + bytes32(s), + bytes32(webAuthnData.pubKeyX), + bytes32(webAuthnData.pubKeyY) ); // return the validation data @@ -107,6 +133,17 @@ contract WebAuthnSigner is SignerBase { } return SIG_VALIDATION_FAILED_UINT; } + + function _verifyStatelessSignature(bytes32 hash, bytes calldata signature, bytes calldata data) + private + view + returns (bool) + { + if (data.length != 96) return false; + (WebAuthnSignerData memory webAuthnData,) = abi.decode(data, (WebAuthnSignerData, bytes32)); + if (webAuthnData.pubKeyX == 0 || webAuthnData.pubKeyY == 0) return false; + return _verifySignature(hash, signature, webAuthnData) == SIG_VALIDATION_SUCCESS_UINT; + } /** * @notice Install WebAuthn signer for a kernel account. * @dev The kernel account need to be the `msg.sender`. diff --git a/src/signers/WeightedECDSASigner.sol b/src/signers/WeightedECDSASigner.sol index 5a94b97..5c417c2 100644 --- a/src/signers/WeightedECDSASigner.sol +++ b/src/signers/WeightedECDSASigner.sol @@ -6,6 +6,7 @@ import {ECDSA} from "solady/utils/ECDSA.sol"; import {EIP712} from "solady/utils/EIP712.sol"; import {PackedUserOperation} from "account-abstraction/interfaces/PackedUserOperation.sol"; import {SignerBase} from "src/base/SignerBase.sol"; +import {WeightedThresholdBase} from "src/base/WeightedThresholdBase.sol"; import { ERC1271_MAGICVALUE, ERC1271_INVALID, @@ -30,12 +31,19 @@ struct GuardianStorage { address nextGuardian; } -contract WeightedECDSASigner is EIP712, SignerBase, IStatelessValidator, IStatelessValidatorWithSender { +contract WeightedECDSASigner is + EIP712, + SignerBase, + WeightedThresholdBase, + IStatelessValidator, + IStatelessValidatorWithSender +{ // EIP712 typehash for the Proposal struct bytes32 private constant PROPOSAL_TYPEHASH = keccak256("Proposal(address account,bytes32 id,bytes callData,uint256 nonce)"); error ZeroWeightSigner(); + error SignersNotSorted(); error LengthMismatch(); error EmptyGuardians(); error ZeroThreshold(); @@ -43,9 +51,16 @@ contract WeightedECDSASigner is EIP712, SignerBase, IStatelessValidator, IStatel error ZeroAddressGuardian(); error ZeroWeight(); error GuardianAlreadyEnabled(); - error SignersNotSorted(); error ThresholdExceedsTotalWeight(); + function _revertZeroWeightSigner() internal pure override { + revert ZeroWeightSigner(); + } + + function _revertSignersNotSorted() internal pure override { + revert SignersNotSorted(); + } + mapping(bytes32 id => mapping(address kernel => WeightedECDSASignerStorage)) public weightedStorage; mapping(address guardian => mapping(bytes32 id => mapping(address kernel => GuardianStorage))) public guardian; @@ -103,13 +118,34 @@ contract WeightedECDSASigner is EIP712, SignerBase, IStatelessValidator, IStatel return weightedStorage[id][smartAccount].totalWeight != 0; } + /// @notice Weight lookup for the base aggregation logic (cfg == permission id). + function _guardianWeight(bytes32 cfg, address account, address signer) internal view override returns (uint256) { + return guardian[signer][cfg][account].weight; + } + function checkUserOpSignature(bytes32 id, PackedUserOperation calldata userOp, bytes32 userOpHash) external payable override returns (uint256) { - return _validateUserOpSignature(id, userOp, userOpHash, userOp.signature, msg.sender); + // Split signature scheme: first N-1 sigs over the EIP712 proposalHash, last sig over the + // RAW userOpHash (ep > 0.7). See WeightedThresholdBase._verifyUserOp. + bytes32 proposalHash = _hashTypedData( + keccak256( + abi.encode( + PROPOSAL_TYPEHASH, + userOp.sender, // account address + id, // id + keccak256(userOp.callData), // calldata hash + userOp.nonce // nonce + ) + ) + ); + uint256 threshold = weightedStorage[id][msg.sender].threshold; + return _verifyUserOp(id, msg.sender, proposalHash, userOpHash, userOp.signature, threshold) + ? SIG_VALIDATION_SUCCESS_UINT + : SIG_VALIDATION_FAILED_UINT; } /// @notice Validate an ERC-1271 signature @@ -124,7 +160,8 @@ contract WeightedECDSASigner is EIP712, SignerBase, IStatelessValidator, IStatel override returns (bytes4) { - return _validateSignature(id, hash, sig, msg.sender); + uint256 threshold = weightedStorage[id][msg.sender].threshold; + return _verifySorted(id, msg.sender, hash, sig, threshold) ? ERC1271_MAGICVALUE : ERC1271_INVALID; } function validateSignatureWithData(bytes32 hash, bytes calldata signature, bytes calldata data) @@ -149,176 +186,10 @@ contract WeightedECDSASigner is EIP712, SignerBase, IStatelessValidator, IStatel return _validateStatelessSignature(hash, signature, guardians, weights, threshold); } - // ==================== Internal Shared Logic ==================== - - /** - * @notice Internal function to validate user operation signatures - * @dev Shared logic for both installed and stateless validator modes - * - * SECURITY: Split Signature Scheme - * The first N-1 signatures verify a proposalHash (EIP-712 typed data covering - * account, id, callData, and nonce). The last signature MUST verify the full - * userOpHash to bind the complete UserOp (including gas fields). - * This prevents a scenario where guardians approve a proposal but an attacker - * manipulates gas parameters in the final UserOp. - * A double-counting check ensures a guardian who signed both the proposalHash - * and userOpHash only has their weight counted once. - */ - function _validateUserOpSignature( - bytes32 id, - PackedUserOperation calldata userOp, - bytes32 userOpHash, - bytes calldata sig, - address account - ) internal returns (uint256) { - WeightedECDSASignerStorage storage strg = weightedStorage[id][account]; - if (strg.threshold == 0) { - return SIG_VALIDATION_FAILED_UINT; - } - - // Create EIP712 hash with visible fields: account, id, calldata, nonce - bytes32 proposalHash = _hashTypedData( - keccak256( - abi.encode( - PROPOSAL_TYPEHASH, - userOp.sender, // account address - id, // id - keccak256(userOp.callData), // calldata hash - userOp.nonce // nonce - ) - ) - ); - - if (sig.length % 65 != 0) { - return SIG_VALIDATION_FAILED_UINT; - } - - uint256 sigCount = sig.length / 65; - if (sigCount == 0) { - return SIG_VALIDATION_FAILED_UINT; - } - - uint256 totalWeight = 0; - uint256 threshold = strg.threshold; - address signer; - address lastSigner = address(0); - - // Track proposalHash signers to prevent double-counting with userOpHash signer - address[] memory proposalSigners = new address[](sigCount - 1); - - // Process all signatures except the last one (they sign proposalHash) - // Signers must be in strictly ascending order to prevent reuse - // NOTE: No early return - must always verify userOpHash signature - for (uint256 i = 0; i < sigCount - 1; i++) { - signer = ECDSA.tryRecoverCalldata(proposalHash, sig[i * 65:(i + 1) * 65]); - - // Enforce sorted order to prevent signature reuse - require(signer > lastSigner, SignersNotSorted()); - lastSigner = signer; - proposalSigners[i] = signer; - - uint24 guardianWeight = guardian[signer][id][account].weight; - // Revert if non-last signer has zero weight (prevents gas griefing) - if (guardianWeight == 0) { - revert ZeroWeightSigner(); - } - totalWeight += guardianWeight; - // No early return here - must verify userOpHash signature - } - - // Last signature MUST verify userOpHash to bind the full userOp - // This prevents malleability of gas fields and other userOp parameters - // NOTE: use this with ep > 0.7 only, for ep <= 0.7, need to use toEthSignedMessageHash - signer = ECDSA.tryRecoverCalldata(userOpHash, sig[sig.length - 65:]); - - uint24 lastWeight = guardian[signer][id][account].weight; - // If last signer has zero weight, return validation failed (don't revert) - if (lastWeight == 0) { - return SIG_VALIDATION_FAILED_UINT; - } - - // Check if userOpHash signer already signed proposalHash (prevent double-counting) - bool alreadySigned = false; - for (uint256 i = 0; i < proposalSigners.length; i++) { - if (proposalSigners[i] == signer) { - alreadySigned = true; - break; - } - } - - // Only add weight if signer hasn't already contributed via proposalHash - if (!alreadySigned) { - totalWeight += lastWeight; - } - - if (totalWeight >= threshold) { - return SIG_VALIDATION_SUCCESS_UINT; - } - - return SIG_VALIDATION_FAILED_UINT; - } - - /** - * @notice Internal function to validate ERC-1271 signatures - * @dev Shared logic for both installed and stateless validator modes - */ - function _validateSignature(bytes32 id, bytes32 hash, bytes calldata sig, address account) - internal - view - returns (bytes4) - { - WeightedECDSASignerStorage storage strg = weightedStorage[id][account]; - if (strg.threshold == 0) { - return ERC1271_INVALID; - } - - uint256 sigCount = sig.length / 65; - if (sigCount == 0) { - return ERC1271_INVALID; - } - - uint256 totalWeight = 0; - address signer; - address lastSigner = address(0); - - // Process all signatures except the last one - for (uint256 i = 0; i < sigCount - 1; i++) { - signer = ECDSA.tryRecoverCalldata(hash, sig[i * 65:(i + 1) * 65]); - - // Enforce sorted order to prevent signature reuse - if (signer <= lastSigner) { - return ERC1271_INVALID; - } - lastSigner = signer; - - uint24 guardianWeight = guardian[signer][id][account].weight; - // Revert if non-last signer has zero weight (prevents gas griefing) - if (guardianWeight == 0) { - revert ZeroWeightSigner(); - } - totalWeight += guardianWeight; - if (totalWeight >= strg.threshold) { - return ERC1271_MAGICVALUE; - } - } - - // Process last signature - signer = ECDSA.tryRecoverCalldata(hash, sig[sig.length - 65:]); - if (signer <= lastSigner) { - return ERC1271_INVALID; - } - uint24 lastWeight = guardian[signer][id][account].weight; - // If last signer has zero weight, return invalid (don't revert) - if (lastWeight == 0) { - return ERC1271_INVALID; - } - totalWeight += lastWeight; - if (totalWeight >= strg.threshold) { - return ERC1271_MAGICVALUE; - } - - return ERC1271_INVALID; - } + // ==================== Stateless (memory-config) validation ==================== + // The installed/storage-backed paths (checkUserOpSignature / checkSignature) delegate to + // WeightedThresholdBase. The stateless paths below use caller-provided memory guardians, which + // the base's storage-keyed _guardianWeight cannot serve, so they keep their own implementation. function _validateStatelessSignature( bytes32 hash, diff --git a/src/utils/Base64URL.sol b/src/utils/Base64URL.sol deleted file mode 100644 index f6d0499..0000000 --- a/src/utils/Base64URL.sol +++ /dev/null @@ -1,31 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.0; - -import "openzeppelin-contracts/contracts/utils/Base64.sol"; - -library Base64URL { - function encode(bytes memory data) internal pure returns (string memory) { - string memory strb64 = Base64.encode(data); - bytes memory b64 = bytes(strb64); - - // Base64 can end with "=" or "=="; Base64URL has no padding. - uint256 equalsCount = 0; - if (b64.length > 2 && b64[b64.length - 2] == "=") equalsCount = 2; - else if (b64.length > 1 && b64[b64.length - 1] == "=") equalsCount = 1; - - uint256 len = b64.length - equalsCount; - bytes memory result = new bytes(len); - - for (uint256 i = 0; i < len; i++) { - if (b64[i] == "+") { - result[i] = "-"; - } else if (b64[i] == "/") { - result[i] = "_"; - } else { - result[i] = b64[i]; - } - } - - return string(result); - } -} diff --git a/src/utils/P256.sol b/src/utils/P256.sol deleted file mode 100644 index 53f064d..0000000 --- a/src/utils/P256.sol +++ /dev/null @@ -1,49 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.0; - -/** - * Helper library for external contracts to verify P256 signatures. - * - */ -library P256 { - address constant DAIMO_VERIFIER = 0xc2b78104907F722DABAc4C69f826a522B2754De4; - address constant PRECOMPILED_VERIFIER = 0x0000000000000000000000000000000000000100; - - function verifySignatureAllowMalleability( - bytes32 message_hash, - uint256 r, - uint256 s, - uint256 x, - uint256 y, - bool usePrecompiled - ) internal view returns (bool) { - bytes memory args = abi.encode(message_hash, r, s, x, y); - - if (usePrecompiled) { - (bool success, bytes memory ret) = PRECOMPILED_VERIFIER.staticcall(args); - if (success == false || ret.length == 0) { - return false; - } - return abi.decode(ret, (uint256)) == 1; - } else { - (, bytes memory ret) = DAIMO_VERIFIER.staticcall(args); - return abi.decode(ret, (uint256)) == 1; - } - } - - /// P256 curve order n/2 for malleability check - uint256 constant P256_N_DIV_2 = 57896044605178124381348723474703786764998477612067880171211129530534256022184; - - function verifySignature(bytes32 message_hash, uint256 r, uint256 s, uint256 x, uint256 y, bool usePrecompiled) - internal - view - returns (bool) - { - // check for signature malleability - if (s > P256_N_DIV_2) { - return false; - } - - return verifySignatureAllowMalleability(message_hash, r, s, x, y, usePrecompiled); - } -} diff --git a/src/utils/P256Validation.sol b/src/utils/P256Validation.sol new file mode 100644 index 0000000..741768a --- /dev/null +++ b/src/utils/P256Validation.sol @@ -0,0 +1,42 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.20; + +import {P256} from "solady/utils/P256.sol"; + +/// @notice Shared raw P-256 validation helpers for the validator and signer modules. +library P256Validation { + uint256 internal constant P = 0xFFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFF; + uint256 internal constant A = 0xFFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFC; + uint256 internal constant B = 0x5AC635D8AA3A93E7B3EBBD55769886BC651D06B0CC53B0F63BCE3C3E27D2604B; + + function isPrecompileAvailable() internal view returns (bool) { + return P256.hasPrecompile(); + } + + function isValidPublicKey(uint256 x, uint256 y) internal pure returns (bool) { + uint256 lhs = mulmod(y, y, P); + uint256 rhs = addmod(mulmod(addmod(mulmod(x, x, P), A, P), x, P), B, P); + return x < P && y < P && lhs == rhs; + } + + function decodePublicKey(bytes calldata data) internal pure returns (uint256 x, uint256 y, bool valid) { + if (data.length != 64) return (0, 0, false); + assembly ("memory-safe") { + x := calldataload(data.offset) + y := calldataload(add(data.offset, 0x20)) + } + valid = isValidPublicKey(x, y); + } + + function verify(bytes32 hash, bytes calldata signature, uint256 x, uint256 y) internal view returns (bool) { + if (signature.length != 64 || !isValidPublicKey(x, y)) return false; + + bytes32 r; + bytes32 s; + assembly ("memory-safe") { + r := calldataload(signature.offset) + s := calldataload(add(signature.offset, 0x20)) + } + return P256.verifySignature(hash, r, s, bytes32(x), bytes32(y)); + } +} diff --git a/src/utils/WebAuthn.sol b/src/utils/WebAuthn.sol deleted file mode 100644 index 85708b8..0000000 --- a/src/utils/WebAuthn.sol +++ /dev/null @@ -1,168 +0,0 @@ -// SPDX-License-Identifier: MIT - -pragma solidity ^0.8.0; - -import "./Base64URL.sol"; -import "./P256.sol"; - -/** - * Helper library for external contracts to verify WebAuthn signatures. - * - */ -library WebAuthn { - /// Checks whether substr occurs in str starting at a given byte offset. - function contains(string memory substr, string memory str, uint256 location) internal pure returns (bool) { - bytes memory substrBytes = bytes(substr); - bytes memory strBytes = bytes(str); - - uint256 substrLen = substrBytes.length; - uint256 strLen = strBytes.length; - - for (uint256 i = 0; i < substrLen; i++) { - if (location + i >= strLen) { - return false; - } - - if (substrBytes[i] != strBytes[location + i]) { - return false; - } - } - - return true; - } - - bytes1 constant AUTH_DATA_FLAGS_UP = 0x01; // Bit 0 - bytes1 constant AUTH_DATA_FLAGS_UV = 0x04; // Bit 2 - bytes1 constant AUTH_DATA_FLAGS_BE = 0x08; // Bit 3 - bytes1 constant AUTH_DATA_FLAGS_BS = 0x10; // Bit 4 - - /// Verifies the authFlags in authenticatorData. Numbers in inline comment - /// correspond to the same numbered bullets in - /// https://www.w3.org/TR/webauthn-2/#sctn-verifying-assertion. - function checkAuthFlags(bytes1 flags, bool requireUserVerification) internal pure returns (bool) { - // 17. Verify that the UP bit of the flags in authData is set. - if (flags & AUTH_DATA_FLAGS_UP != AUTH_DATA_FLAGS_UP) { - return false; - } - - // 18. If user verification was determined to be required, verify that - // the UV bit of the flags in authData is set. Otherwise, ignore the - // value of the UV flag. - if (requireUserVerification && (flags & AUTH_DATA_FLAGS_UV) != AUTH_DATA_FLAGS_UV) { - return false; - } - - // 19. If the BE bit of the flags in authData is not set, verify that - // the BS bit is not set. - if (flags & AUTH_DATA_FLAGS_BE != AUTH_DATA_FLAGS_BE) { - if (flags & AUTH_DATA_FLAGS_BS == AUTH_DATA_FLAGS_BS) { - return false; - } - } - - return true; - } - - /** - * Verifies a Webauthn P256 signature (Authentication Assertion) as described - * in https://www.w3.org/TR/webauthn-2/#sctn-verifying-assertion. We do not - * verify all the steps as described in the specification, only ones relevant - * to our context. Please carefully read through this list before usage. - * Specifically, we do verify the following: - * - Verify that authenticatorData (which comes from the authenticator, - * such as iCloud Keychain) indicates a well-formed assertion. If - * requireUserVerification is set, checks that the authenticator enforced - * user verification. User verification should be required if, - * and only if, options.userVerification is set to required in the request - * - Verifies that the client JSON is of type "webauthn.get", i.e. the client - * was responding to a request to assert authentication. - * - Verifies that the client JSON contains the requested challenge. - * - Finally, verifies that (r, s) constitute a valid signature over both - * the authenicatorData and client JSON, for public key (x, y). - * - * We make some assumptions about the particular use case of this verifier, - * so we do NOT verify the following: - * - Does NOT verify that the origin in the clientDataJSON matches the - * Relying Party's origin: It is considered the authenticator's - * responsibility to ensure that the user is interacting with the correct - * RP. This is enforced by most high quality authenticators properly, - * particularly the iCloud Keychain and Google Password Manager were - * tested. - * - Does NOT verify That c.topOrigin is well-formed: We assume c.topOrigin - * would never be present, i.e. the credentials are never used in a - * cross-origin/iframe context. The website/app set up should disallow - * cross-origin usage of the credentials. This is the default behaviour for - * created credentials in common settings. - * - Does NOT verify that the rpIdHash in authData is the SHA-256 hash of an - * RP ID expected by the Relying Party: This means that we rely on the - * authenticator to properly enforce credentials to be used only by the - * correct RP. This is generally enforced with features like Apple App Site - * Association and Google Asset Links. To protect from edge cases in which - * a previously-linked RP ID is removed from the authorised RP IDs, - * we recommend that messages signed by the authenticator include some - * expiry mechanism. - * - Does NOT verify the credential backup state: This assumes the credential - * backup state is NOT used as part of Relying Party business logic or - * policy. - * - Does NOT verify the values of the client extension outputs: This assumes - * that the Relying Party does not use client extension outputs. - * - Does NOT verify the signature counter: Signature counters are intended - * to enable risk scoring for the Relying Party. This assumes risk scoring - * is not used as part of Relying Party business logic or policy. - * - Does NOT verify the attestation object: This assumes that - * response.attestationObject is NOT present in the response, i.e. the - * RP does not intend to verify an attestation. - */ - function verifySignature( - bytes memory challenge, - bytes memory authenticatorData, - bool requireUserVerification, - string memory clientDataJSON, - uint256 challengeLocation, - uint256 responseTypeLocation, - uint256 r, - uint256 s, - uint256 x, - uint256 y, - bool usePrecompiled - ) internal view returns (bool) { - /// @notice defer the result to the end so dummy signature can go through all verification process including p256.verifySignature - bool deferredResult = true; - - // Check that authenticatorData has good flags - if (authenticatorData.length < 37 || !checkAuthFlags(authenticatorData[32], requireUserVerification)) { - deferredResult = false; - } - - // Check that response is for an authentication assertion - string memory responseType = '"type":"webauthn.get"'; - if (!contains(responseType, clientDataJSON, responseTypeLocation)) { - deferredResult = false; - } - - // Check that challenge is in the clientDataJSON - string memory challengeB64url = Base64URL.encode(challenge); - string memory challengeProperty = string.concat('"challenge":"', challengeB64url, '"'); - - if (!contains(challengeProperty, clientDataJSON, challengeLocation)) { - deferredResult = false; - } - - // Check that the public key signed sha256(authenticatorData || sha256(clientDataJSON)) - bytes32 clientDataJSONHash = sha256(bytes(clientDataJSON)); - bytes32 messageHash = sha256(abi.encodePacked(authenticatorData, clientDataJSONHash)); - - // if responseTypeLocation is set to max, it means the signature is a dummy signature - if (responseTypeLocation == type(uint256).max) { - P256.verifySignature(messageHash, r, s, x, y, usePrecompiled); - return false; - } - - bool verified = P256.verifySignature(messageHash, r, s, x, y, usePrecompiled); - - if (verified && deferredResult) { - return true; - } - return false; - } -} diff --git a/src/validators/MultiOwnerValidator.sol b/src/validators/MultiOwnerValidator.sol new file mode 100644 index 0000000..6864065 --- /dev/null +++ b/src/validators/MultiOwnerValidator.sol @@ -0,0 +1,229 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.20; + +import {PackedUserOperation} from "account-abstraction/interfaces/PackedUserOperation.sol"; + +import {IModule, IStatelessValidator, IValidator} from "src/interfaces/IERC7579Modules.sol"; +import { + ERC1271_INVALID, + ERC1271_MAGICVALUE, + MODULE_TYPE_STATELESS_VALIDATOR, + MODULE_TYPE_VALIDATOR, + SIG_VALIDATION_FAILED_UINT, + SIG_VALIDATION_SUCCESS_UINT +} from "src/types/Constants.sol"; + +/// @title MultiOwnerValidator +/// @author taek +/// @notice A root validator that gives multiple stateless signer configurations equal administrative rights. +/// @dev Each owner delegates verification to an external module implementing `IStatelessValidator`. +/// The signer module does not need to be installed on the account because its complete validation +/// configuration is stored here and supplied on every verification call. +/// +/// Install data is `abi.encode(OwnerConfig[])`. Signatures are encoded as +/// `abi.encodePacked(ownerId, ownerSignature)`. The selected stateless validator defines both +/// `ownerSignature` and `validationData`. +contract MultiOwnerValidator is IValidator { + uint256 public constant MAX_OWNERS = 32; + + struct OwnerConfig { + bytes32 ownerId; + address statelessValidator; + bytes validationData; + } + + struct Owner { + address statelessValidator; + bytes validationData; + } + + mapping(address account => mapping(bytes32 ownerId => Owner)) internal _owners; + + mapping(address account => bytes32[]) internal _ownerIds; + mapping(address account => mapping(bytes32 ownerId => uint256 indexPlusOne)) internal _ownerIndex; + + event OwnerAdded( + address indexed account, bytes32 indexed ownerId, address indexed statelessValidator, bytes validationData + ); + event OwnerUpdated( + address indexed account, bytes32 indexed ownerId, address indexed statelessValidator, bytes validationData + ); + event OwnerRemoved(address indexed account, bytes32 indexed ownerId); + + error EmptyOwners(); + error InvalidOwnerId(); + error InvalidStatelessValidator(address validator); + error OwnerAlreadyExists(bytes32 ownerId); + error OwnerDoesNotExist(bytes32 ownerId); + error MaxOwnersExceeded(); + error CannotRemoveLastOwner(); + + function onInstall(bytes calldata data) external payable override { + require(!_isInitialized(msg.sender), AlreadyInitialized(msg.sender)); + + OwnerConfig[] memory configs = abi.decode(data, (OwnerConfig[])); + require(configs.length != 0, EmptyOwners()); + require(configs.length <= MAX_OWNERS, MaxOwnersExceeded()); + + for (uint256 i; i < configs.length; ++i) { + _addOwner(msg.sender, configs[i]); + } + } + + function onUninstall(bytes calldata) external payable override { + require(_isInitialized(msg.sender), NotInitialized(msg.sender)); + + bytes32[] storage ids = _ownerIds[msg.sender]; + uint256 length = ids.length; + for (uint256 i; i < length; ++i) { + bytes32 ownerId = ids[i]; + delete _owners[msg.sender][ownerId]; + delete _ownerIndex[msg.sender][ownerId]; + } + delete _ownerIds[msg.sender]; + } + + /// @notice Adds an owner to the caller's validator configuration. + /// @dev The caller is the smart account. An existing owner can authorize an account call to + /// this function, giving every owner the same ability to administer the owner set. + function addOwner(OwnerConfig calldata config) external { + require(_isInitialized(msg.sender), NotInitialized(msg.sender)); + _addOwner(msg.sender, config); + } + + /// @notice Replaces an existing owner's validator or validation data without changing its identifier. + function updateOwner(OwnerConfig calldata config) external { + require(_isInitialized(msg.sender), NotInitialized(msg.sender)); + require(_ownerIndex[msg.sender][config.ownerId] != 0, OwnerDoesNotExist(config.ownerId)); + _validateOwnerConfig(config); + + _owners[msg.sender][config.ownerId] = Owner(config.statelessValidator, config.validationData); + emit OwnerUpdated(msg.sender, config.ownerId, config.statelessValidator, config.validationData); + } + + /// @notice Removes an owner while ensuring the validator cannot be left ownerless. + function removeOwner(bytes32 ownerId) external { + require(_isInitialized(msg.sender), NotInitialized(msg.sender)); + + uint256 indexPlusOne = _ownerIndex[msg.sender][ownerId]; + require(indexPlusOne != 0, OwnerDoesNotExist(ownerId)); + require(_ownerIds[msg.sender].length > 1, CannotRemoveLastOwner()); + + uint256 index = indexPlusOne - 1; + bytes32[] storage ids = _ownerIds[msg.sender]; + uint256 lastIndex = ids.length - 1; + if (index != lastIndex) { + bytes32 movedOwnerId = ids[lastIndex]; + ids[index] = movedOwnerId; + _ownerIndex[msg.sender][movedOwnerId] = index + 1; + } + ids.pop(); + + delete _owners[msg.sender][ownerId]; + delete _ownerIndex[msg.sender][ownerId]; + + emit OwnerRemoved(msg.sender, ownerId); + } + + function validateUserOp(PackedUserOperation calldata userOp, bytes32 userOpHash) + external + payable + override + returns (uint256) + { + if (userOp.sender != msg.sender) return SIG_VALIDATION_FAILED_UINT; + return _verifySignature(msg.sender, userOpHash, userOp.signature) + ? SIG_VALIDATION_SUCCESS_UINT + : SIG_VALIDATION_FAILED_UINT; + } + + /// @dev `sender` is the requesting protocol, not the account whose owner registry is used. + function isValidSignatureWithSender(address, bytes32 hash, bytes calldata signature) + external + view + override + returns (bytes4) + { + return _verifySignature(msg.sender, hash, signature) ? ERC1271_MAGICVALUE : ERC1271_INVALID; + } + + function isModuleType(uint256 moduleTypeId) external pure override returns (bool) { + return moduleTypeId == MODULE_TYPE_VALIDATOR; + } + + function isInitialized(address account) external view returns (bool) { + return _isInitialized(account); + } + + function ownerCount(address account) external view returns (uint256) { + return _ownerIds[account].length; + } + + function ownerIdAt(address account, uint256 index) external view returns (bytes32) { + return _ownerIds[account][index]; + } + + function owners(address account, bytes32 ownerId) + external + view + returns (address statelessValidator, bytes memory validationData) + { + Owner storage owner = _owners[account][ownerId]; + return (owner.statelessValidator, owner.validationData); + } + + function _isInitialized(address account) internal view returns (bool) { + return _ownerIds[account].length != 0; + } + + function _addOwner(address account, OwnerConfig memory config) internal { + require(_ownerIds[account].length < MAX_OWNERS, MaxOwnersExceeded()); + require(_ownerIndex[account][config.ownerId] == 0, OwnerAlreadyExists(config.ownerId)); + _validateOwnerConfig(config); + + _owners[account][config.ownerId] = Owner(config.statelessValidator, config.validationData); + _ownerIds[account].push(config.ownerId); + _ownerIndex[account][config.ownerId] = _ownerIds[account].length; + + emit OwnerAdded(account, config.ownerId, config.statelessValidator, config.validationData); + } + + function _validateOwnerConfig(OwnerConfig memory config) internal view { + require(config.ownerId != bytes32(0), InvalidOwnerId()); + + address statelessValidator = config.statelessValidator; + require(statelessValidator.code.length != 0, InvalidStatelessValidator(statelessValidator)); + + (bool success, bytes memory result) = + statelessValidator.staticcall(abi.encodeCall(IModule.isModuleType, (MODULE_TYPE_STATELESS_VALIDATOR))); + uint256 supported; + if (result.length == 32) { + assembly ("memory-safe") { + supported := mload(add(result, 0x20)) + } + } + require(success && supported == 1, InvalidStatelessValidator(statelessValidator)); + } + + function _verifySignature(address account, bytes32 hash, bytes calldata signature) internal view returns (bool) { + if (signature.length < 32) return false; + + bytes32 ownerId; + assembly ("memory-safe") { + ownerId := calldataload(signature.offset) + } + + Owner storage owner = _owners[account][ownerId]; + bytes calldata ownerSignature = signature[32:]; + + if (owner.statelessValidator == address(0)) return false; + try IStatelessValidator(owner.statelessValidator) + .validateSignatureWithData(hash, ownerSignature, owner.validationData) returns ( + bool isValid + ) { + return isValid; + } catch { + return false; + } + } +} diff --git a/src/validators/P256Validator.sol b/src/validators/P256Validator.sol new file mode 100644 index 0000000..011e45b --- /dev/null +++ b/src/validators/P256Validator.sol @@ -0,0 +1,119 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.20; + +import {IValidator, IStatelessValidator, IStatelessValidatorWithSender} from "src/interfaces/IERC7579Modules.sol"; +import {PackedUserOperation} from "account-abstraction/interfaces/PackedUserOperation.sol"; +import { + MODULE_TYPE_VALIDATOR, + MODULE_TYPE_STATELESS_VALIDATOR, + MODULE_TYPE_STATELESS_VALIDATOR_WITH_SENDER, + SIG_VALIDATION_SUCCESS_UINT, + SIG_VALIDATION_FAILED_UINT, + ERC1271_MAGICVALUE, + ERC1271_INVALID +} from "src/types/Constants.sol"; +import {P256Validation} from "src/utils/P256Validation.sol"; + +struct P256ValidatorData { + uint256 pubKeyX; + uint256 pubKeyY; +} + +/// @title P256Validator +/// @author taek +/// @notice ERC-7579 validator for raw P-256 signatures, including stateless dispatch. +/// @dev Requires the RIP-7212 / EIP-7951 precompile at address 0x100. +contract P256Validator is IValidator, IStatelessValidator, IStatelessValidatorWithSender { + error InvalidDataLength(); + error InvalidPublicKey(); + error P256PrecompileNotAvailable(); + + event PublicKeyRegistered(address indexed account, uint256 x, uint256 y); + event PublicKeyRemoved(address indexed account); + + mapping(address account => P256ValidatorData) public p256ValidatorStorage; + + constructor() { + if (!P256Validation.isPrecompileAvailable()) revert P256PrecompileNotAvailable(); + } + + function onInstall(bytes calldata data) external payable override { + if (_isInitialized(msg.sender)) revert AlreadyInitialized(msg.sender); + if (data.length != 64) revert InvalidDataLength(); + + (uint256 x, uint256 y) = abi.decode(data, (uint256, uint256)); + if (!P256Validation.isValidPublicKey(x, y)) revert InvalidPublicKey(); + + p256ValidatorStorage[msg.sender] = P256ValidatorData(x, y); + emit PublicKeyRegistered(msg.sender, x, y); + } + + function onUninstall(bytes calldata) external payable override { + if (!_isInitialized(msg.sender)) revert NotInitialized(msg.sender); + delete p256ValidatorStorage[msg.sender]; + emit PublicKeyRemoved(msg.sender); + } + + function isModuleType(uint256 typeID) external pure override returns (bool) { + return typeID == MODULE_TYPE_VALIDATOR || typeID == MODULE_TYPE_STATELESS_VALIDATOR + || typeID == MODULE_TYPE_STATELESS_VALIDATOR_WITH_SENDER; + } + + function isInitialized(address account) external view returns (bool) { + return _isInitialized(account); + } + + function validateUserOp(PackedUserOperation calldata userOp, bytes32 userOpHash) + external + payable + override + returns (uint256) + { + P256ValidatorData storage key = p256ValidatorStorage[msg.sender]; + return P256Validation.verify(userOpHash, userOp.signature, key.pubKeyX, key.pubKeyY) + ? SIG_VALIDATION_SUCCESS_UINT + : SIG_VALIDATION_FAILED_UINT; + } + + function isValidSignatureWithSender(address, bytes32 hash, bytes calldata signature) + external + view + override + returns (bytes4) + { + P256ValidatorData storage key = p256ValidatorStorage[msg.sender]; + return P256Validation.verify(hash, signature, key.pubKeyX, key.pubKeyY) ? ERC1271_MAGICVALUE : ERC1271_INVALID; + } + + function validateSignatureWithData(bytes32 hash, bytes calldata signature, bytes calldata data) + external + view + override + returns (bool) + { + return _validateStateless(hash, signature, data); + } + + function validateSignatureWithDataWithSender(address, bytes32 hash, bytes calldata signature, bytes calldata data) + external + view + override + returns (bool) + { + return _validateStateless(hash, signature, data); + } + + function _isInitialized(address account) internal view returns (bool) { + P256ValidatorData storage key = p256ValidatorStorage[account]; + return key.pubKeyX != 0 || key.pubKeyY != 0; + } + + function _validateStateless(bytes32 hash, bytes calldata signature, bytes calldata data) + internal + view + returns (bool) + { + (uint256 x, uint256 y, bool validKey) = P256Validation.decodePublicKey(data); + return validKey && P256Validation.verify(hash, signature, x, y); + } +} diff --git a/src/validators/WebAuthnValidator.sol b/src/validators/WebAuthnValidator.sol index 722416a..7d9e142 100644 --- a/src/validators/WebAuthnValidator.sol +++ b/src/validators/WebAuthnValidator.sol @@ -2,8 +2,12 @@ pragma solidity ^0.8.0; -import {IValidator, IHook} from "src/interfaces/IERC7579Modules.sol"; -import {MODULE_TYPE_VALIDATOR, MODULE_TYPE_HOOK} from "src/types/Constants.sol"; +import {IValidator, IStatelessValidator, IStatelessValidatorWithSender} from "src/interfaces/IERC7579Modules.sol"; +import { + MODULE_TYPE_VALIDATOR, + MODULE_TYPE_STATELESS_VALIDATOR, + MODULE_TYPE_STATELESS_VALIDATOR_WITH_SENDER +} from "src/types/Constants.sol"; import {PackedUserOperation} from "account-abstraction/interfaces/PackedUserOperation.sol"; import { SIG_VALIDATION_FAILED_UINT, @@ -11,7 +15,7 @@ import { ERC1271_MAGICVALUE, ERC1271_INVALID } from "src/types/Constants.sol"; -import {WebAuthn} from "src/utils/WebAuthn.sol"; +import {WebAuthn} from "solady/utils/WebAuthn.sol"; struct WebAuthnValidatorData { uint256 pubKeyX; @@ -22,10 +26,7 @@ struct WebAuthnValidatorData { * @title WebAuthnValidator * @notice This validator uses the P256 curve to validate signatures. */ -contract WebAuthnValidator is IValidator { - // The location of the challenge in the clientDataJSON - uint256 constant CHALLENGE_LOCATION = 23; - +contract WebAuthnValidator is IValidator, IStatelessValidator, IStatelessValidatorWithSender { // Emitted when a bad key is provided. error InvalidPublicKey(); @@ -63,8 +64,9 @@ contract WebAuthnValidator is IValidator { delete webAuthnValidatorStorage[msg.sender]; } - function isModuleType(uint256 typeID) external view override returns (bool) { - return typeID == MODULE_TYPE_VALIDATOR; + function isModuleType(uint256 typeID) external pure override returns (bool) { + return typeID == MODULE_TYPE_VALIDATOR || typeID == MODULE_TYPE_STATELESS_VALIDATOR + || typeID == MODULE_TYPE_STATELESS_VALIDATOR_WITH_SENDER; } function isInitialized(address smartAccount) external view returns (bool) { @@ -84,52 +86,69 @@ contract WebAuthnValidator is IValidator { override returns (uint256) { - return _verifySignature(msg.sender, _userOpHash, _userOp.signature); + return _verifySignature(_userOpHash, _userOp.signature, webAuthnValidatorStorage[msg.sender]); } /** * @notice Verify a signature with sender for ERC-1271 validation. */ - function isValidSignatureWithSender(address sender, bytes32 hash, bytes calldata data) + function isValidSignatureWithSender(address, bytes32 hash, bytes calldata data) external view returns (bytes4) { + return _verifySignature(hash, data, webAuthnValidatorStorage[msg.sender]) == SIG_VALIDATION_SUCCESS_UINT + ? ERC1271_MAGICVALUE + : ERC1271_INVALID; + } + + function validateSignatureWithData(bytes32 hash, bytes calldata signature, bytes calldata data) external view - returns (bytes4) + override + returns (bool) { - return _verifySignature(msg.sender, hash, data) == SIG_VALIDATION_SUCCESS_UINT - ? ERC1271_MAGICVALUE - : ERC1271_INVALID; + return _verifyStatelessSignature(hash, signature, data); + } + + function validateSignatureWithDataWithSender(address, bytes32 hash, bytes calldata signature, bytes calldata data) + external + view + override + returns (bool) + { + return _verifyStatelessSignature(hash, signature, data); } /** * @notice Verify a signature. + * @dev `signature` is `abi.encode(authenticatorData, clientDataJSON, challengeLocation, + * responseTypeLocation, r, s)`. + * @dev Virtual to let formal-verification harnesses model only the cryptographic boundary. */ - function _verifySignature(address account, bytes32 hash, bytes calldata signature) private view returns (uint256) { + function _verifySignature(bytes32 hash, bytes calldata signature, WebAuthnValidatorData memory webAuthnData) + internal + view + virtual + returns (uint256) + { // decode the signature ( bytes memory authenticatorData, string memory clientDataJSON, + uint256 challengeLocation, uint256 responseTypeLocation, uint256 r, - uint256 s, - bool usePrecompiled - ) = abi.decode(signature, (bytes, string, uint256, uint256, uint256, bool)); - - // get the public key from storage - WebAuthnValidatorData memory webAuthnData = webAuthnValidatorStorage[account]; + uint256 s + ) = abi.decode(signature, (bytes, string, uint256, uint256, uint256, uint256)); - // verify the signature using the signature and the public key - bool isValid = WebAuthn.verifySignature( + bool isValid = WebAuthn.verify( abi.encodePacked(hash), - authenticatorData, true, + authenticatorData, clientDataJSON, - CHALLENGE_LOCATION, + challengeLocation, responseTypeLocation, - r, - s, - webAuthnData.pubKeyX, - webAuthnData.pubKeyY, - usePrecompiled + bytes32(r), + bytes32(s), + bytes32(webAuthnData.pubKeyX), + bytes32(webAuthnData.pubKeyY) ); // return the validation data @@ -139,4 +158,15 @@ contract WebAuthnValidator is IValidator { return SIG_VALIDATION_FAILED_UINT; } + + function _verifyStatelessSignature(bytes32 hash, bytes calldata signature, bytes calldata data) + private + view + returns (bool) + { + if (data.length != 96) return false; + (WebAuthnValidatorData memory webAuthnData,) = abi.decode(data, (WebAuthnValidatorData, bytes32)); + if (webAuthnData.pubKeyX == 0 || webAuthnData.pubKeyY == 0) return false; + return _verifySignature(hash, signature, webAuthnData) == SIG_VALIDATION_SUCCESS_UINT; + } } diff --git a/src/validators/WeightedECDSAValidator.sol b/src/validators/WeightedECDSAValidator.sol new file mode 100644 index 0000000..c703293 --- /dev/null +++ b/src/validators/WeightedECDSAValidator.sol @@ -0,0 +1,175 @@ +// SPDX-License-Identifier: MIT + +pragma solidity ^0.8.0; + +import {ECDSA} from "solady/utils/ECDSA.sol"; +import {EIP712} from "solady/utils/EIP712.sol"; +import {PackedUserOperation} from "account-abstraction/interfaces/PackedUserOperation.sol"; +import {IValidator, IModule} from "src/interfaces/IERC7579Modules.sol"; +import {WeightedThresholdBase} from "src/base/WeightedThresholdBase.sol"; +import { + ERC1271_MAGICVALUE, + ERC1271_INVALID, + SIG_VALIDATION_FAILED_UINT, + SIG_VALIDATION_SUCCESS_UINT, + MODULE_TYPE_VALIDATOR +} from "src/types/Constants.sol"; + +struct WeightedECDSAValidatorStorage { + uint24 totalWeight; + uint24 threshold; + address firstGuardian; +} + +struct GuardianStorage { + uint24 weight; + address nextGuardian; +} + +/// @title WeightedECDSAValidator +/// @author taek +/// @notice Weighted guardian-multisig validator. A thin adapter over WeightedThresholdBase: it owns +/// a single-config guardian set per account and delegates all signature aggregation to the +/// shared base, adopting the (EC-01-fixed) split-signature scheme. +/// @dev This variant targets EntryPoint v0.7 (the last UserOp signature is over the eth-signed +/// userOpHash). New v4 / EntryPoint v0.9 accounts should use WeightedECDSAValidatorV09, +/// which overrides only `_finalUserOpHash`. +contract WeightedECDSAValidator is EIP712, WeightedThresholdBase, IValidator { + /// @dev EIP712 typehash for the Proposal struct (id fixed to bytes32(0): one config per account). + bytes32 private constant PROPOSAL_TYPEHASH = + keccak256("Proposal(address account,bytes32 id,bytes callData,uint256 nonce)"); + + error ZeroWeightSigner(); + error SignersNotSorted(); + error LengthMismatch(); + error EmptyGuardians(); + error ZeroThreshold(); + error GuardianCannotBeSelf(); + error ZeroAddressGuardian(); + error ZeroWeight(); + error GuardianAlreadyEnabled(); + error ThresholdExceedsTotalWeight(); + + mapping(address kernel => WeightedECDSAValidatorStorage) public weightedStorage; + mapping(address guardian => mapping(address kernel => GuardianStorage)) public guardian; + + event GuardianAdded(address indexed guardian, address indexed kernel, uint24 weight); + event GuardianRemoved(address indexed guardian, address indexed kernel); + + function _domainNameAndVersion() internal pure override returns (string memory, string memory) { + return ("WeightedECDSAValidator", "0.0.4"); + } + + function _revertZeroWeightSigner() internal pure override { + revert ZeroWeightSigner(); + } + + function _revertSignersNotSorted() internal pure override { + revert SignersNotSorted(); + } + + /// @notice Single-config weight lookup for the base aggregation (cfg is ignored). + function _guardianWeight(bytes32, address account, address signer) internal view override returns (uint256) { + return guardian[signer][account].weight; + } + + /// @notice Hash the LAST UserOp signature must sign. ep v0.7 uses the eth-signed userOpHash. + /// @dev Overridden by WeightedECDSAValidatorV09 to return the raw userOpHash (ep v0.9). + function _finalUserOpHash(bytes32 userOpHash) internal view virtual returns (bytes32) { + return ECDSA.toEthSignedMessageHash(userOpHash); + } + + // ==================== install / uninstall ==================== + + function onInstall(bytes calldata _data) external payable override { + if (_isInitialized(msg.sender)) revert AlreadyInitialized(msg.sender); + + (address[] memory _guardians, uint24[] memory _weights, uint24 _threshold) = + abi.decode(_data, (address[], uint24[], uint24)); + require(_guardians.length == _weights.length, LengthMismatch()); + require(_guardians.length > 0, EmptyGuardians()); + require(_threshold > 0, ZeroThreshold()); + + // Sentinel: firstGuardian starts as the account itself and terminates the linked list. + // No install-time sort is required; de-dup is enforced via GuardianAlreadyEnabled. + weightedStorage[msg.sender].firstGuardian = msg.sender; + for (uint256 i = 0; i < _guardians.length; i++) { + require(_guardians[i] != msg.sender, GuardianCannotBeSelf()); + require(_guardians[i] != address(0), ZeroAddressGuardian()); + require(_weights[i] != 0, ZeroWeight()); + require(guardian[_guardians[i]][msg.sender].weight == 0, GuardianAlreadyEnabled()); + guardian[_guardians[i]][msg.sender] = + GuardianStorage({weight: _weights[i], nextGuardian: weightedStorage[msg.sender].firstGuardian}); + weightedStorage[msg.sender].firstGuardian = _guardians[i]; + weightedStorage[msg.sender].totalWeight += _weights[i]; + emit GuardianAdded(_guardians[i], msg.sender, _weights[i]); + } + require(_threshold <= weightedStorage[msg.sender].totalWeight, ThresholdExceedsTotalWeight()); + weightedStorage[msg.sender].threshold = _threshold; + } + + function onUninstall(bytes calldata) external payable override { + if (!_isInitialized(msg.sender)) revert NotInitialized(msg.sender); + address currentGuardian = weightedStorage[msg.sender].firstGuardian; + while (currentGuardian != msg.sender) { + address nextGuardian = guardian[currentGuardian][msg.sender].nextGuardian; + emit GuardianRemoved(currentGuardian, msg.sender); + delete guardian[currentGuardian][msg.sender]; + currentGuardian = nextGuardian; + } + delete weightedStorage[msg.sender]; + } + + function isModuleType(uint256 moduleTypeId) external pure override returns (bool) { + return moduleTypeId == MODULE_TYPE_VALIDATOR; + } + + function isInitialized(address smartAccount) external view returns (bool) { + return _isInitialized(smartAccount); + } + + function _isInitialized(address smartAccount) internal view returns (bool) { + return weightedStorage[smartAccount].totalWeight != 0; + } + + // ==================== validation ==================== + + function validateUserOp(PackedUserOperation calldata userOp, bytes32 userOpHash) + external + payable + override + returns (uint256) + { + uint256 threshold = weightedStorage[msg.sender].threshold; + // Split signature scheme: first N-1 sigs over the EIP712 proposalHash (id = 0), last sig + // over the ep-specific final userOp hash. See WeightedThresholdBase._verifyUserOp. + bytes32 proposalHash = _hashTypedData( + keccak256( + abi.encode(PROPOSAL_TYPEHASH, userOp.sender, bytes32(0), keccak256(userOp.callData), userOp.nonce) + ) + ); + bytes32 finalHash = _finalUserOpHash(userOpHash); + return _verifyUserOp(bytes32(0), msg.sender, proposalHash, finalHash, userOp.signature, threshold) + ? SIG_VALIDATION_SUCCESS_UINT + : SIG_VALIDATION_FAILED_UINT; + } + + /// @notice ERC-1271 validation. ep-agnostic and byte-identical across variants (signs `hash` + /// directly). This is the EC-01-critical path: strictly ascending signers, ordering + /// check before weight is counted. + function isValidSignatureWithSender(address, bytes32 hash, bytes calldata data) external view returns (bytes4) { + uint256 threshold = weightedStorage[msg.sender].threshold; + return _verifySorted(bytes32(0), msg.sender, hash, data, threshold) ? ERC1271_MAGICVALUE : ERC1271_INVALID; + } +} + +/// @title WeightedECDSAValidatorV09 +/// @author taek +/// @notice WeightedECDSAValidator variant for new v4 / EntryPoint v0.9 accounts. The last UserOp +/// signature signs the RAW userOpHash (no eth-signed prefix); everything else is inherited. +contract WeightedECDSAValidatorV09 is WeightedECDSAValidator { + /// @inheritdoc WeightedECDSAValidator + function _finalUserOpHash(bytes32 userOpHash) internal view override returns (bytes32) { + return userOpHash; // ep v0.9: sign the raw userOpHash + } +} diff --git a/test/GasPolicy.t.sol b/test/GasPolicy.t.sol new file mode 100644 index 0000000..d666116 --- /dev/null +++ b/test/GasPolicy.t.sol @@ -0,0 +1,428 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.30; + +import {PolicyTestBase} from "./base/PolicyTestBase.sol"; +import {GasPolicy, Status} from "src/policies/GasPolicy.sol"; +import {PackedUserOperation} from "account-abstraction/interfaces/PackedUserOperation.sol"; +import {IModule} from "src/interfaces/IERC7579Modules.sol"; +import {SIG_VALIDATION_FAILED_UINT, SIG_VALIDATION_SUCCESS_UINT} from "src/types/Constants.sol"; + +contract GasPolicyTest is PolicyTestBase { + uint128 constant ALLOWED = 1_000_000; + // valid op: (preVerificationGas 0 + verificationGasLimit 100 + callGasLimit 100) * maxFeePerGas 1 = 200 + uint128 constant VALID_GAS_LIMIT = 100; + uint128 constant VALID_FEE = 1; + // invalid op: (0 + 1_000_000 + 1_000_000) * 1 = 2_000_000 > ALLOWED + uint128 constant INVALID_GAS_LIMIT = 1_000_000; + + address paymaster = address(0xBEEF); + address otherPaymaster = address(0xCAFE); + + function deployModule() internal override returns (IModule) { + return new GasPolicy(); + } + + function _initializeTest() internal override {} + + function installData() internal pure override returns (bytes memory) { + return abi.encode(ALLOWED, false, address(0)); + } + + function _installDataWithPaymaster(uint128 allowed, bool enforcePaymaster, address allowedPaymaster) + internal + pure + returns (bytes memory) + { + return abi.encode(allowed, enforcePaymaster, allowedPaymaster); + } + + function _userOp(uint128 gasLimit, uint128 fee, bytes memory paymasterAndData) + internal + pure + returns (PackedUserOperation memory) + { + return PackedUserOperation({ + sender: WALLET, + nonce: 0, + initCode: "", + callData: "", + accountGasLimits: bytes32(abi.encodePacked(gasLimit, gasLimit)), + preVerificationGas: 0, + gasFees: bytes32(abi.encodePacked(fee, fee)), + paymasterAndData: paymasterAndData, + signature: "" + }); + } + + function _userOpRaw( + uint128 verificationGasLimit, + uint128 callGasLimit, + uint256 preVerificationGas, + uint128 maxFeePerGas, + bytes memory paymasterAndData + ) internal pure returns (PackedUserOperation memory) { + return PackedUserOperation({ + sender: WALLET, + nonce: 0, + initCode: "", + callData: "", + accountGasLimits: bytes32(abi.encodePacked(verificationGasLimit, callGasLimit)), + preVerificationGas: preVerificationGas, + gasFees: bytes32(abi.encodePacked(maxFeePerGas, maxFeePerGas)), + paymasterAndData: paymasterAndData, + signature: "" + }); + } + + function validUserOp() internal pure override returns (PackedUserOperation memory) { + return _userOp(VALID_GAS_LIMIT, VALID_FEE, ""); + } + + function invalidUserOp() internal pure override returns (PackedUserOperation memory) { + return _userOp(INVALID_GAS_LIMIT, VALID_FEE, ""); + } + + function validSignatureData(bytes32) internal pure override returns (address sender, bytes memory signature) { + return (WALLET, ""); + } + + function invalidSignatureData(bytes32) internal pure override returns (address sender, bytes memory signature) { + return (WALLET, ""); + } + + // GasPolicy's checkSignaturePolicy ignores sender/hash/sig entirely -- it only gates on + // policy status. The generic base "fail" test assumes sig data content can flip the result, + // which is impossible here, so we cover the real failure mode (not-Live) directly instead. + function testPolicyCheckSignaturePolicyFail() public payable override { + GasPolicy policy = GasPolicy(address(module)); + // never installed -> status is NA, not Live + vm.prank(WALLET); + vm.expectRevert(); + policy.checkSignaturePolicy(policyId(), WALLET, keccak256("hash"), ""); + } + + function _afterInstallCheck(bytes32 id) internal view override { + (Status s) = GasPolicy(address(module)).status(id, WALLET); + assertTrue(s == Status.Live, "status should be Live after install"); + } + + function _afterUninstallCheck(bytes32 id) internal view override { + (Status s) = GasPolicy(address(module)).status(id, WALLET); + assertTrue(s == Status.Deprecated, "status should be Deprecated after uninstall"); + } + + // --------------------------------------------------------------------- + // install / uninstall state machine (beyond PolicyTestBase generic ones) + // --------------------------------------------------------------------- + + function test_install_StoresConfig() public { + GasPolicy policy = GasPolicy(address(module)); + vm.prank(WALLET); + policy.onInstall(abi.encodePacked(policyId(), installData())); + + (uint128 allowed, bool enforcePaymaster, address allowedPaymaster) = policy.gasPolicyConfig(policyId(), WALLET); + assertEq(allowed, ALLOWED, "allowed should match installData"); + assertFalse(enforcePaymaster, "enforcePaymaster should be false"); + assertEq(allowedPaymaster, address(0), "allowedPaymaster should be zero"); + } + + function test_uninstall_WhenNotLive_ShouldRevert() public { + GasPolicy policy = GasPolicy(address(module)); + // never installed -> status is NA + vm.prank(WALLET); + vm.expectRevert(); + policy.onUninstall(abi.encodePacked(policyId(), installData())); + } + + function test_uninstall_WhenAlreadyDeprecated_ShouldRevert() public { + GasPolicy policy = GasPolicy(address(module)); + vm.startPrank(WALLET); + policy.onInstall(abi.encodePacked(policyId(), installData())); + policy.onUninstall(abi.encodePacked(policyId(), installData())); + + vm.expectRevert(); + policy.onUninstall(abi.encodePacked(policyId(), installData())); + vm.stopPrank(); + } + + function test_reinstall_AfterUninstall_ShouldRevert() public { + // status is Deprecated, not NA, so re-install must revert too + GasPolicy policy = GasPolicy(address(module)); + vm.startPrank(WALLET); + policy.onInstall(abi.encodePacked(policyId(), installData())); + policy.onUninstall(abi.encodePacked(policyId(), installData())); + + vm.expectRevert(); + policy.onInstall(abi.encodePacked(policyId(), installData())); + vm.stopPrank(); + } + + // --------------------------------------------------------------------- + // checkUserOpPolicy - not Live + // --------------------------------------------------------------------- + + function test_checkUserOpPolicy_WhenNotLive_ShouldRevert() public { + GasPolicy policy = GasPolicy(address(module)); + PackedUserOperation memory userOp = validUserOp(); + + vm.prank(WALLET); + vm.expectRevert(); + policy.checkUserOpPolicy(policyId(), userOp); + } + + // --------------------------------------------------------------------- + // checkUserOpPolicy - budget accounting + // --------------------------------------------------------------------- + + function test_checkUserOpPolicy_WhenWithinBudget_ShouldPassAndDecrement() public { + GasPolicy policy = GasPolicy(address(module)); + vm.prank(WALLET); + policy.onInstall(abi.encodePacked(policyId(), installData())); + + uint256 expectedCost = uint256(VALID_GAS_LIMIT) * 2 * VALID_FEE; // 200 + + vm.prank(WALLET); + uint256 result = policy.checkUserOpPolicy(policyId(), validUserOp()); + + assertEq(result, SIG_VALIDATION_SUCCESS_UINT, "should succeed within budget"); + + (uint128 remaining,,) = policy.gasPolicyConfig(policyId(), WALLET); + assertEq(remaining, ALLOWED - expectedCost, "allowed should be decremented by cost"); + } + + function test_checkUserOpPolicy_WhenOverBudget_ShouldFailWithoutDecrement() public { + GasPolicy policy = GasPolicy(address(module)); + vm.prank(WALLET); + policy.onInstall(abi.encodePacked(policyId(), installData())); + + vm.prank(WALLET); + uint256 result = policy.checkUserOpPolicy(policyId(), invalidUserOp()); + + assertEq(result, SIG_VALIDATION_FAILED_UINT, "should fail when over budget"); + + (uint128 remaining,,) = policy.gasPolicyConfig(policyId(), WALLET); + assertEq(remaining, ALLOWED, "allowed should NOT be decremented on failure"); + } + + function test_checkUserOpPolicy_WhenExactlyAtBudget_ShouldPass() public { + // boundary: maxAmount == allowed exactly -> passes (only strictly-greater fails) + GasPolicy policy = GasPolicy(address(module)); + uint128 small = 200; // matches validUserOp cost exactly + vm.prank(WALLET); + policy.onInstall(abi.encodePacked(policyId(), _installDataWithPaymaster(small, false, address(0)))); + + vm.prank(WALLET); + uint256 result = policy.checkUserOpPolicy(policyId(), validUserOp()); + + assertEq(result, SIG_VALIDATION_SUCCESS_UINT, "maxAmount == allowed should pass"); + + (uint128 remaining,,) = policy.gasPolicyConfig(policyId(), WALLET); + assertEq(remaining, 0, "budget should be fully consumed"); + } + + function test_checkUserOpPolicy_WhenOneWeiOverBudget_ShouldFail() public { + GasPolicy policy = GasPolicy(address(module)); + uint128 small = 199; // one less than validUserOp cost of 200 + vm.prank(WALLET); + policy.onInstall(abi.encodePacked(policyId(), _installDataWithPaymaster(small, false, address(0)))); + + vm.prank(WALLET); + uint256 result = policy.checkUserOpPolicy(policyId(), validUserOp()); + + assertEq(result, SIG_VALIDATION_FAILED_UINT, "maxAmount == allowed + 1 should fail"); + } + + function test_checkUserOpPolicy_MultipleOps_ShouldDecrementCumulatively() public { + GasPolicy policy = GasPolicy(address(module)); + vm.prank(WALLET); + policy.onInstall(abi.encodePacked(policyId(), installData())); + + uint256 costPerOp = uint256(VALID_GAS_LIMIT) * 2 * VALID_FEE; // 200 + + vm.startPrank(WALLET); + uint256 r1 = policy.checkUserOpPolicy(policyId(), validUserOp()); + uint256 r2 = policy.checkUserOpPolicy(policyId(), validUserOp()); + uint256 r3 = policy.checkUserOpPolicy(policyId(), validUserOp()); + vm.stopPrank(); + + assertEq(r1, SIG_VALIDATION_SUCCESS_UINT, "op1 should pass"); + assertEq(r2, SIG_VALIDATION_SUCCESS_UINT, "op2 should pass"); + assertEq(r3, SIG_VALIDATION_SUCCESS_UINT, "op3 should pass"); + + (uint128 remaining,,) = policy.gasPolicyConfig(policyId(), WALLET); + assertEq(remaining, ALLOWED - 3 * costPerOp, "allowed should reflect cumulative spend"); + } + + function test_checkUserOpPolicy_MultipleOps_ShouldFailOnceBudgetExhausted() public { + // Install with a budget that allows exactly 2 ops of 200 each, third must fail + GasPolicy policy = GasPolicy(address(module)); + uint128 twoOpsBudget = 400; + vm.prank(WALLET); + policy.onInstall(abi.encodePacked(policyId(), _installDataWithPaymaster(twoOpsBudget, false, address(0)))); + + vm.startPrank(WALLET); + uint256 r1 = policy.checkUserOpPolicy(policyId(), validUserOp()); + uint256 r2 = policy.checkUserOpPolicy(policyId(), validUserOp()); + uint256 r3 = policy.checkUserOpPolicy(policyId(), validUserOp()); + vm.stopPrank(); + + assertEq(r1, SIG_VALIDATION_SUCCESS_UINT, "op1 should pass"); + assertEq(r2, SIG_VALIDATION_SUCCESS_UINT, "op2 should pass"); + assertEq(r3, SIG_VALIDATION_FAILED_UINT, "op3 should fail, budget exhausted"); + + (uint128 remaining,,) = policy.gasPolicyConfig(policyId(), WALLET); + assertEq(remaining, 0, "remaining budget should be exactly 0 after 2 successful ops"); + } + + // --------------------------------------------------------------------- + // checkUserOpPolicy - paymaster enforcement branches + // --------------------------------------------------------------------- + + function test_checkUserOpPolicy_WhenPaymasterEnforcedAndMatches_ShouldPass() public { + GasPolicy policy = GasPolicy(address(module)); + vm.prank(WALLET); + policy.onInstall(abi.encodePacked(policyId(), _installDataWithPaymaster(ALLOWED, true, paymaster))); + + bytes memory paymasterAndData = abi.encodePacked(paymaster, uint256(0), uint256(0)); + PackedUserOperation memory userOp = _userOp(VALID_GAS_LIMIT, VALID_FEE, paymasterAndData); + + vm.prank(WALLET); + uint256 result = policy.checkUserOpPolicy(policyId(), userOp); + + assertEq(result, SIG_VALIDATION_SUCCESS_UINT, "matching paymaster should pass"); + } + + function test_checkUserOpPolicy_WhenPaymasterEnforcedAndMismatches_ShouldFail() public { + GasPolicy policy = GasPolicy(address(module)); + vm.prank(WALLET); + policy.onInstall(abi.encodePacked(policyId(), _installDataWithPaymaster(ALLOWED, true, paymaster))); + + bytes memory paymasterAndData = abi.encodePacked(otherPaymaster, uint256(0), uint256(0)); + PackedUserOperation memory userOp = _userOp(VALID_GAS_LIMIT, VALID_FEE, paymasterAndData); + + vm.prank(WALLET); + uint256 result = policy.checkUserOpPolicy(policyId(), userOp); + + assertEq(result, SIG_VALIDATION_FAILED_UINT, "mismatched paymaster should fail"); + + (uint128 remaining,,) = policy.gasPolicyConfig(policyId(), WALLET); + assertEq(remaining, ALLOWED, "allowed should not be decremented on paymaster mismatch"); + } + + function test_checkUserOpPolicy_WhenPaymasterEnforcedButAllowedPaymasterIsZero_ShouldSkipCheckAndPass() public { + // enforcePaymaster = true but allowedPaymaster == address(0) => the address(0) branch + // short-circuits the paymaster comparison entirely, regardless of who the actual paymaster is. + GasPolicy policy = GasPolicy(address(module)); + vm.prank(WALLET); + policy.onInstall(abi.encodePacked(policyId(), _installDataWithPaymaster(ALLOWED, true, address(0)))); + + bytes memory paymasterAndData = abi.encodePacked(otherPaymaster, uint256(0), uint256(0)); + PackedUserOperation memory userOp = _userOp(VALID_GAS_LIMIT, VALID_FEE, paymasterAndData); + + vm.prank(WALLET); + uint256 result = policy.checkUserOpPolicy(policyId(), userOp); + + assertEq(result, SIG_VALIDATION_SUCCESS_UINT, "zero allowedPaymaster should skip paymaster check"); + } + + function test_checkUserOpPolicy_WhenNotEnforcingPaymaster_ShouldIgnorePaymasterAndDataField() public { + // enforcePaymaster = false entirely skips the outer branch, even with empty paymasterAndData. + GasPolicy policy = GasPolicy(address(module)); + vm.prank(WALLET); + policy.onInstall(abi.encodePacked(policyId(), installData())); // enforcePaymaster = false + + vm.prank(WALLET); + uint256 result = policy.checkUserOpPolicy(policyId(), validUserOp()); // empty paymasterAndData + + assertEq(result, SIG_VALIDATION_SUCCESS_UINT, "no paymaster enforcement should ignore paymasterAndData"); + } + + /// @notice When enforcePaymaster is true and allowedPaymaster != address(0), the + /// length of paymasterAndData is guarded before slicing. Empty paymasterAndData does not + /// revert with an out-of-bounds panic — it is treated as "no paymaster provided" and fails + /// validation cleanly via SIG_VALIDATION_FAILED_UINT. + function test_DO01_PaymasterEnforcedEmptyData_ReturnsFailed() public { + GasPolicy policy = GasPolicy(address(module)); + vm.prank(WALLET); + policy.onInstall(abi.encodePacked(policyId(), _installDataWithPaymaster(ALLOWED, true, paymaster))); + + PackedUserOperation memory userOp = _userOp(VALID_GAS_LIMIT, VALID_FEE, ""); // empty paymasterAndData + + vm.prank(WALLET); + uint256 result = policy.checkUserOpPolicy(policyId(), userOp); + + assertEq(result, SIG_VALIDATION_FAILED_UINT, "empty paymasterAndData should fail cleanly, not revert"); + + (uint128 remaining,,) = policy.gasPolicyConfig(policyId(), WALLET); + assertEq(remaining, ALLOWED, "allowed should not be decremented on paymaster length-guard failure"); + } + + /// @notice paymasterAndData shorter than 20 bytes (but non-empty) is also guarded. + function test_DO01_PaymasterEnforcedShortData_ReturnsFailed() public { + GasPolicy policy = GasPolicy(address(module)); + vm.prank(WALLET); + policy.onInstall(abi.encodePacked(policyId(), _installDataWithPaymaster(ALLOWED, true, paymaster))); + + PackedUserOperation memory userOp = _userOp(VALID_GAS_LIMIT, VALID_FEE, hex"1234"); // 2 bytes, < 20 + + vm.prank(WALLET); + uint256 result = policy.checkUserOpPolicy(policyId(), userOp); + + assertEq(result, SIG_VALIDATION_FAILED_UINT, "short paymasterAndData should fail cleanly, not revert"); + } + + /// @notice True uint256 cost is exactly 2^128 (>= budget of 1e18) but its + /// low-128-bit residue is 0. A `uint128(allowed) >= uint128(maxAmount)`-style + /// truncated comparison would let a residue of 0 slip under any nonzero budget. Comparing + /// the full uint256 product against `allowed` means this op must be rejected and the + /// budget must be left untouched. + function test_TF01_TruncatedProductWithZeroResidue_ReturnsFailedAndBudgetUnchanged() public { + GasPolicy policy = GasPolicy(address(module)); + uint128 allowed = 1e18; + vm.prank(WALLET); + policy.onInstall(abi.encodePacked(policyId(), _installDataWithPaymaster(allowed, false, address(0)))); + + // verificationGasLimit = 2^80, callGasLimit = 0, preVerificationGas = 0, maxFeePerGas = 2^48 + // true product = 2^80 * 2^48 = 2^128 (low 128 bits == 0, so a uint128 truncation would see 0). + uint128 verificationGasLimit = uint128(2 ** 80); + uint128 callGasLimit = 0; + uint128 maxFeePerGas = uint128(2 ** 48); + PackedUserOperation memory userOp = _userOpRaw(verificationGasLimit, callGasLimit, 0, maxFeePerGas, ""); + + // Sanity: confirm the residue really is 0 and the true cost really exceeds the budget. + uint256 trueCost = (uint256(0) + verificationGasLimit + callGasLimit) * maxFeePerGas; + assertEq(trueCost, 2 ** 128, "true cost should be exactly 2^128"); + assertEq(uint128(trueCost), 0, "low-128 residue should be 0 (this is what pre-fix code would compare)"); + assertGt(trueCost, allowed, "true cost must exceed the budget"); + + vm.prank(WALLET); + uint256 result = policy.checkUserOpPolicy(policyId(), userOp); + + assertEq(result, SIG_VALIDATION_FAILED_UINT, "over-cap op must fail despite zero low-128 residue"); + + (uint128 remaining,,) = policy.gasPolicyConfig(policyId(), WALLET); + assertEq(remaining, allowed, "budget must not be decremented when the true cost exceeds it"); + } + + // --------------------------------------------------------------------- + // checkSignaturePolicy + // --------------------------------------------------------------------- + + function test_checkSignaturePolicy_WhenNotLive_ShouldRevert() public { + GasPolicy policy = GasPolicy(address(module)); + vm.prank(WALLET); + vm.expectRevert(); + policy.checkSignaturePolicy(policyId(), WALLET, keccak256("hash"), ""); + } + + function test_checkSignaturePolicy_WhenLive_ShouldReturnSuccess() public { + GasPolicy policy = GasPolicy(address(module)); + vm.prank(WALLET); + policy.onInstall(abi.encodePacked(policyId(), installData())); + + vm.prank(WALLET); + uint256 result = policy.checkSignaturePolicy(policyId(), WALLET, keccak256("hash"), ""); + + assertEq(result, SIG_VALIDATION_SUCCESS_UINT, "should succeed when Live"); + } +} diff --git a/test/MultiOwnerValidator.t.sol b/test/MultiOwnerValidator.t.sol new file mode 100644 index 0000000..7769515 --- /dev/null +++ b/test/MultiOwnerValidator.t.sol @@ -0,0 +1,507 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.20; + +import {PackedUserOperation} from "account-abstraction/interfaces/PackedUserOperation.sol"; + +import {IModule, IStatelessValidator} from "src/interfaces/IERC7579Modules.sol"; +import {ECDSASigner} from "src/signers/ECDSASigner.sol"; +import {P256Signer} from "src/signers/P256Signer.sol"; +import {WebAuthnSigner, WebAuthnSignerData} from "src/signers/WebAuthnSigner.sol"; +import { + ERC1271_INVALID, + ERC1271_MAGICVALUE, + MODULE_TYPE_STATELESS_VALIDATOR, + SIG_VALIDATION_FAILED_UINT +} from "src/types/Constants.sol"; +import {MultiOwnerValidator} from "src/validators/MultiOwnerValidator.sol"; +import {Base64} from "solady/utils/Base64.sol"; +import {ValidatorTestBase} from "test/base/ValidatorTestBase.sol"; + +contract ArbitraryStatelessSigner is IStatelessValidator { + function onInstall(bytes calldata) external payable {} + + function onUninstall(bytes calldata) external payable {} + + function isModuleType(uint256 moduleTypeId) external pure returns (bool) { + return moduleTypeId == MODULE_TYPE_STATELESS_VALIDATOR; + } + + function validateSignatureWithData(bytes32 hash, bytes calldata signature, bytes calldata data) + external + pure + returns (bool) + { + return keccak256(signature) == keccak256(abi.encodePacked(hash, data)); + } +} + +contract RevertingStatelessSigner is IStatelessValidator { + function onInstall(bytes calldata) external payable {} + + function onUninstall(bytes calldata) external payable {} + + function isModuleType(uint256 moduleTypeId) external pure returns (bool) { + return moduleTypeId == MODULE_TYPE_STATELESS_VALIDATOR; + } + + function validateSignatureWithData(bytes32, bytes calldata, bytes calldata) external pure returns (bool) { + revert("validation reverted"); + } +} + +contract NonStatelessModule is IModule { + function onInstall(bytes calldata) external payable {} + + function onUninstall(bytes calldata) external payable {} + + function isModuleType(uint256) external pure returns (bool) { + return false; + } +} + +contract MultiOwnerValidatorTest is ValidatorTestBase { + uint256 internal constant P256_N = 0xFFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC632551; + uint256 internal constant ECDSA_KEY = 0xA11CE; + uint256 internal constant P256_KEY = 0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef; + + bytes32 internal constant ECDSA_ID = keccak256("ecdsa-owner"); + bytes32 internal constant P256_ID = keccak256("p256-owner"); + bytes32 internal constant WEBAUTHN_ID = keccak256("webauthn-owner"); + bytes32 internal constant ARBITRARY_ID = keccak256("arbitrary-owner"); + + MultiOwnerValidator internal validator; + ECDSASigner internal ecdsaSigner; + P256Signer internal p256Signer; + WebAuthnSigner internal webAuthnSigner; + ArbitraryStatelessSigner internal arbitrarySigner; + RevertingStatelessSigner internal revertingSigner; + NonStatelessModule internal nonStatelessModule; + + address internal ecdsaOwner; + uint256 internal p256X; + uint256 internal p256Y; + + function deployModule() internal override returns (IModule) { + validator = new MultiOwnerValidator(); + return validator; + } + + function _initializeTest() internal override { + ecdsaSigner = new ECDSASigner(); + p256Signer = new P256Signer(); + webAuthnSigner = new WebAuthnSigner(); + arbitrarySigner = new ArbitraryStatelessSigner(); + revertingSigner = new RevertingStatelessSigner(); + nonStatelessModule = new NonStatelessModule(); + + ecdsaOwner = vm.addr(ECDSA_KEY); + (p256X, p256Y) = vm.publicKeyP256(P256_KEY); + } + + function installData() internal view override returns (bytes memory) { + MultiOwnerValidator.OwnerConfig[] memory configs = new MultiOwnerValidator.OwnerConfig[](1); + configs[0] = _ecdsaConfig(ECDSA_ID, ecdsaOwner); + return abi.encode(configs); + } + + function userOpSignature(PackedUserOperation memory userOp, bool valid) + internal + view + override + returns (bytes memory) + { + bytes32 hash = ENTRYPOINT.getUserOpHash(userOp); + return abi.encodePacked(ECDSA_ID, _ecdsaSignature(valid ? hash : keccak256(abi.encode("invalid", hash)))); + } + + function erc1271Signature(bytes32 hash, bool valid) + internal + pure + override + returns (address sender, bytes memory signature) + { + bytes32 signedHash = valid ? hash : keccak256(abi.encode("invalid", hash)); + return (address(0), abi.encodePacked(ECDSA_ID, _ecdsaSignature(signedHash))); + } + + function _afterInstallCheck() internal view override { + assertTrue(validator.isInitialized(WALLET)); + assertEq(validator.ownerCount(WALLET), 1); + assertEq(validator.ownerIdAt(WALLET, 0), ECDSA_ID); + (address statelessValidator, bytes memory validationData) = validator.owners(WALLET, ECDSA_ID); + assertEq(statelessValidator, address(ecdsaSigner)); + assertEq(validationData, abi.encodePacked(ecdsaOwner)); + } + + function _afterUninstallCheck() internal view override { + assertFalse(validator.isInitialized(WALLET)); + assertEq(validator.ownerCount(WALLET), 0); + (address statelessValidator, bytes memory validationData) = validator.owners(WALLET, ECDSA_ID); + assertEq(statelessValidator, address(0)); + assertEq(validationData.length, 0); + } + + function testInstallSupportsAnyStatelessSigner() public { + MultiOwnerValidator.OwnerConfig[] memory configs = new MultiOwnerValidator.OwnerConfig[](4); + configs[0] = _ecdsaConfig(ECDSA_ID, ecdsaOwner); + configs[1] = _p256Config(P256_ID); + configs[2] = _webAuthnConfig(WEBAUTHN_ID); + configs[3] = _config(ARBITRARY_ID, address(arbitrarySigner), hex"c0ffee"); + + vm.prank(WALLET); + validator.onInstall(abi.encode(configs)); + + assertEq(validator.ownerCount(WALLET), 4); + assertEq(validator.ownerIdAt(WALLET, 0), ECDSA_ID); + assertEq(validator.ownerIdAt(WALLET, 1), P256_ID); + assertEq(validator.ownerIdAt(WALLET, 2), WEBAUTHN_ID); + assertEq(validator.ownerIdAt(WALLET, 3), ARBITRARY_ID); + } + + function testInstallRejectsEmptyOwnerSet() public { + MultiOwnerValidator.OwnerConfig[] memory configs = new MultiOwnerValidator.OwnerConfig[](0); + vm.prank(WALLET); + vm.expectRevert(MultiOwnerValidator.EmptyOwners.selector); + validator.onInstall(abi.encode(configs)); + } + + function testInstallRejectsDuplicateOwnerIds() public { + MultiOwnerValidator.OwnerConfig[] memory configs = new MultiOwnerValidator.OwnerConfig[](2); + configs[0] = _ecdsaConfig(ECDSA_ID, ecdsaOwner); + configs[1] = _p256Config(ECDSA_ID); + + vm.prank(WALLET); + vm.expectRevert(abi.encodeWithSelector(MultiOwnerValidator.OwnerAlreadyExists.selector, ECDSA_ID)); + validator.onInstall(abi.encode(configs)); + } + + function testInstallRejectsInvalidOwnerConfigurations() public { + _expectInvalidConfig( + _config(bytes32(0), address(ecdsaSigner), abi.encodePacked(ecdsaOwner)), + MultiOwnerValidator.InvalidOwnerId.selector + ); + _expectInvalidConfig( + _config(ECDSA_ID, address(0), abi.encodePacked(ecdsaOwner)), + abi.encodeWithSelector(MultiOwnerValidator.InvalidStatelessValidator.selector, address(0)) + ); + _expectInvalidConfig( + _config(ECDSA_ID, ecdsaOwner, abi.encodePacked(ecdsaOwner)), + abi.encodeWithSelector(MultiOwnerValidator.InvalidStatelessValidator.selector, ecdsaOwner) + ); + _expectInvalidConfig( + _config(ECDSA_ID, address(nonStatelessModule), abi.encodePacked(ecdsaOwner)), + abi.encodeWithSelector(MultiOwnerValidator.InvalidStatelessValidator.selector, address(nonStatelessModule)) + ); + } + + function testAddUpdateAndRemoveOwners() public { + _installDefault(); + + vm.prank(WALLET); + validator.addOwner(_p256Config(P256_ID)); + assertEq(validator.ownerCount(WALLET), 2); + + MultiOwnerValidator.OwnerConfig memory updated = _webAuthnConfig(P256_ID); + vm.prank(WALLET); + validator.updateOwner(updated); + (address statelessValidator, bytes memory validationData) = validator.owners(WALLET, P256_ID); + assertEq(statelessValidator, address(webAuthnSigner)); + assertEq(validationData, _webAuthnData()); + assertEq(validator.ownerCount(WALLET), 2); + + vm.prank(WALLET); + validator.removeOwner(ECDSA_ID); + assertEq(validator.ownerCount(WALLET), 1); + assertEq(validator.ownerIdAt(WALLET, 0), P256_ID); + (statelessValidator, validationData) = validator.owners(WALLET, ECDSA_ID); + assertEq(statelessValidator, address(0)); + assertEq(validationData.length, 0); + } + + function testCannotRemoveLastOwner() public { + _installDefault(); + vm.prank(WALLET); + vm.expectRevert(MultiOwnerValidator.CannotRemoveLastOwner.selector); + validator.removeOwner(ECDSA_ID); + } + + function testLifecycleOperationsRequireInitializedCaller() public { + vm.startPrank(WALLET); + vm.expectRevert(abi.encodeWithSelector(IModule.NotInitialized.selector, WALLET)); + validator.addOwner(_ecdsaConfig(ECDSA_ID, ecdsaOwner)); + vm.expectRevert(abi.encodeWithSelector(IModule.NotInitialized.selector, WALLET)); + validator.updateOwner(_ecdsaConfig(ECDSA_ID, ecdsaOwner)); + vm.expectRevert(abi.encodeWithSelector(IModule.NotInitialized.selector, WALLET)); + validator.removeOwner(ECDSA_ID); + vm.stopPrank(); + } + + function testAccountStorageIsIsolated() public { + _installDefault(); + address otherAccount = address(0xBEEF); + address otherOwner = vm.addr(0xB0B); + MultiOwnerValidator.OwnerConfig[] memory configs = new MultiOwnerValidator.OwnerConfig[](1); + configs[0] = _ecdsaConfig(ECDSA_ID, otherOwner); + + vm.prank(otherAccount); + validator.onInstall(abi.encode(configs)); + + (, bytes memory walletData) = validator.owners(WALLET, ECDSA_ID); + (, bytes memory otherAccountData) = validator.owners(otherAccount, ECDSA_ID); + assertEq(walletData, abi.encodePacked(ecdsaOwner)); + assertEq(otherAccountData, abi.encodePacked(otherOwner)); + } + + function testUninstallClearsEveryOwnerAndAllowsReinstall() public { + _installDefault(); + vm.prank(WALLET); + validator.addOwner(_p256Config(P256_ID)); + + vm.prank(WALLET); + validator.onUninstall(""); + assertEq(validator.ownerCount(WALLET), 0); + (address ecdsaModule,) = validator.owners(WALLET, ECDSA_ID); + (address p256Module,) = validator.owners(WALLET, P256_ID); + assertEq(ecdsaModule, address(0)); + assertEq(p256Module, address(0)); + + vm.prank(WALLET); + validator.onInstall(installData()); + assertEq(validator.ownerCount(WALLET), 1); + } + + function testDelegatesToECDSAStatelessSigner() public { + _installDefault(); + bytes32 hash = keccak256("ECDSA stateless owner"); + bytes32 ethHash = keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", hash)); + bytes memory signature = abi.encodePacked(ECDSA_ID, _ecdsaSignature(ethHash)); + + vm.prank(WALLET); + assertEq(validator.isValidSignatureWithSender(address(0), hash, signature), ERC1271_MAGICVALUE); + } + + function testDelegatesToP256StatelessSigner() public { + _installDefault(); + vm.prank(WALLET); + validator.addOwner(_p256Config(P256_ID)); + + bytes32 hash = keccak256("P256 stateless owner"); + bytes memory signature = abi.encodePacked(P256_ID, _p256Signature(hash)); + vm.prank(WALLET); + assertEq(validator.isValidSignatureWithSender(address(0), hash, signature), ERC1271_MAGICVALUE); + } + + function testDelegatesToWebAuthnStatelessSignerWithDynamicLocations() public { + _installDefault(); + vm.prank(WALLET); + validator.addOwner(_webAuthnConfig(WEBAUTHN_ID)); + + bytes32 hash = keccak256("dynamic WebAuthn locations"); + bytes memory webAuthnSignature = _webAuthnSignature(hash, '{"origin":"https://example.com",'); + ( + bytes memory authenticatorData, + string memory clientDataJSON, + uint256 challengeLocation, + uint256 responseTypeLocation, + uint256 r, + uint256 s + ) = abi.decode(webAuthnSignature, (bytes, string, uint256, uint256, uint256, uint256)); + assertNotEq(challengeLocation, 23); + + vm.prank(WALLET); + assertEq( + validator.isValidSignatureWithSender(address(0), hash, abi.encodePacked(WEBAUTHN_ID, webAuthnSignature)), + ERC1271_MAGICVALUE + ); + + bytes memory wrongLocationSignature = + abi.encode(authenticatorData, clientDataJSON, uint256(23), responseTypeLocation, r, s); + vm.prank(WALLET); + assertEq( + validator.isValidSignatureWithSender( + address(0), hash, abi.encodePacked(WEBAUTHN_ID, wrongLocationSignature) + ), + ERC1271_INVALID + ); + } + + function testDelegatesToArbitraryStatelessSigner() public { + bytes memory validationData = hex"c0ffee"; + MultiOwnerValidator.OwnerConfig[] memory configs = new MultiOwnerValidator.OwnerConfig[](1); + configs[0] = _config(ARBITRARY_ID, address(arbitrarySigner), validationData); + vm.prank(WALLET); + validator.onInstall(abi.encode(configs)); + + bytes32 hash = keccak256("arbitrary signer"); + bytes memory ownerSignature = abi.encodePacked(hash, validationData); + vm.prank(WALLET); + assertEq( + validator.isValidSignatureWithSender(address(0), hash, abi.encodePacked(ARBITRARY_ID, ownerSignature)), + ERC1271_MAGICVALUE + ); + } + + function testSelectedOwnerDefinesSignatureFormat() public { + _installDefault(); + vm.prank(WALLET); + validator.addOwner(_p256Config(P256_ID)); + + bytes32 hash = keccak256("validator binding"); + bytes memory ecdsaUnderP256Id = abi.encodePacked(P256_ID, _ecdsaSignature(hash)); + bytes memory p256UnderECDSAId = abi.encodePacked(ECDSA_ID, _p256Signature(hash)); + + vm.startPrank(WALLET); + assertEq(validator.isValidSignatureWithSender(address(0), hash, ecdsaUnderP256Id), ERC1271_INVALID); + assertEq(validator.isValidSignatureWithSender(address(0), hash, p256UnderECDSAId), ERC1271_INVALID); + vm.stopPrank(); + } + + function testRemovedAndUnknownOwnersFail() public { + _installDefault(); + vm.prank(WALLET); + validator.addOwner(_p256Config(P256_ID)); + vm.prank(WALLET); + validator.removeOwner(ECDSA_ID); + + bytes32 hash = keccak256("removed owner"); + vm.startPrank(WALLET); + assertEq( + validator.isValidSignatureWithSender(address(0), hash, abi.encodePacked(ECDSA_ID, _ecdsaSignature(hash))), + ERC1271_INVALID + ); + assertEq( + validator.isValidSignatureWithSender( + address(0), hash, abi.encodePacked(bytes32(uint256(0xBAD)), _ecdsaSignature(hash)) + ), + ERC1271_INVALID + ); + vm.stopPrank(); + } + + function testMalformedOrRevertingChildValidationFailsWithoutReverting() public { + _installDefault(); + vm.prank(WALLET); + validator.addOwner(_config(ARBITRARY_ID, address(revertingSigner), "")); + + bytes32 hash = keccak256("malformed signatures"); + vm.startPrank(WALLET); + assertEq(validator.isValidSignatureWithSender(address(0), hash, hex""), ERC1271_INVALID); + assertEq( + validator.isValidSignatureWithSender(address(0), hash, abi.encodePacked(ECDSA_ID, hex"01")), ERC1271_INVALID + ); + assertEq( + validator.isValidSignatureWithSender(address(0), hash, abi.encodePacked(ARBITRARY_ID, hex"01")), + ERC1271_INVALID + ); + vm.stopPrank(); + } + + function testValidateUserOpRejectsMismatchedAccount() public { + _installDefault(); + PackedUserOperation memory userOp; + userOp.sender = address(0xBEEF); + userOp.signature = abi.encodePacked(ECDSA_ID, _ecdsaSignature(bytes32(uint256(1)))); + + vm.prank(WALLET); + assertEq(validator.validateUserOp(userOp, bytes32(uint256(1))), SIG_VALIDATION_FAILED_UINT); + } + + function testUpdatingOwnerImmediatelyChangesDelegatedSigner() public { + _installDefault(); + uint256 newKey = 0xB0B; + address newOwner = vm.addr(newKey); + vm.prank(WALLET); + validator.updateOwner(_ecdsaConfig(ECDSA_ID, newOwner)); + + bytes32 hash = keccak256("key rotation"); + bytes memory oldSignature = abi.encodePacked(ECDSA_ID, _ecdsaSignature(hash)); + (uint8 v, bytes32 r, bytes32 s) = vm.sign(newKey, hash); + bytes memory newSignature = abi.encodePacked(ECDSA_ID, r, s, v); + + vm.startPrank(WALLET); + assertEq(validator.isValidSignatureWithSender(address(0), hash, oldSignature), ERC1271_INVALID); + assertEq(validator.isValidSignatureWithSender(address(0), hash, newSignature), ERC1271_MAGICVALUE); + vm.stopPrank(); + } + + function _installDefault() internal { + vm.prank(WALLET); + validator.onInstall(installData()); + } + + function _expectInvalidConfig(MultiOwnerValidator.OwnerConfig memory config, bytes memory expectedError) internal { + MultiOwnerValidator.OwnerConfig[] memory configs = new MultiOwnerValidator.OwnerConfig[](1); + configs[0] = config; + vm.prank(WALLET); + vm.expectRevert(expectedError); + validator.onInstall(abi.encode(configs)); + } + + function _expectInvalidConfig(MultiOwnerValidator.OwnerConfig memory config, bytes4 expectedError) internal { + MultiOwnerValidator.OwnerConfig[] memory configs = new MultiOwnerValidator.OwnerConfig[](1); + configs[0] = config; + vm.prank(WALLET); + vm.expectRevert(expectedError); + validator.onInstall(abi.encode(configs)); + } + + function _config(bytes32 ownerId, address statelessValidator, bytes memory validationData) + internal + pure + returns (MultiOwnerValidator.OwnerConfig memory) + { + return MultiOwnerValidator.OwnerConfig(ownerId, statelessValidator, validationData); + } + + function _ecdsaConfig(bytes32 ownerId, address owner) + internal + view + returns (MultiOwnerValidator.OwnerConfig memory) + { + return _config(ownerId, address(ecdsaSigner), abi.encodePacked(owner)); + } + + function _p256Config(bytes32 ownerId) internal view returns (MultiOwnerValidator.OwnerConfig memory) { + return _config(ownerId, address(p256Signer), abi.encode(p256X, p256Y)); + } + + function _webAuthnConfig(bytes32 ownerId) internal view returns (MultiOwnerValidator.OwnerConfig memory) { + return _config(ownerId, address(webAuthnSigner), _webAuthnData()); + } + + function _webAuthnData() internal view returns (bytes memory) { + return abi.encode(WebAuthnSignerData(p256X, p256Y), bytes32(0)); + } + + function _ecdsaSignature(bytes32 hash) internal pure returns (bytes memory) { + (uint8 v, bytes32 r, bytes32 s) = vm.sign(ECDSA_KEY, hash); + return abi.encodePacked(r, s, v); + } + + function _p256Signature(bytes32 hash) internal pure returns (bytes memory) { + (bytes32 r, bytes32 s) = vm.signP256(P256_KEY, hash); + uint256 normalizedS = uint256(s); + if (normalizedS > P256_N / 2) normalizedS = P256_N - normalizedS; + return abi.encode(r, bytes32(normalizedS)); + } + + function _webAuthnSignature(bytes32 hash, string memory clientDataPrefix) internal pure returns (bytes memory) { + bytes memory authenticatorData = new bytes(37); + authenticatorData[32] = bytes1(uint8(0x05)); + + string memory challenge = Base64.encode(abi.encodePacked(hash), true, true); + string memory clientDataJSON = + string.concat(clientDataPrefix, '"type":"webauthn.get",', '"challenge":"', challenge, '"}'); + uint256 responseTypeLocation = bytes(clientDataPrefix).length; + uint256 challengeLocation = responseTypeLocation + 22; + bytes32 messageHash = sha256(abi.encodePacked(authenticatorData, sha256(bytes(clientDataJSON)))); + (bytes32 r, bytes32 s) = vm.signP256(P256_KEY, messageHash); + uint256 normalizedS = uint256(s); + if (normalizedS > P256_N / 2) normalizedS = P256_N - normalizedS; + + return + abi.encode( + authenticatorData, clientDataJSON, challengeLocation, responseTypeLocation, uint256(r), normalizedS + ); + } +} diff --git a/test/Overflow_verify.t.sol b/test/Overflow_verify.t.sol new file mode 100644 index 0000000..282817f --- /dev/null +++ b/test/Overflow_verify.t.sol @@ -0,0 +1,63 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import "forge-std/Test.sol"; +import {GasPolicy} from "src/policies/GasPolicy.sol"; +import {PackedUserOperation} from "account-abstraction/interfaces/PackedUserOperation.sol"; +import {SIG_VALIDATION_FAILED_UINT} from "src/types/Constants.sol"; + +/// @notice Regression test for GasPolicy: the gas-cost `maxAmount` must not be computed/compared +/// with an implicit uint128 downcast, since an op whose TRUE uint256 cost is a multiple of 2^128 +/// (residue 0 in the low 128 bits) would truncate to 0 and sail under any nonzero budget while the +/// full multi-billion-gas cost is silently never charged. Comparing the full uint256 +/// product against `allowed` blocks this: the over-cap op is +/// rejected and the budget is left untouched. +contract OverflowVerifyTest is Test { + address constant WALLET = address(0xA11CE); + + GasPolicy policy; + + function setUp() public { + policy = new GasPolicy(); + } + + function test_TF01_OverflowTruncationExploit_IsBlocked() public { + bytes32 id = keccak256("POLICY_ID_1"); + uint128 allowed = 1e18; + + vm.prank(WALLET); + policy.onInstall(abi.encodePacked(id, abi.encode(allowed, false, address(0)))); + + // verificationGasLimit = 2^80, callGasLimit = 0, preVerificationGas = 0, maxFeePerGas = 2^48. + // True cost = 2^80 * 2^48 = 2^128, whose low 128 bits truncate to exactly 0 -- the classic + // uint128-downcast edge case: comparing 0 < allowed would incorrectly pass for free. + uint128 verificationGasLimit = uint128(2 ** 80); + uint128 callGasLimit = 0; + uint128 maxFeePerGas = uint128(2 ** 48); + + uint256 trueCost = (uint256(0) + verificationGasLimit + callGasLimit) * maxFeePerGas; + assertEq(trueCost, 2 ** 128, "true cost should be exactly 2^128"); + assertEq(uint128(trueCost), 0, "low-128 truncated residue is 0 -- the edge case precondition"); + assertGt(trueCost, allowed, "true cost must exceed the installed budget"); + + PackedUserOperation memory userOp = PackedUserOperation({ + sender: WALLET, + nonce: 0, + initCode: "", + callData: "", + accountGasLimits: bytes32(abi.encodePacked(verificationGasLimit, callGasLimit)), + preVerificationGas: 0, + gasFees: bytes32(abi.encodePacked(maxFeePerGas, maxFeePerGas)), + paymasterAndData: "", + signature: "" + }); + + vm.prank(WALLET); + uint256 result = policy.checkUserOpPolicy(id, userOp); + + assertEq(result, SIG_VALIDATION_FAILED_UINT, "over-cap op must be rejected despite zero low-128 residue"); + + (uint128 remaining,,) = policy.gasPolicyConfig(id, WALLET); + assertEq(remaining, allowed, "budget must be untouched -- the exploit must not drain it for free"); + } +} diff --git a/test/P256Signer.t.sol b/test/P256Signer.t.sol new file mode 100644 index 0000000..30f1c4a --- /dev/null +++ b/test/P256Signer.t.sol @@ -0,0 +1,130 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.20; + +import {SignerTestBase} from "test/base/SignerTestBase.sol"; +import {StatelessValidatorTestBase} from "test/base/StatelessValidatorTestBase.sol"; +import {StatelessValidatorWithSenderTestBase} from "test/base/StatelessValidatorWithSenderTestBase.sol"; +import {P256Signer} from "src/signers/P256Signer.sol"; +import {PackedUserOperation} from "account-abstraction/interfaces/PackedUserOperation.sol"; +import {IModule, ISigner, IStatelessValidator} from "src/interfaces/IERC7579Modules.sol"; +import {SIG_VALIDATION_FAILED_UINT, ERC1271_INVALID} from "src/types/Constants.sol"; + +contract P256SignerTest is SignerTestBase, StatelessValidatorTestBase, StatelessValidatorWithSenderTestBase { + uint256 internal constant P256_N = 0xFFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC632551; + uint256 internal constant PRIVATE_KEY = 0xabcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890; + + uint256 internal pubKeyX; + uint256 internal pubKeyY; + + function deployModule() internal override returns (IModule) { + return new P256Signer(); + } + + function _initializeTest() internal override { + (pubKeyX, pubKeyY) = vm.publicKeyP256(PRIVATE_KEY); + } + + function installData() internal view override returns (bytes memory) { + return abi.encode(pubKeyX, pubKeyY); + } + + function userOpSignature(PackedUserOperation memory userOp, bool valid) + internal + view + override + returns (bytes memory) + { + bytes32 hash = ENTRYPOINT.getUserOpHash(userOp); + return _signature(valid ? hash : keccak256(abi.encodePacked("invalid", hash)), PRIVATE_KEY); + } + + function erc1271Signature(bytes32 hash, bool valid) internal pure override returns (address, bytes memory) { + return (address(0), _signature(valid ? hash : keccak256(abi.encodePacked("invalid", hash)), PRIVATE_KEY)); + } + + function statelessValidationSignature(bytes32 hash, bool valid) + internal + pure + override + returns (address, bytes memory) + { + return erc1271Signature(hash, valid); + } + + function statelessValidationSignatureWithSender(bytes32 hash, bool valid) + internal + pure + override + returns (address, bytes memory) + { + return erc1271Signature(hash, valid); + } + + function _afterInstallCheck(bytes32 id) internal view override { + (uint256 x, uint256 y) = P256Signer(address(module)).p256SignerStorage(id, WALLET); + assertEq(x, pubKeyX); + assertEq(y, pubKeyY); + assertTrue(P256Signer(address(module)).isInitialized(id, WALLET)); + } + + function _afterUninstallCheck(bytes32 id) internal view override { + (uint256 x, uint256 y) = P256Signer(address(module)).p256SignerStorage(id, WALLET); + assertEq(x, 0); + assertEq(y, 0); + assertFalse(P256Signer(address(module)).isInitialized(id, WALLET)); + } + + function testOnInstallRejectsInvalidLength() public { + vm.prank(WALLET); + vm.expectRevert(P256Signer.InvalidDataLength.selector); + ISigner(address(module)).onInstall(abi.encodePacked(signerId(), hex"01")); + } + + function testOnInstallRejectsOffCurveKey() public { + vm.prank(WALLET); + vm.expectRevert(P256Signer.InvalidPublicKey.selector); + ISigner(address(module)).onInstall(abi.encodePacked(signerId(), abi.encode(uint256(1), uint256(0)))); + } + + function testUninitializedValidationFailsWithoutReverting() public { + PackedUserOperation memory userOp; + userOp.sender = WALLET; + userOp.signature = _signature(bytes32(uint256(1)), PRIVATE_KEY); + + vm.prank(WALLET); + assertEq( + ISigner(address(module)).checkUserOpSignature(signerId(), userOp, bytes32(uint256(1))), + SIG_VALIDATION_FAILED_UINT + ); + + vm.prank(WALLET); + assertEq( + ISigner(address(module)).checkSignature(signerId(), address(0), bytes32(uint256(1)), userOp.signature), + ERC1271_INVALID + ); + } + + function testStatelessValidationUsesSuppliedKeyWithoutInstall() public view { + uint256 otherKey = PRIVATE_KEY + 1; + (uint256 otherX, uint256 otherY) = vm.publicKeyP256(otherKey); + bytes32 hash = keccak256("stateless P256 signer"); + + assertTrue( + IStatelessValidator(address(module)) + .validateSignatureWithData(hash, _signature(hash, otherKey), abi.encode(otherX, otherY)) + ); + } + + function testStatelessValidationRejectsMalformedSignature() public view { + assertFalse( + IStatelessValidator(address(module)).validateSignatureWithData(bytes32(uint256(1)), hex"01", installData()) + ); + } + + function _signature(bytes32 hash, uint256 privateKey) internal pure returns (bytes memory) { + (bytes32 r, bytes32 s) = vm.signP256(privateKey, hash); + uint256 normalizedS = uint256(s); + if (normalizedS > P256_N / 2) normalizedS = P256_N - normalizedS; + return abi.encode(r, bytes32(normalizedS)); + } +} diff --git a/test/P256Validator.t.sol b/test/P256Validator.t.sol new file mode 100644 index 0000000..3861da9 --- /dev/null +++ b/test/P256Validator.t.sol @@ -0,0 +1,145 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.20; + +import {ValidatorTestBase} from "test/base/ValidatorTestBase.sol"; +import {StatelessValidatorTestBase} from "test/base/StatelessValidatorTestBase.sol"; +import {StatelessValidatorWithSenderTestBase} from "test/base/StatelessValidatorWithSenderTestBase.sol"; +import {P256Validator} from "src/validators/P256Validator.sol"; +import {PackedUserOperation} from "account-abstraction/interfaces/PackedUserOperation.sol"; +import {IModule, IValidator, IStatelessValidator} from "src/interfaces/IERC7579Modules.sol"; +import {SIG_VALIDATION_FAILED_UINT, ERC1271_INVALID} from "src/types/Constants.sol"; + +contract P256ValidatorTest is ValidatorTestBase, StatelessValidatorTestBase, StatelessValidatorWithSenderTestBase { + uint256 internal constant P256_N = 0xFFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC632551; + uint256 internal constant PRIVATE_KEY = 0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef; + + uint256 internal pubKeyX; + uint256 internal pubKeyY; + + function deployModule() internal override returns (IModule) { + return new P256Validator(); + } + + function _initializeTest() internal override { + (pubKeyX, pubKeyY) = vm.publicKeyP256(PRIVATE_KEY); + } + + function installData() internal view override returns (bytes memory) { + return abi.encode(pubKeyX, pubKeyY); + } + + function userOpSignature(PackedUserOperation memory userOp, bool valid) + internal + view + override + returns (bytes memory) + { + bytes32 hash = ENTRYPOINT.getUserOpHash(userOp); + return _signature(valid ? hash : keccak256(abi.encodePacked("invalid", hash)), PRIVATE_KEY); + } + + function erc1271Signature(bytes32 hash, bool valid) internal pure override returns (address, bytes memory) { + return (address(0), _signature(valid ? hash : keccak256(abi.encodePacked("invalid", hash)), PRIVATE_KEY)); + } + + function statelessValidationSignature(bytes32 hash, bool valid) + internal + pure + override + returns (address, bytes memory) + { + return erc1271Signature(hash, valid); + } + + function statelessValidationSignatureWithSender(bytes32 hash, bool valid) + internal + pure + override + returns (address, bytes memory) + { + return erc1271Signature(hash, valid); + } + + function _afterInstallCheck() internal view override { + (uint256 x, uint256 y) = P256Validator(address(module)).p256ValidatorStorage(WALLET); + assertEq(x, pubKeyX); + assertEq(y, pubKeyY); + assertTrue(P256Validator(address(module)).isInitialized(WALLET)); + } + + function _afterUninstallCheck() internal view override { + (uint256 x, uint256 y) = P256Validator(address(module)).p256ValidatorStorage(WALLET); + assertEq(x, 0); + assertEq(y, 0); + assertFalse(P256Validator(address(module)).isInitialized(WALLET)); + } + + function testOnInstallRejectsInvalidLength() public { + vm.prank(WALLET); + vm.expectRevert(P256Validator.InvalidDataLength.selector); + IValidator(address(module)).onInstall(hex"01"); + } + + function testOnInstallRejectsOffCurveKey() public { + vm.prank(WALLET); + vm.expectRevert(P256Validator.InvalidPublicKey.selector); + IValidator(address(module)).onInstall(abi.encode(uint256(0), uint256(1))); + } + + function testUninitializedValidationFailsWithoutReverting() public { + PackedUserOperation memory userOp; + userOp.sender = WALLET; + userOp.signature = _signature(bytes32(uint256(1)), PRIVATE_KEY); + + vm.prank(WALLET); + assertEq(IValidator(address(module)).validateUserOp(userOp, bytes32(uint256(1))), SIG_VALIDATION_FAILED_UINT); + + vm.prank(WALLET); + assertEq( + IValidator(address(module)).isValidSignatureWithSender(address(0), bytes32(uint256(1)), userOp.signature), + ERC1271_INVALID + ); + } + + function testMalformedSignatureFailsWithoutReverting() public { + vm.prank(WALLET); + IValidator(address(module)).onInstall(installData()); + + vm.prank(WALLET); + assertEq( + IValidator(address(module)).isValidSignatureWithSender(address(0), bytes32(uint256(1)), hex"01"), + ERC1271_INVALID + ); + } + + function testStatelessValidationUsesSuppliedKeyWithoutInstall() public view { + uint256 otherKey = PRIVATE_KEY + 1; + (uint256 otherX, uint256 otherY) = vm.publicKeyP256(otherKey); + bytes32 hash = keccak256("stateless P256 validator"); + + assertTrue( + IStatelessValidator(address(module)) + .validateSignatureWithData(hash, _signature(hash, otherKey), abi.encode(otherX, otherY)) + ); + } + + function testStatelessValidationRejectsMalformedConfig() public view { + assertFalse(IStatelessValidator(address(module)).validateSignatureWithData(bytes32(uint256(1)), hex"", hex"01")); + } + + function testHighSValueIsRejected() public view { + bytes32 hash = keccak256("high s"); + (bytes32 r, bytes32 s) = vm.signP256(PRIVATE_KEY, hash); + uint256 normalizedS = uint256(s) > P256_N / 2 ? P256_N - uint256(s) : uint256(s); + bytes memory highSignature = abi.encode(r, bytes32(P256_N - normalizedS)); + + assertFalse(IStatelessValidator(address(module)).validateSignatureWithData(hash, highSignature, installData())); + } + + function _signature(bytes32 hash, uint256 privateKey) internal pure returns (bytes memory) { + (bytes32 r, bytes32 s) = vm.signP256(privateKey, hash); + uint256 normalizedS = uint256(s); + if (normalizedS > P256_N / 2) normalizedS = P256_N - normalizedS; + return abi.encode(r, bytes32(normalizedS)); + } +} diff --git a/test/RateLimitPolicy.t.sol b/test/RateLimitPolicy.t.sol new file mode 100644 index 0000000..99bbf49 --- /dev/null +++ b/test/RateLimitPolicy.t.sol @@ -0,0 +1,276 @@ +pragma solidity ^0.8.20; + +import {PolicyTestBase} from "./base/PolicyTestBase.sol"; +import {RateLimitPolicy, Status} from "src/policies/RateLimitPolicy.sol"; +import {PackedUserOperation} from "account-abstraction/interfaces/PackedUserOperation.sol"; +import {IModule} from "src/interfaces/IERC7579Modules.sol"; +import {SIG_VALIDATION_SUCCESS_UINT} from "src/types/Constants.sol"; + +contract RateLimitPolicyTest is PolicyTestBase { + uint48 constant INTERVAL = 100; + uint48 constant INITIAL_COUNT = 3; + + RateLimitPolicy policy; + + function deployModule() internal virtual override returns (IModule) { + policy = new RateLimitPolicy(); + return policy; + } + + function _initializeTest() internal override {} + + function installData() internal view override returns (bytes memory) { + return abi.encodePacked(bytes6(INTERVAL), bytes6(INITIAL_COUNT)); + } + + function _dummyUserOp() internal view returns (PackedUserOperation memory) { + return PackedUserOperation({ + sender: WALLET, + nonce: 0, + initCode: "", + callData: "", + accountGasLimits: bytes32(abi.encodePacked(uint128(100000), uint128(200000))), + preVerificationGas: 0, + gasFees: bytes32(abi.encodePacked(uint128(1), uint128(1))), + paymasterAndData: "", + signature: "" + }); + } + + function validUserOp() internal view virtual override returns (PackedUserOperation memory) { + return _dummyUserOp(); + } + + function invalidUserOp() internal view virtual override returns (PackedUserOperation memory) { + return _dummyUserOp(); + } + + function validSignatureData(bytes32) internal view virtual override returns (address, bytes memory) { + return (WALLET, ""); + } + + function invalidSignatureData(bytes32) internal view virtual override returns (address, bytes memory) { + return (WALLET, ""); + } + + function _afterInstallCheck(bytes32 id) internal virtual override { + assertEq(uint8(policy.status(id, WALLET)), uint8(Status.Live), "status should be Live after install"); + (uint48 interval, uint48 initialCount) = policy.rateLimitConfigs(id, WALLET); + assertEq(interval, INTERVAL, "interval mismatch"); + assertEq(initialCount, INITIAL_COUNT, "initialCount mismatch"); + (uint48 storedCount, uint48 resetDate) = policy.rateLimitState(id, WALLET); + assertEq(storedCount, INITIAL_COUNT, "storedCount should start at initialCount"); + assertEq(resetDate, uint48(block.timestamp) + INTERVAL, "resetDate should be now + interval"); + } + + function _afterUninstallCheck(bytes32 id) internal virtual override { + assertEq( + uint8(policy.status(id, WALLET)), uint8(Status.Deprecated), "status should be Deprecated after uninstall" + ); + } + + // checkUserOpPolicy always returns a non-zero packed validation timestamp on success (never + // SIG_VALIDATION_SUCCESS_UINT == 0), so the base "success" test's `assertEq(result, 0)` does + // not hold for this policy. Override with an assertion of the real success shape. + function testPolicyAfterInstallCheckUserOpPolicySuccess() public payable override { + bytes32 id = policyId(); + vm.startPrank(WALLET); + policy.onInstall(abi.encodePacked(id, installData())); + + uint256 validationResult = policy.checkUserOpPolicy(id, validUserOp()); + vm.stopPrank(); + assertFalse(validationResult == 0, "success returns a nonzero packed validAfter/validUntil"); + } + + // checkUserOpPolicy does not gate on Status.Live, so the base "fail" test (which asserts a + // non-zero return for `invalidUserOp`) does not apply here — there is no userOp-shape based + // failure. Override with a revert-based assertion of the real failure mode: RateLimited(). + function testPolicyAfterInstallCheckUserOpPolicyFail() public payable override { + bytes32 id = policyId(); + vm.startPrank(WALLET); + policy.onInstall(abi.encodePacked(id, installData())); + + PackedUserOperation memory userOp = _dummyUserOp(); + for (uint256 i = 0; i < INITIAL_COUNT; i++) { + policy.checkUserOpPolicy(id, userOp); + } + + vm.expectRevert(RateLimitPolicy.RateLimited.selector); + policy.checkUserOpPolicy(id, userOp); + vm.stopPrank(); + } + + // checkSignaturePolicy returns SIG_VALIDATION_SUCCESS_UINT unconditionally (see + // RateLimitPolicy.checkSignaturePolicy) — there is no signature-shape based failure to + // model, so the base "fail" test's premise (a distinguishable invalid signature) does not + // apply. Override to assert the real, unconditional-success behavior instead. + function testPolicyCheckSignaturePolicyFail() public payable override { + bytes32 id = policyId(); + vm.startPrank(WALLET); + policy.onInstall(abi.encodePacked(id, installData())); + + bytes32 testHash = keccak256(abi.encodePacked("TEST_HASH")); + (address sender, bytes memory sigData) = invalidSignatureData(testHash); + + uint256 result = policy.checkSignaturePolicy(id, sender, testHash, sigData); + vm.stopPrank(); + assertEq(result, SIG_VALIDATION_SUCCESS_UINT, "checkSignaturePolicy always succeeds, even for 'invalid' inputs"); + } + + function test_onInstall_RevertWhen_DataTooShort() public { + bytes32 id = policyId(); + bytes memory shortData = abi.encodePacked(bytes6(INTERVAL), bytes5(uint40(1))); + vm.prank(WALLET); + vm.expectRevert(RateLimitPolicy.InvalidInstallData.selector); + policy.onInstall(abi.encodePacked(id, shortData)); + } + + function test_onInstall_RevertWhen_ExactlyTooShort() public { + // 11 bytes total is one short of the 12-byte minimum. + bytes32 id = policyId(); + bytes memory shortData = new bytes(11); + vm.prank(WALLET); + vm.expectRevert(RateLimitPolicy.InvalidInstallData.selector); + policy.onInstall(abi.encodePacked(id, shortData)); + } + + function test_onInstall_AllowsExtraTrailingBytes() public { + // >= 12 bytes is accepted; extra bytes beyond the first 12 are ignored. + bytes32 id = policyId(); + bytes memory data = abi.encodePacked(bytes6(INTERVAL), bytes6(INITIAL_COUNT), bytes1(0xAB)); + vm.prank(WALLET); + policy.onInstall(abi.encodePacked(id, data)); + _afterInstallCheck(id); + } + + function test_checkUserOpPolicy_DecrementsStoredCount() public { + bytes32 id = policyId(); + vm.startPrank(WALLET); + policy.onInstall(abi.encodePacked(id, installData())); + + PackedUserOperation memory userOp = _dummyUserOp(); + policy.checkUserOpPolicy(id, userOp); + (uint48 storedCount,) = policy.rateLimitState(id, WALLET); + assertEq(storedCount, INITIAL_COUNT - 1, "storedCount should decrement by 1"); + vm.stopPrank(); + } + + function test_checkUserOpPolicy_ReturnsPackedValidationData() public { + bytes32 id = policyId(); + vm.startPrank(WALLET); + policy.onInstall(abi.encodePacked(id, installData())); + + uint256 expectedResetDate = block.timestamp + INTERVAL; + uint256 validationData = policy.checkUserOpPolicy(id, _dummyUserOp()); + vm.stopPrank(); + + uint48 validAfter = uint48(validationData >> 208); + uint48 validUntil = uint48(validationData >> 160); + assertEq(validAfter, uint48(block.timestamp), "validAfter should be current time"); + assertEq(validUntil, uint48(expectedResetDate), "validUntil should be resetDate"); + } + + function test_checkUserOpPolicy_RevertWhen_BudgetExhausted() public { + bytes32 id = policyId(); + vm.startPrank(WALLET); + policy.onInstall(abi.encodePacked(id, installData())); + + PackedUserOperation memory userOp = _dummyUserOp(); + for (uint256 i = 0; i < INITIAL_COUNT; i++) { + policy.checkUserOpPolicy(id, userOp); + } + (uint48 storedCount,) = policy.rateLimitState(id, WALLET); + assertEq(storedCount, 0, "storedCount should be exhausted"); + + vm.expectRevert(RateLimitPolicy.RateLimited.selector); + policy.checkUserOpPolicy(id, userOp); + vm.stopPrank(); + } + + function test_checkUserOpPolicy_RefillsAfterWindowElapses() public { + bytes32 id = policyId(); + vm.startPrank(WALLET); + policy.onInstall(abi.encodePacked(id, installData())); + + PackedUserOperation memory userOp = _dummyUserOp(); + for (uint256 i = 0; i < INITIAL_COUNT; i++) { + policy.checkUserOpPolicy(id, userOp); + } + vm.expectRevert(RateLimitPolicy.RateLimited.selector); + policy.checkUserOpPolicy(id, userOp); + + // Warp past the reset window; budget should refill to initialCount and succeed again. + vm.warp(block.timestamp + INTERVAL); + uint256 validationData = policy.checkUserOpPolicy(id, userOp); + vm.stopPrank(); + + (uint48 storedCount, uint48 resetDate) = policy.rateLimitState(id, WALLET); + // One op was consumed after the refill, so storedCount = initialCount - 1. + assertEq(storedCount, INITIAL_COUNT - 1, "storedCount should refill then decrement"); + assertEq(resetDate, uint48(block.timestamp) + INTERVAL, "resetDate should be pushed forward"); + + uint48 validAfter = uint48(validationData >> 208); + uint48 validUntil = uint48(validationData >> 160); + assertEq(validAfter, uint48(block.timestamp), "validAfter should be new current time"); + assertEq(validUntil, resetDate, "validUntil should be new resetDate"); + } + + function test_checkUserOpPolicy_RefillExactlyAtResetDate() public { + // Boundary: block.timestamp == state.resetDate triggers the refill branch (>=). + bytes32 id = policyId(); + vm.startPrank(WALLET); + policy.onInstall(abi.encodePacked(id, installData())); + (, uint48 resetDateBefore) = policy.rateLimitState(id, WALLET); + + vm.warp(resetDateBefore); + policy.checkUserOpPolicy(id, _dummyUserOp()); + (uint48 storedCount,) = policy.rateLimitState(id, WALLET); + // Refilled to INITIAL_COUNT then decremented once. + assertEq(storedCount, INITIAL_COUNT - 1, "storedCount should refill exactly at resetDate boundary"); + vm.stopPrank(); + } + + function test_checkSignaturePolicy_AlwaysReturnsSuccess() public { + bytes32 id = policyId(); + vm.prank(WALLET); + policy.onInstall(abi.encodePacked(id, installData())); + + uint256 result = policy.checkSignaturePolicy(id, WALLET, keccak256("hash"), ""); + assertEq(result, SIG_VALIDATION_SUCCESS_UINT, "checkSignaturePolicy should always succeed"); + } + + function test_checkSignaturePolicy_ReturnsSuccessEvenWithoutInstall() public { + // checkSignaturePolicy is unconditional and does not check status. + uint256 result = policy.checkSignaturePolicy(policyId(), WALLET, keccak256("hash"), ""); + assertEq(result, SIG_VALIDATION_SUCCESS_UINT, "checkSignaturePolicy should succeed regardless of status"); + } + + function test_onInstall_RevertWhen_AlreadyLive() public { + bytes32 id = policyId(); + vm.startPrank(WALLET); + policy.onInstall(abi.encodePacked(id, installData())); + vm.expectRevert(); + policy.onInstall(abi.encodePacked(id, installData())); + vm.stopPrank(); + } + + function test_onInstall_AllowedAfterUninstall() public { + bytes32 id = policyId(); + vm.startPrank(WALLET); + policy.onInstall(abi.encodePacked(id, installData())); + policy.onUninstall(abi.encodePacked(id, installData())); + assertEq(uint8(policy.status(id, WALLET)), uint8(Status.Deprecated), "should be Deprecated"); + + // Re-install allowed since status != Live. + policy.onInstall(abi.encodePacked(id, installData())); + assertEq(uint8(policy.status(id, WALLET)), uint8(Status.Live), "should be Live again after re-install"); + vm.stopPrank(); + } + + function test_onUninstall_RevertWhen_NotLive() public { + bytes32 id = policyId(); + vm.prank(WALLET); + vm.expectRevert(); + policy.onUninstall(abi.encodePacked(id, installData())); + } +} diff --git a/test/RecoveryAction.t.sol b/test/RecoveryAction.t.sol new file mode 100644 index 0000000..1f84023 --- /dev/null +++ b/test/RecoveryAction.t.sol @@ -0,0 +1,102 @@ +pragma solidity ^0.8.20; + +import {Test} from "forge-std/Test.sol"; +import {RecoveryAction} from "src/actions/RecoveryAction.sol"; +import {MockValidator} from "./mocks/MockValidator.sol"; + +contract RecoveryActionTest is Test { + RecoveryAction internal action; + MockValidator internal validator; + + function setUp() public { + action = new RecoveryAction(); + validator = new MockValidator(); + } + + function test_doRecovery_CallsOnUninstallThenOnInstall() public { + bytes memory newConfig = abi.encode(address(0xBEEF)); + + action.doRecovery(address(validator), newConfig); + + assertEq(validator.onUninstallCallCount(), 1, "onUninstall should be called exactly once"); + assertEq(validator.onInstallCallCount(), 1, "onInstall should be called exactly once"); + } + + function test_doRecovery_PassesEmptyBytesToOnUninstall() public { + bytes memory newConfig = abi.encode(address(0xBEEF)); + + action.doRecovery(address(validator), newConfig); + + assertEq(validator.lastOnUninstallData(), hex"", "onUninstall must receive empty calldata"); + } + + function test_doRecovery_PassesDataThroughToOnInstall() public { + bytes memory newConfig = abi.encode(address(0xCAFE), uint256(42)); + + action.doRecovery(address(validator), newConfig); + + assertEq(validator.lastOnInstallData(), newConfig, "onInstall must receive the passed _data unchanged"); + } + + function test_doRecovery_CallsOnUninstallBeforeOnInstall() public { + bytes memory newConfig = abi.encode(address(0xCAFE)); + + action.doRecovery(address(validator), newConfig); + + assertLt( + validator.onUninstallCallOrder(), + validator.onInstallCallOrder(), + "onUninstall must be called strictly before onInstall" + ); + } + + function test_doRecovery_WithEmptyData_ForwardsEmptyDataToOnInstall() public { + action.doRecovery(address(validator), hex""); + + assertEq(validator.onInstallCallCount(), 1, "onInstall should still be invoked with empty data"); + assertEq(validator.lastOnInstallData(), hex"", "onInstall should receive empty bytes as-is"); + } + + function test_doRecovery_WhenValidatorReverts_PropagatesRevert() public { + RevertingValidator revertingValidator = new RevertingValidator(); + + vm.expectRevert(RevertingValidator.AlwaysReverts.selector); + action.doRecovery(address(revertingValidator), ""); + } + + function test_doRecovery_WhenOnUninstallReverts_OnInstallIsNeverCalled() public { + // onUninstall reverts before onInstall would run, so onInstall must never be reached. + RevertOnUninstallValidator revertingValidator = new RevertOnUninstallValidator(); + + vm.expectRevert(RevertOnUninstallValidator.UninstallReverts.selector); + action.doRecovery(address(revertingValidator), ""); + + assertEq(revertingValidator.onInstallCallCount(), 0, "onInstall must not be called if onUninstall reverts"); + } +} + +contract RevertingValidator { + error AlwaysReverts(); + + function onUninstall(bytes calldata) external pure { + revert AlwaysReverts(); + } + + function onInstall(bytes calldata) external pure { + revert AlwaysReverts(); + } +} + +contract RevertOnUninstallValidator { + error UninstallReverts(); + + uint256 public onInstallCallCount; + + function onUninstall(bytes calldata) external pure { + revert UninstallReverts(); + } + + function onInstall(bytes calldata) external { + onInstallCallCount++; + } +} diff --git a/test/SudoPolicy.t.sol b/test/SudoPolicy.t.sol new file mode 100644 index 0000000..1949423 --- /dev/null +++ b/test/SudoPolicy.t.sol @@ -0,0 +1,132 @@ +pragma solidity ^0.8.20; + +import {PolicyTestBase} from "./base/PolicyTestBase.sol"; +import {SudoPolicy} from "src/policies/SudoPolicy.sol"; +import {PackedUserOperation} from "account-abstraction/interfaces/PackedUserOperation.sol"; +import {IModule, IPolicy} from "src/interfaces/IERC7579Modules.sol"; +import {SIG_VALIDATION_SUCCESS_UINT} from "src/types/Constants.sol"; + +contract SudoPolicyTest is PolicyTestBase { + function deployModule() internal virtual override returns (IModule) { + return new SudoPolicy(); + } + + function _initializeTest() internal override {} + + function installData() internal view virtual override returns (bytes memory) { + return ""; + } + + function validUserOp() internal view virtual override returns (PackedUserOperation memory) { + return PackedUserOperation({ + sender: WALLET, + nonce: 0, + initCode: "", + callData: "", + accountGasLimits: bytes32(abi.encodePacked(uint128(100000), uint128(200000))), + preVerificationGas: 0, + gasFees: bytes32(abi.encodePacked(uint128(1), uint128(1))), + paymasterAndData: "", + signature: "" + }); + } + + function invalidUserOp() internal view virtual override returns (PackedUserOperation memory) { + // SudoPolicy has no fail path; kept for interface parity only. + return validUserOp(); + } + + function validSignatureData(bytes32) + internal + view + virtual + override + returns (address sender, bytes memory signature) + { + return (WALLET, ""); + } + + function invalidSignatureData(bytes32) + internal + view + virtual + override + returns (address sender, bytes memory signature) + { + // SudoPolicy has no fail path; kept for interface parity only. + return (WALLET, ""); + } + + // SudoPolicy's onInstall is a true no-op (no stored state), so installing the same + // policy id twice does NOT revert — unlike stateful policies (e.g. CallerPolicy) that + // track an installed/live status per id. Override to assert the real no-op behavior + // instead of the stateful-policy default inherited from PolicyTestBase. + function testPolicyOnInstallFailSameId() public payable override { + IPolicy policyModule = IPolicy(address(module)); + vm.startPrank(WALLET); + policyModule.onInstall(abi.encodePacked(policyId(), installData())); + // Second install with the same id must succeed silently since _policyOninstall is a no-op. + policyModule.onInstall(abi.encodePacked(policyId(), installData())); + vm.stopPrank(); + } + + // SudoPolicy always returns SIG_VALIDATION_SUCCESS_UINT regardless of userOp content — + // there is no way to make checkUserOpPolicy fail, so override to assert the real spec. + function testPolicyAfterInstallCheckUserOpPolicyFail() public payable override { + IPolicy policyModule = IPolicy(address(module)); + vm.startPrank(WALLET); + policyModule.onInstall(abi.encodePacked(policyId(), installData())); + + PackedUserOperation memory userOp = invalidUserOp(); + uint256 validationResult = policyModule.checkUserOpPolicy(policyId(), userOp); + vm.stopPrank(); + assertEq(validationResult, SIG_VALIDATION_SUCCESS_UINT, "SudoPolicy must always approve userOps"); + } + + // Same reasoning for signature checks — SudoPolicy has no fail path. + function testPolicyCheckSignaturePolicyFail() public payable override { + IPolicy policyModule = IPolicy(address(module)); + vm.startPrank(WALLET); + policyModule.onInstall(abi.encodePacked(policyId(), installData())); + + bytes32 testHash = keccak256(abi.encodePacked("TEST_HASH")); + (address sender, bytes memory sigData) = invalidSignatureData(testHash); + uint256 result = policyModule.checkSignaturePolicy(policyId(), sender, testHash, sigData); + vm.stopPrank(); + assertEq(result, SIG_VALIDATION_SUCCESS_UINT, "SudoPolicy must always approve signatures"); + } + + // checkUserOpPolicy/checkSignaturePolicy must also succeed without any prior onInstall, + // since SudoPolicy's approval does not depend on install state at all. + function test_checkUserOpPolicy_WithoutInstall_StillSucceeds() public { + IPolicy policyModule = IPolicy(address(module)); + PackedUserOperation memory userOp = validUserOp(); + + uint256 result = policyModule.checkUserOpPolicy(policyId(), userOp); + assertEq(result, SIG_VALIDATION_SUCCESS_UINT, "SudoPolicy should approve even without install"); + } + + function test_checkSignaturePolicy_WithoutInstall_StillSucceeds() public view { + IPolicy policyModule = IPolicy(address(module)); + bytes32 testHash = keccak256(abi.encodePacked("TEST_HASH")); + + uint256 result = policyModule.checkSignaturePolicy(policyId(), WALLET, testHash, ""); + assertEq(result, SIG_VALIDATION_SUCCESS_UINT, "SudoPolicy should approve even without install"); + } + + // Ensure onInstall/onUninstall are true no-ops: calling with only the 32-byte id + // (empty tail data) must not revert, covering the empty _policyOninstall/_policyOnUninstall bodies. + function test_onInstall_WithEmptyData_DoesNotRevert() public { + IPolicy policyModule = IPolicy(address(module)); + vm.prank(WALLET); + policyModule.onInstall(abi.encodePacked(policyId())); + } + + function test_onUninstall_WithEmptyData_DoesNotRevert() public { + IPolicy policyModule = IPolicy(address(module)); + vm.startPrank(WALLET); + policyModule.onInstall(abi.encodePacked(policyId())); + policyModule.onUninstall(abi.encodePacked(policyId())); + vm.stopPrank(); + } +} diff --git a/test/ThrottlePolicy.t.sol b/test/ThrottlePolicy.t.sol new file mode 100644 index 0000000..bfdc860 --- /dev/null +++ b/test/ThrottlePolicy.t.sol @@ -0,0 +1,292 @@ +pragma solidity ^0.8.20; + +import {PolicyTestBase} from "./base/PolicyTestBase.sol"; +import {ThrottlePolicy, Status} from "src/policies/ThrottlePolicy.sol"; +import {ValidAfter} from "src/types/Types.sol"; +import {PackedUserOperation} from "account-abstraction/interfaces/PackedUserOperation.sol"; +import {IModule} from "src/interfaces/IERC7579Modules.sol"; +import {SIG_VALIDATION_SUCCESS_UINT, SIG_VALIDATION_FAILED_UINT} from "src/types/Constants.sol"; + +contract ThrottlePolicyTest is PolicyTestBase { + uint48 constant INTERVAL = 100; + uint48 constant COUNT = 3; + uint48 constant START_AT = 1000; + + ThrottlePolicy policy; + + function deployModule() internal virtual override returns (IModule) { + policy = new ThrottlePolicy(); + return policy; + } + + function _initializeTest() internal override {} + + function installData() internal view override returns (bytes memory) { + return abi.encodePacked(bytes6(INTERVAL), bytes6(COUNT), bytes6(START_AT)); + } + + function _dummyUserOp() internal view returns (PackedUserOperation memory) { + return PackedUserOperation({ + sender: WALLET, + nonce: 0, + initCode: "", + callData: "", + accountGasLimits: bytes32(abi.encodePacked(uint128(100000), uint128(200000))), + preVerificationGas: 0, + gasFees: bytes32(abi.encodePacked(uint128(1), uint128(1))), + paymasterAndData: "", + signature: "" + }); + } + + function validUserOp() internal view virtual override returns (PackedUserOperation memory) { + return _dummyUserOp(); + } + + function invalidUserOp() internal view virtual override returns (PackedUserOperation memory) { + return _dummyUserOp(); + } + + function validSignatureData(bytes32) internal view virtual override returns (address, bytes memory) { + return (WALLET, ""); + } + + function invalidSignatureData(bytes32) internal view virtual override returns (address, bytes memory) { + return (WALLET, ""); + } + + function _afterInstallCheck(bytes32 id) internal virtual override { + assertEq(uint8(policy.status(id, WALLET)), uint8(Status.Live), "status should be Live after install"); + (uint48 interval, uint48 count, ValidAfter startAt) = policy.throttleConfigs(id, WALLET); + assertEq(interval, INTERVAL, "interval mismatch"); + assertEq(count, COUNT, "count mismatch"); + assertEq(ValidAfter.unwrap(startAt), START_AT, "startAt mismatch"); + } + + function _afterUninstallCheck(bytes32 id) internal virtual override { + assertEq( + uint8(policy.status(id, WALLET)), uint8(Status.Deprecated), "status should be Deprecated after uninstall" + ); + } + + // checkUserOpPolicy returns a nonzero packed validAfter on success (never + // SIG_VALIDATION_SUCCESS_UINT == 0), so the base "success" test's `assertEq(result, 0)` does + // not hold. Override with an assertion of the real success shape. + function testPolicyAfterInstallCheckUserOpPolicySuccess() public payable override { + bytes32 id = policyId(); + vm.startPrank(WALLET); + policy.onInstall(abi.encodePacked(id, installData())); + + uint256 validationResult = policy.checkUserOpPolicy(id, validUserOp()); + vm.stopPrank(); + assertFalse(validationResult == 0, "success returns a nonzero packed validAfter"); + } + + // ThrottlePolicy's checkUserOpPolicy does not fail on userOp shape — the base fail-test + // (asserting a non-zero return for `invalidUserOp`) does not model this contract's real + // failure mode. Override with the real exhausted-budget failure path (returns 1, not revert). + function testPolicyAfterInstallCheckUserOpPolicyFail() public payable override { + bytes32 id = policyId(); + vm.startPrank(WALLET); + policy.onInstall(abi.encodePacked(id, installData())); + + PackedUserOperation memory userOp = _dummyUserOp(); + for (uint256 i = 0; i < COUNT; i++) { + policy.checkUserOpPolicy(id, userOp); + } + uint256 result = policy.checkUserOpPolicy(id, userOp); + vm.stopPrank(); + assertEq(result, SIG_VALIDATION_FAILED_UINT, "should return failure once count is exhausted"); + } + + // checkSignaturePolicy returns SIG_VALIDATION_SUCCESS_UINT unconditionally once Live (see + // ThrottlePolicy.checkSignaturePolicy) — there is no signature-shape based failure to model + // with a valid/invalid signature pair, so the base "fail" test's premise does not apply. + // Override to assert the real, unconditional-success-when-Live behavior instead. + function testPolicyCheckSignaturePolicyFail() public payable override { + bytes32 id = policyId(); + vm.startPrank(WALLET); + policy.onInstall(abi.encodePacked(id, installData())); + + bytes32 testHash = keccak256(abi.encodePacked("TEST_HASH")); + (address sender, bytes memory sigData) = invalidSignatureData(testHash); + + uint256 result = policy.checkSignaturePolicy(id, sender, testHash, sigData); + vm.stopPrank(); + assertEq(result, SIG_VALIDATION_SUCCESS_UINT, "checkSignaturePolicy always succeeds when Live"); + } + + function test_onInstall_SetsConfigAndStatus() public { + bytes32 id = policyId(); + vm.prank(WALLET); + policy.onInstall(abi.encodePacked(id, installData())); + _afterInstallCheck(id); + } + + function test_onInstall_RevertWhen_AlreadyLive() public { + bytes32 id = policyId(); + vm.startPrank(WALLET); + policy.onInstall(abi.encodePacked(id, installData())); + vm.expectRevert(); + policy.onInstall(abi.encodePacked(id, installData())); + vm.stopPrank(); + } + + function test_onInstall_RevertWhen_Deprecated() public { + bytes32 id = policyId(); + vm.startPrank(WALLET); + policy.onInstall(abi.encodePacked(id, installData())); + policy.onUninstall(abi.encodePacked(id, installData())); + assertEq(uint8(policy.status(id, WALLET)), uint8(Status.Deprecated), "should be Deprecated"); + + // Status.NA is required for install; Deprecated is not NA, so re-install must revert. + vm.expectRevert(); + policy.onInstall(abi.encodePacked(id, installData())); + vm.stopPrank(); + } + + function test_onUninstall_RevertWhen_NotLive() public { + bytes32 id = policyId(); + vm.prank(WALLET); + vm.expectRevert(); + policy.onUninstall(abi.encodePacked(id, installData())); + } + + function test_checkUserOpPolicy_RevertWhen_NotLive() public { + bytes32 id = policyId(); + vm.prank(WALLET); + vm.expectRevert(); + policy.checkUserOpPolicy(id, _dummyUserOp()); + } + + function test_checkUserOpPolicy_DecrementsCountAndAdvancesStartAt() public { + bytes32 id = policyId(); + vm.startPrank(WALLET); + policy.onInstall(abi.encodePacked(id, installData())); + + uint256 validationData = policy.checkUserOpPolicy(id, _dummyUserOp()); + vm.stopPrank(); + + (, uint48 count, ValidAfter startAt) = policy.throttleConfigs(id, WALLET); + assertEq(count, COUNT - 1, "count should decrement by 1"); + assertEq(ValidAfter.unwrap(startAt), START_AT + INTERVAL, "startAt should advance by interval"); + + // Returned validAfter must be the PRE-increment startAt, validUntil must be 0. + uint48 returnedValidAfter = uint48(validationData >> 208); + uint48 returnedValidUntil = uint48(validationData >> 160); + assertEq(returnedValidAfter, START_AT, "returned validAfter should be pre-increment startAt"); + assertEq(returnedValidUntil, 0, "returned validUntil should always be 0"); + } + + function test_checkUserOpPolicy_SuccessiveCallsAdvanceStartAtEachTime() public { + bytes32 id = policyId(); + vm.startPrank(WALLET); + policy.onInstall(abi.encodePacked(id, installData())); + + PackedUserOperation memory userOp = _dummyUserOp(); + + uint256 v1 = policy.checkUserOpPolicy(id, userOp); + uint48 validAfter1 = uint48(v1 >> 208); + assertEq(validAfter1, START_AT, "first call returns original startAt"); + + uint256 v2 = policy.checkUserOpPolicy(id, userOp); + uint48 validAfter2 = uint48(v2 >> 208); + assertEq(validAfter2, START_AT + INTERVAL, "second call returns startAt advanced by one interval"); + + uint256 v3 = policy.checkUserOpPolicy(id, userOp); + uint48 validAfter3 = uint48(v3 >> 208); + assertEq(validAfter3, START_AT + 2 * INTERVAL, "third call returns startAt advanced by two intervals"); + + (, uint48 count,) = policy.throttleConfigs(id, WALLET); + assertEq(count, 0, "count should be fully exhausted after COUNT calls"); + vm.stopPrank(); + } + + function test_checkUserOpPolicy_ReturnsFailureWhenCountExhausted() public { + bytes32 id = policyId(); + vm.startPrank(WALLET); + policy.onInstall(abi.encodePacked(id, installData())); + + PackedUserOperation memory userOp = _dummyUserOp(); + for (uint256 i = 0; i < COUNT; i++) { + policy.checkUserOpPolicy(id, userOp); + } + + (, uint48 countBefore, ValidAfter startAtBefore) = policy.throttleConfigs(id, WALLET); + assertEq(countBefore, 0, "count should be 0 before the exhausted call"); + + uint256 result = policy.checkUserOpPolicy(id, userOp); + assertEq(result, SIG_VALIDATION_FAILED_UINT, "should return SIG_VALIDATION_FAILED_UINT when count is 0"); + + // Exhausted path must not mutate config further. + (, uint48 countAfter, ValidAfter startAtAfter) = policy.throttleConfigs(id, WALLET); + assertEq(countAfter, 0, "count should remain 0"); + assertEq( + ValidAfter.unwrap(startAtAfter), + ValidAfter.unwrap(startAtBefore), + "startAt should not advance when exhausted" + ); + vm.stopPrank(); + } + + /// @notice After an idle period the next slot is anchored to `now`, not to + /// the stale `startAt`, so a burst of ops cannot all become immediately valid. With + /// interval=1 day, count=3, startAt=t0, warping to t0+3days and calling once must push the + /// stored startAt to `now + interval` (future), so an immediate second call in the same block + /// returns a validAfter that is still in the future -- the count budget (3) is unaffected. + function test_TF02_NoBurstAfterIdle() public { + bytes32 id = policyId(); + uint48 interval = 1 days; + uint48 count = 3; + uint48 t0 = 1000; + bytes memory data = abi.encodePacked(bytes6(interval), bytes6(count), bytes6(t0)); + + vm.prank(WALLET); + policy.onInstall(abi.encodePacked(id, data)); + + uint256 idleUntil = uint256(t0) + 3 * uint256(interval); + vm.warp(idleUntil); + + PackedUserOperation memory userOp = _dummyUserOp(); + + vm.prank(WALLET); + uint256 v1 = policy.checkUserOpPolicy(id, userOp); + uint48 validAfter1 = uint48(v1 >> 208); + assertEq(validAfter1, t0, "first post-idle call returns the pre-update (already-elapsed) startAt"); + assertLe(validAfter1, uint48(block.timestamp), "returned validAfter for this op should already be elapsed"); + + // Stored startAt must now be anchored to `now`, not to the stale t0 + interval. + (, uint48 countAfter1, ValidAfter storedStartAt1) = policy.throttleConfigs(id, WALLET); + assertEq( + ValidAfter.unwrap(storedStartAt1), + uint48(idleUntil) + interval, + "stored startAt should be anchored to now + interval, not t0 + interval" + ); + assertEq(countAfter1, count - 1, "count should decrement by 1"); + + // A second op in the same block must NOT be immediately valid -- its validAfter is future. + vm.prank(WALLET); + uint256 v2 = policy.checkUserOpPolicy(id, userOp); + uint48 validAfter2 = uint48(v2 >> 208); + assertEq(validAfter2, uint48(idleUntil) + interval, "second call's validAfter should be the anchored slot"); + assertGt(validAfter2, uint48(block.timestamp), "second call's validAfter must be in the future (no burst)"); + + (, uint48 countAfter2,) = policy.throttleConfigs(id, WALLET); + assertEq(countAfter2, count - 2, "count budget still tracks total ops, independent of anchoring"); + } + + function test_checkSignaturePolicy_RevertWhen_NotLive() public { + vm.expectRevert(); + policy.checkSignaturePolicy(policyId(), WALLET, keccak256("hash"), ""); + } + + function test_checkSignaturePolicy_ReturnsSuccessWhenLive() public { + bytes32 id = policyId(); + vm.startPrank(WALLET); + policy.onInstall(abi.encodePacked(id, installData())); + + uint256 result = policy.checkSignaturePolicy(id, WALLET, keccak256("hash"), ""); + vm.stopPrank(); + assertEq(result, SIG_VALIDATION_SUCCESS_UINT, "checkSignaturePolicy should succeed when Live"); + } +} diff --git a/test/TimelockPolicy.t.sol b/test/TimelockPolicy.t.sol index 34e411e..3374cc9 100644 --- a/test/TimelockPolicy.t.sol +++ b/test/TimelockPolicy.t.sol @@ -118,7 +118,7 @@ contract TimelockPolicyTest is PolicyTestBase, StatelessValidatorTestBase, State bytes memory data = abi.encode(uint48(0), uint48(0), address(0)); vm.startPrank(WALLET); - vm.expectRevert("TimelockPolicy: stateless signature validation not supported"); + vm.expectRevert(TimelockPolicy.StatelessValidationNotSupported.selector); validatorModule.validateSignatureWithData(message, sig, data); vm.stopPrank(); } @@ -132,7 +132,7 @@ contract TimelockPolicyTest is PolicyTestBase, StatelessValidatorTestBase, State bytes memory validData = abi.encode(delay, expirationPeriod); vm.startPrank(WALLET); - vm.expectRevert("TimelockPolicy: stateless signature validation not supported"); + vm.expectRevert(TimelockPolicy.StatelessValidationNotSupported.selector); validatorModule.validateSignatureWithData(message, sig, validData); vm.stopPrank(); } @@ -146,7 +146,7 @@ contract TimelockPolicyTest is PolicyTestBase, StatelessValidatorTestBase, State bytes memory data = abi.encode(uint48(0), uint48(0), address(0)); vm.startPrank(WALLET); - vm.expectRevert("TimelockPolicy: stateless signature validation not supported"); + vm.expectRevert(TimelockPolicy.StatelessValidationNotSupported.selector); validatorModule.validateSignatureWithDataWithSender(caller, message, sig, data); vm.stopPrank(); } @@ -160,7 +160,7 @@ contract TimelockPolicyTest is PolicyTestBase, StatelessValidatorTestBase, State bytes memory validData = abi.encode(delay, expirationPeriod); vm.startPrank(WALLET); - vm.expectRevert("TimelockPolicy: stateless signature validation not supported"); + vm.expectRevert(TimelockPolicy.StatelessValidationNotSupported.selector); validatorModule.validateSignatureWithDataWithSender(caller, message, sig, validData); vm.stopPrank(); } @@ -233,7 +233,7 @@ contract TimelockPolicyTest is PolicyTestBase, StatelessValidatorTestBase, State (address sender, bytes memory sigData) = validSignatureData(testHash); vm.startPrank(WALLET); - vm.expectRevert("TimelockPolicy: signature validation not supported"); + vm.expectRevert(TimelockPolicy.SignatureValidationNotSupported.selector); policyModule.checkSignaturePolicy(policyId(), sender, testHash, sigData); vm.stopPrank(); } @@ -245,7 +245,7 @@ contract TimelockPolicyTest is PolicyTestBase, StatelessValidatorTestBase, State (address sender, bytes memory sigData) = invalidSignatureData(testHash); vm.startPrank(WALLET); - vm.expectRevert("TimelockPolicy: signature validation not supported"); + vm.expectRevert(TimelockPolicy.SignatureValidationNotSupported.selector); policyModule.checkSignaturePolicy(policyId(), sender, testHash, sigData); vm.stopPrank(); } diff --git a/test/WebAuthnStateless.t.sol b/test/WebAuthnStateless.t.sol new file mode 100644 index 0000000..99f8c1f --- /dev/null +++ b/test/WebAuthnStateless.t.sol @@ -0,0 +1,145 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.20; + +import {Test} from "forge-std/Test.sol"; +import {IStatelessValidator, IStatelessValidatorWithSender} from "src/interfaces/IERC7579Modules.sol"; +import {MODULE_TYPE_STATELESS_VALIDATOR, MODULE_TYPE_STATELESS_VALIDATOR_WITH_SENDER} from "src/types/Constants.sol"; +import {WebAuthnValidator, WebAuthnValidatorData} from "src/validators/WebAuthnValidator.sol"; +import {WebAuthnSigner, WebAuthnSignerData} from "src/signers/WebAuthnSigner.sol"; +import {Base64} from "solady/utils/Base64.sol"; + +contract WebAuthnStatelessTest is Test { + uint256 internal constant P256_N = 0xFFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC632551; + uint256 internal constant PRIVATE_KEY = 0x234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef1; + + WebAuthnValidator internal validator; + WebAuthnSigner internal signer; + uint256 internal pubKeyX; + uint256 internal pubKeyY; + + function setUp() public { + validator = new WebAuthnValidator(); + signer = new WebAuthnSigner(); + (pubKeyX, pubKeyY) = vm.publicKeyP256(PRIVATE_KEY); + } + + function testModulesAdvertiseStatelessInterfaces() public view { + assertTrue(validator.isModuleType(MODULE_TYPE_STATELESS_VALIDATOR)); + assertTrue(validator.isModuleType(MODULE_TYPE_STATELESS_VALIDATOR_WITH_SENDER)); + assertTrue(signer.isModuleType(MODULE_TYPE_STATELESS_VALIDATOR)); + assertTrue(signer.isModuleType(MODULE_TYPE_STATELESS_VALIDATOR_WITH_SENDER)); + } + + function testValidatorStatelessValidationUsesSuppliedKeyWithoutInstall() public view { + bytes32 hash = keccak256("stateless WebAuthn validator"); + assertTrue( + IStatelessValidator(address(validator)).validateSignatureWithData(hash, _signature(hash), _validatorData()) + ); + } + + function testSignerStatelessValidationUsesSuppliedKeyWithoutInstall() public view { + bytes32 hash = keccak256("stateless WebAuthn signer"); + assertTrue( + IStatelessValidator(address(signer)).validateSignatureWithData(hash, _signature(hash), _signerData()) + ); + } + + function testStatelessValidationWithSenderUsesSuppliedKey() public view { + bytes32 hash = keccak256("stateless WebAuthn with sender"); + address requestingProtocol = address(0xBEEF); + + assertTrue( + IStatelessValidatorWithSender(address(validator)) + .validateSignatureWithDataWithSender(requestingProtocol, hash, _signature(hash), _validatorData()) + ); + assertTrue( + IStatelessValidatorWithSender(address(signer)) + .validateSignatureWithDataWithSender(requestingProtocol, hash, _signature(hash), _signerData()) + ); + } + + function testStatelessValidationRejectsDifferentChallenge() public view { + bytes32 signedHash = keccak256("signed WebAuthn challenge"); + bytes32 requestedHash = keccak256("different WebAuthn challenge"); + + assertFalse( + IStatelessValidator(address(validator)) + .validateSignatureWithData(requestedHash, _signature(signedHash), _validatorData()) + ); + assertFalse( + IStatelessValidator(address(signer)) + .validateSignatureWithData(requestedHash, _signature(signedHash), _signerData()) + ); + } + + function testStatelessValidationRequiresUserPresenceAndVerification() public view { + bytes32 hash = keccak256("WebAuthn flags"); + + assertFalse( + IStatelessValidator(address(validator)) + .validateSignatureWithData(hash, _signature(hash, 0x04), _validatorData()) + ); + assertFalse( + IStatelessValidator(address(signer)).validateSignatureWithData(hash, _signature(hash, 0x01), _signerData()) + ); + } + + function testStatelessValidationUsesDynamicClientDataLocations() public view { + bytes32 hash = keccak256("dynamic WebAuthn locations"); + bytes memory signature = _signature(hash, 0x05, '{"origin":"https://example.com",'); + + assertTrue(IStatelessValidator(address(validator)).validateSignatureWithData(hash, signature, _validatorData())); + assertTrue(IStatelessValidator(address(signer)).validateSignatureWithData(hash, signature, _signerData())); + } + + function testStatelessValidationRejectsMalformedOrZeroKeyData() public view { + bytes32 hash = keccak256("bad WebAuthn config"); + bytes memory signature = _signature(hash); + + assertFalse(IStatelessValidator(address(validator)).validateSignatureWithData(hash, signature, hex"01")); + assertFalse( + IStatelessValidator(address(signer)) + .validateSignatureWithData(hash, signature, abi.encode(uint256(0), uint256(0), bytes32(0))) + ); + } + + function _validatorData() internal view returns (bytes memory) { + return abi.encode(WebAuthnValidatorData(pubKeyX, pubKeyY), bytes32(0)); + } + + function _signerData() internal view returns (bytes memory) { + return abi.encode(WebAuthnSignerData(pubKeyX, pubKeyY), bytes32(0)); + } + + function _signature(bytes32 hash) internal pure returns (bytes memory) { + return _signature(hash, 0x05); + } + + function _signature(bytes32 hash, uint8 flags) internal pure returns (bytes memory) { + return _signature(hash, flags, "{"); + } + + function _signature(bytes32 hash, uint8 flags, string memory clientDataPrefix) + internal + pure + returns (bytes memory) + { + bytes memory authenticatorData = new bytes(37); + authenticatorData[32] = bytes1(flags); + + string memory challenge = Base64.encode(abi.encodePacked(hash), true, true); + string memory clientDataJSON = + string.concat(clientDataPrefix, '"type":"webauthn.get",', '"challenge":"', challenge, '"}'); + uint256 responseTypeLocation = bytes(clientDataPrefix).length; + uint256 challengeLocation = responseTypeLocation + 22; + bytes32 messageHash = sha256(abi.encodePacked(authenticatorData, sha256(bytes(clientDataJSON)))); + (bytes32 r, bytes32 s) = vm.signP256(PRIVATE_KEY, messageHash); + uint256 normalizedS = uint256(s); + if (normalizedS > P256_N / 2) normalizedS = P256_N - normalizedS; + + return + abi.encode( + authenticatorData, clientDataJSON, challengeLocation, responseTypeLocation, uint256(r), normalizedS + ); + } +} diff --git a/test/WeightedECDSAValidator.t.sol b/test/WeightedECDSAValidator.t.sol new file mode 100644 index 0000000..fe46a4b --- /dev/null +++ b/test/WeightedECDSAValidator.t.sol @@ -0,0 +1,708 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.20; + +/// @author taek + +import {Test} from "forge-std/Test.sol"; +import {WeightedECDSAValidator, WeightedECDSAValidatorV09} from "src/validators/WeightedECDSAValidator.sol"; +import {PackedUserOperation} from "account-abstraction/interfaces/PackedUserOperation.sol"; +import {IEntryPoint} from "account-abstraction/interfaces/IEntryPoint.sol"; +import {EntryPointLib} from "./utils/EntryPointLib.sol"; +import {IModule} from "src/interfaces/IERC7579Modules.sol"; +import {WeightedThresholdBase} from "src/base/WeightedThresholdBase.sol"; +import {ECDSA} from "solady/utils/ECDSA.sol"; +import { + ERC1271_MAGICVALUE, + ERC1271_INVALID, + SIG_VALIDATION_FAILED_UINT, + SIG_VALIDATION_SUCCESS_UINT, + MODULE_TYPE_VALIDATOR +} from "src/types/Constants.sol"; + +/// @title WeightedECDSAValidatorTest +/// @notice Unit tests for the guardian multisig validator after the WeightedThresholdBase refactor. +/// WALLET plays the role of the "kernel" — msg.sender for install/validate calls. +/// The validator adopts the signer's split-signature scheme: first N-1 sigs over the EIP712 +/// Proposal(id=0) hash (strictly ASCENDING), last sig over the ep-specific final userOp hash. +contract WeightedECDSAValidatorTest is Test { + WeightedECDSAValidator internal validator; + IEntryPoint internal ENTRYPOINT; + + address constant WALLET = address(0x1234); + + address[3] internal guardianAddrs; + uint256[3] internal guardianKeys; + + uint24 constant W1 = 50; + uint24 constant W2 = 30; + uint24 constant W3 = 20; + uint24 constant THRESHOLD = 60; // needs at least two of the three guardians + + string internal domainName = "WeightedECDSAValidator"; + + function setUp() public virtual { + validator = _deploy(); + ENTRYPOINT = EntryPointLib.deploy(); + + (address a1, uint256 k1) = makeAddrAndKey("g1"); + (address a2, uint256 k2) = makeAddrAndKey("g2"); + (address a3, uint256 k3) = makeAddrAndKey("g3"); + + address[] memory addrs = new address[](3); + uint256[] memory keys = new uint256[](3); + addrs[0] = a1; + addrs[1] = a2; + addrs[2] = a3; + keys[0] = k1; + keys[1] = k2; + keys[2] = k3; + + // sort ascending by address (guardian0 lowest) so split-signature ordering is easy to reason about + for (uint256 i = 0; i < 3; i++) { + for (uint256 j = 0; j < 2 - i; j++) { + if (addrs[j] > addrs[j + 1]) { + (addrs[j], addrs[j + 1]) = (addrs[j + 1], addrs[j]); + (keys[j], keys[j + 1]) = (keys[j + 1], keys[j]); + } + } + } + + guardianAddrs = [addrs[0], addrs[1], addrs[2]]; + guardianKeys = [keys[0], keys[1], keys[2]]; + } + + // ---- variant hooks (V09 subclass overrides these two) ---- + + function _deploy() internal virtual returns (WeightedECDSAValidator) { + return new WeightedECDSAValidator(); + } + + /// @dev The final userOp hash the LAST signature must sign. ep0.7 = eth-signed; ep0.9 = raw. + function _finalHash(bytes32 userOpHash) internal view virtual returns (bytes32) { + return ECDSA.toEthSignedMessageHash(userOpHash); + } + + /// @dev The "wrong" convention (must fail): opposite of _finalHash. + function _wrongFinalHash(bytes32 userOpHash) internal view virtual returns (bytes32) { + return userOpHash; + } + + // ============ helpers ============ + + function _weights() internal pure returns (uint24[] memory weights) { + weights = new uint24[](3); + weights[0] = W1; + weights[1] = W2; + weights[2] = W3; + } + + function _guardians() internal view returns (address[] memory guardians) { + guardians = new address[](3); + guardians[0] = guardianAddrs[0]; + guardians[1] = guardianAddrs[1]; + guardians[2] = guardianAddrs[2]; + } + + function _installData() internal view returns (bytes memory) { + return abi.encode(_guardians(), _weights(), THRESHOLD); + } + + function _install() internal { + vm.prank(WALLET); + validator.onInstall(_installData()); + } + + function _domainSeparator() internal view returns (bytes32) { + return keccak256( + abi.encode( + keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)"), + keccak256(bytes(domainName)), + keccak256("0.0.4"), + block.chainid, + address(validator) + ) + ); + } + + function _proposalHash(PackedUserOperation memory userOp) internal view returns (bytes32) { + return keccak256( + abi.encodePacked( + "\x19\x01", + _domainSeparator(), + keccak256( + abi.encode( + keccak256("Proposal(address account,bytes32 id,bytes callData,uint256 nonce)"), + userOp.sender, + bytes32(0), + keccak256(userOp.callData), + userOp.nonce + ) + ) + ) + ); + } + + function _sign(uint256 key, bytes32 digest) internal pure returns (bytes memory) { + (uint8 v, bytes32 r, bytes32 s) = vm.sign(key, digest); + return abi.encodePacked(r, s, v); + } + + function _userOp(bytes memory callData, uint256 nonce) internal pure returns (PackedUserOperation memory) { + return PackedUserOperation({ + sender: WALLET, + nonce: nonce, + initCode: "", + callData: callData, + accountGasLimits: bytes32(abi.encodePacked(uint128(100000), uint128(200000))), + preVerificationGas: 0, + gasFees: bytes32(abi.encodePacked(uint128(1), uint128(1))), + paymasterAndData: "", + signature: "" + }); + } + + // ============ onInstall ============ + + function test_onInstall_HappyPath_SetsStorage() public { + _install(); + + (uint24 totalWeight, uint24 threshold, address firstGuardian) = validator.weightedStorage(WALLET); + assertEq(totalWeight, W1 + W2 + W3, "totalWeight"); + assertEq(threshold, THRESHOLD, "threshold"); + assertEq(firstGuardian, guardianAddrs[2], "firstGuardian is last-inserted"); + + (uint24 g0Weight, address g0Next) = validator.guardian(guardianAddrs[0], WALLET); + assertEq(g0Weight, W1, "guardian0 weight"); + assertEq(g0Next, WALLET, "guardian0.next is sentinel (msg.sender)"); + + (uint24 g1Weight, address g1Next) = validator.guardian(guardianAddrs[1], WALLET); + assertEq(g1Weight, W2, "guardian1 weight"); + assertEq(g1Next, guardianAddrs[0], "guardian1.next -> guardian0"); + + (uint24 g2Weight, address g2Next) = validator.guardian(guardianAddrs[2], WALLET); + assertEq(g2Weight, W3, "guardian2 weight"); + assertEq(g2Next, guardianAddrs[1], "guardian2.next -> guardian1"); + + assertTrue(validator.isInitialized(WALLET), "isInitialized true"); + } + + function test_onInstall_EmitsGuardianAdded() public { + vm.expectEmit(true, true, false, true, address(validator)); + emit WeightedECDSAValidator.GuardianAdded(guardianAddrs[0], WALLET, W1); + vm.expectEmit(true, true, false, true, address(validator)); + emit WeightedECDSAValidator.GuardianAdded(guardianAddrs[1], WALLET, W2); + vm.expectEmit(true, true, false, true, address(validator)); + emit WeightedECDSAValidator.GuardianAdded(guardianAddrs[2], WALLET, W3); + + vm.prank(WALLET); + validator.onInstall(_installData()); + } + + function test_onInstall_RevertWhen_AlreadyInitialized() public { + _install(); + vm.prank(WALLET); + vm.expectRevert(abi.encodeWithSelector(IModule.AlreadyInitialized.selector, WALLET)); + validator.onInstall(_installData()); + } + + function test_onInstall_RevertWhen_LengthMismatch() public { + address[] memory guardians = new address[](2); + guardians[0] = guardianAddrs[0]; + guardians[1] = guardianAddrs[1]; + uint24[] memory weights = new uint24[](1); + weights[0] = W1; + + vm.prank(WALLET); + vm.expectRevert(WeightedECDSAValidator.LengthMismatch.selector); + validator.onInstall(abi.encode(guardians, weights, THRESHOLD)); + } + + function test_onInstall_RevertWhen_EmptyGuardians() public { + address[] memory guardians = new address[](0); + uint24[] memory weights = new uint24[](0); + vm.prank(WALLET); + vm.expectRevert(WeightedECDSAValidator.EmptyGuardians.selector); + validator.onInstall(abi.encode(guardians, weights, THRESHOLD)); + } + + function test_onInstall_RevertWhen_ZeroThreshold() public { + vm.prank(WALLET); + vm.expectRevert(WeightedECDSAValidator.ZeroThreshold.selector); + validator.onInstall(abi.encode(_guardians(), _weights(), uint24(0))); + } + + function test_onInstall_RevertWhen_GuardianIsSelf() public { + address[] memory guardians = new address[](1); + guardians[0] = WALLET; + uint24[] memory weights = new uint24[](1); + weights[0] = W1; + + vm.prank(WALLET); + vm.expectRevert(WeightedECDSAValidator.GuardianCannotBeSelf.selector); + validator.onInstall(abi.encode(guardians, weights, THRESHOLD)); + } + + function test_onInstall_RevertWhen_GuardianIsZeroAddress() public { + address[] memory guardians = new address[](1); + guardians[0] = address(0); + uint24[] memory weights = new uint24[](1); + weights[0] = W1; + + vm.prank(WALLET); + vm.expectRevert(WeightedECDSAValidator.ZeroAddressGuardian.selector); + validator.onInstall(abi.encode(guardians, weights, THRESHOLD)); + } + + function test_onInstall_RevertWhen_WeightIsZero() public { + address[] memory guardians = new address[](1); + guardians[0] = guardianAddrs[0]; + uint24[] memory weights = new uint24[](1); + weights[0] = 0; + + vm.prank(WALLET); + vm.expectRevert(WeightedECDSAValidator.ZeroWeight.selector); + validator.onInstall(abi.encode(guardians, weights, THRESHOLD)); + } + + function test_onInstall_RevertWhen_DuplicateGuardian() public { + address[] memory guardians = new address[](2); + guardians[0] = guardianAddrs[0]; + guardians[1] = guardianAddrs[0]; + uint24[] memory weights = new uint24[](2); + weights[0] = W1; + weights[1] = W1; + + vm.prank(WALLET); + vm.expectRevert(WeightedECDSAValidator.GuardianAlreadyEnabled.selector); + validator.onInstall(abi.encode(guardians, weights, THRESHOLD)); + } + + function test_onInstall_NoSortRequired_UnsortedSucceeds() public { + // Unlike the old validator, install no longer requires a sorted guardian array. + address[] memory guardians = new address[](3); + guardians[0] = guardianAddrs[1]; + guardians[1] = guardianAddrs[0]; + guardians[2] = guardianAddrs[2]; + uint24[] memory weights = new uint24[](3); + weights[0] = W2; + weights[1] = W1; + weights[2] = W3; + + vm.prank(WALLET); + validator.onInstall(abi.encode(guardians, weights, THRESHOLD)); + assertTrue(validator.isInitialized(WALLET), "unsorted install accepted"); + } + + function test_onInstall_RevertWhen_ThresholdExceedsTotalWeight() public { + vm.prank(WALLET); + vm.expectRevert(WeightedECDSAValidator.ThresholdExceedsTotalWeight.selector); + validator.onInstall(abi.encode(_guardians(), _weights(), uint24(W1 + W2 + W3 + 1))); + } + + function test_onInstall_ThresholdEqualsTotalWeight_Succeeds() public { + vm.prank(WALLET); + validator.onInstall(abi.encode(_guardians(), _weights(), uint24(W1 + W2 + W3))); + (uint24 totalWeight, uint24 threshold,) = validator.weightedStorage(WALLET); + assertEq(threshold, totalWeight, "threshold == totalWeight boundary"); + } + + function test_isModuleType_Validator() public view { + assertTrue(validator.isModuleType(MODULE_TYPE_VALIDATOR)); + assertFalse(validator.isModuleType(999)); + } + + // ============ onUninstall ============ + + function test_onUninstall_RevertWhen_NotInitialized() public { + vm.prank(WALLET); + vm.expectRevert(abi.encodeWithSelector(IModule.NotInitialized.selector, WALLET)); + validator.onUninstall(""); + } + + function test_onUninstall_ClearsGuardiansAndStorage() public { + _install(); + + vm.expectEmit(true, true, false, true, address(validator)); + emit WeightedECDSAValidator.GuardianRemoved(guardianAddrs[2], WALLET); + vm.expectEmit(true, true, false, true, address(validator)); + emit WeightedECDSAValidator.GuardianRemoved(guardianAddrs[1], WALLET); + vm.expectEmit(true, true, false, true, address(validator)); + emit WeightedECDSAValidator.GuardianRemoved(guardianAddrs[0], WALLET); + + vm.prank(WALLET); + validator.onUninstall(""); + + (uint24 totalWeight, uint24 threshold, address firstGuardian) = validator.weightedStorage(WALLET); + assertEq(totalWeight, 0, "totalWeight cleared"); + assertEq(threshold, 0, "threshold cleared"); + assertEq(firstGuardian, address(0), "firstGuardian cleared"); + + for (uint256 i = 0; i < 3; i++) { + (uint24 w, address next) = validator.guardian(guardianAddrs[i], WALLET); + assertEq(w, 0, "guardian weight cleared"); + assertEq(next, address(0), "guardian next cleared"); + } + assertFalse(validator.isInitialized(WALLET), "not initialized after uninstall"); + } + + function test_onInstall_AfterUninstall_Reinstalls() public { + _install(); + vm.prank(WALLET); + validator.onUninstall(""); + _install(); + assertTrue(validator.isInitialized(WALLET), "reinstall after uninstall works"); + } + + // ============ validateUserOp (split-signature scheme) ============ + + /// @dev Happy path: guardian0 (W1=50) signs proposalHash, guardian1 (W2=30) signs finalHash. + /// Combined weight 80 >= 60. proposalSigner < finalSigner not required (only 1 proposal sig). + function test_validateUserOp_TwoSig_ThresholdMet_Success() public { + _install(); + PackedUserOperation memory userOp = _userOp(hex"aabb", 0); + bytes32 userOpHash = ENTRYPOINT.getUserOpHash(userOp); + + userOp.signature = abi.encodePacked( + _sign(guardianKeys[0], _proposalHash(userOp)), // proposal sig + _sign(guardianKeys[1], _finalHash(userOpHash)) // final sig + ); + + vm.prank(WALLET); + assertEq(validator.validateUserOp(userOp, userOpHash), SIG_VALIDATION_SUCCESS_UINT, "threshold met"); + } + + /// @dev Single final signature: guardian0 alone (W1=50) is below threshold 60 -> fail. + function test_validateUserOp_SingleFinalSig_BelowThreshold_Fails() public { + _install(); + PackedUserOperation memory userOp = _userOp(hex"aabb", 0); + bytes32 userOpHash = ENTRYPOINT.getUserOpHash(userOp); + + userOp.signature = _sign(guardianKeys[0], _finalHash(userOpHash)); + + vm.prank(WALLET); + assertEq(validator.validateUserOp(userOp, userOpHash), SIG_VALIDATION_FAILED_UINT, "below threshold"); + } + + /// @dev The final signature must use THIS variant's convention. Signing with the wrong final + /// hash yields a non-guardian recovered address -> last-signer zero weight -> fail. + function test_validateUserOp_WrongFinalHashConvention_Fails() public { + _install(); + PackedUserOperation memory userOp = _userOp(hex"aabb", 0); + bytes32 userOpHash = ENTRYPOINT.getUserOpHash(userOp); + + userOp.signature = abi.encodePacked( + _sign(guardianKeys[0], _proposalHash(userOp)), + _sign(guardianKeys[1], _wrongFinalHash(userOpHash)) // wrong convention + ); + + vm.prank(WALLET); + assertEq( + validator.validateUserOp(userOp, userOpHash), + SIG_VALIDATION_FAILED_UINT, + "wrong final-hash convention rejected" + ); + } + + /// @dev Last signer not a guardian -> fail (returns false, no revert), even though the + /// proposal sigs alone already meet threshold. + function test_validateUserOp_LastSignerNotGuardian_Fails() public { + _install(); + PackedUserOperation memory userOp = _userOp(hex"aabb", 0); + bytes32 userOpHash = ENTRYPOINT.getUserOpHash(userOp); + (, uint256 strangerKey) = makeAddrAndKey("stranger"); + + userOp.signature = abi.encodePacked( + _sign(guardianKeys[0], _proposalHash(userOp)), + _sign(guardianKeys[1], _proposalHash(userOp)), + _sign(strangerKey, _finalHash(userOpHash)) // last signer not a guardian + ); + + // guardianKeys[0] < guardianKeys[1] by address (ascending) required for the two proposal sigs + // guardianAddrs is sorted ascending, so keys[0]..keys[1] are ascending too. + vm.prank(WALLET); + assertEq(validator.validateUserOp(userOp, userOpHash), SIG_VALIDATION_FAILED_UINT, "last signer not guardian"); + } + + /// @dev Non-last (proposal) signer with zero weight must REVERT ZeroWeightSigner. + function test_validateUserOp_RevertWhen_NonLastSignerZeroWeight() public { + _install(); + PackedUserOperation memory userOp = _userOp(hex"aabb", 0); + bytes32 userOpHash = ENTRYPOINT.getUserOpHash(userOp); + (, uint256 strangerKey) = makeAddrAndKey("stranger-nonlast"); + + userOp.signature = abi.encodePacked( + _sign(strangerKey, _proposalHash(userOp)), // proposal signer, zero weight -> revert + _sign(guardianKeys[0], _finalHash(userOpHash)) + ); + + vm.prank(WALLET); + vm.expectRevert(WeightedECDSAValidator.ZeroWeightSigner.selector); + validator.validateUserOp(userOp, userOpHash); + } + + /// @dev De-dup: same guardian signs the proposal AND the final hash. Its weight is counted + /// once. guardian0 alone (W1=50) < 60, so a self-duplicate must NOT reach threshold. + function test_validateUserOp_FinalSignerAlsoProposalSigner_NoDoubleCount_Fails() public { + _install(); + PackedUserOperation memory userOp = _userOp(hex"aabb", 0); + bytes32 userOpHash = ENTRYPOINT.getUserOpHash(userOp); + + userOp.signature = abi.encodePacked( + _sign(guardianKeys[0], _proposalHash(userOp)), + _sign(guardianKeys[0], _finalHash(userOpHash)) // same guardian as final signer + ); + + vm.prank(WALLET); + assertEq( + validator.validateUserOp(userOp, userOpHash), + SIG_VALIDATION_FAILED_UINT, + "final signer weight not double-counted" + ); + } + + /// @dev De-dup positive: two distinct proposal signers reach threshold; the final sig repeats + /// one of them (already counted) but the two distinct proposal weights already pass. + function test_validateUserOp_DedupWithEnoughDistinctWeight_Success() public { + _install(); + PackedUserOperation memory userOp = _userOp(hex"aabb", 0); + bytes32 userOpHash = ENTRYPOINT.getUserOpHash(userOp); + + // guardian0 (50) + guardian1 (30) as proposal sigs (ascending) = 80 >= 60; final repeats guardian0 + userOp.signature = abi.encodePacked( + _sign(guardianKeys[0], _proposalHash(userOp)), + _sign(guardianKeys[1], _proposalHash(userOp)), + _sign(guardianKeys[0], _finalHash(userOpHash)) + ); + + vm.prank(WALLET); + assertEq( + validator.validateUserOp(userOp, userOpHash), SIG_VALIDATION_SUCCESS_UINT, "distinct proposal weight passes" + ); + } + + /// @dev Proposal signers out of ascending order must REVERT SignersNotSorted. + function test_validateUserOp_RevertWhen_ProposalSignersNotSorted() public { + _install(); + PackedUserOperation memory userOp = _userOp(hex"aabb", 0); + bytes32 userOpHash = ENTRYPOINT.getUserOpHash(userOp); + + // guardian1 then guardian0 as proposal sigs = descending -> not sorted + userOp.signature = abi.encodePacked( + _sign(guardianKeys[1], _proposalHash(userOp)), + _sign(guardianKeys[0], _proposalHash(userOp)), + _sign(guardianKeys[2], _finalHash(userOpHash)) + ); + + vm.prank(WALLET); + vm.expectRevert(WeightedECDSAValidator.SignersNotSorted.selector); + validator.validateUserOp(userOp, userOpHash); + } + + function test_validateUserOp_ThresholdZero_NotInstalled_Fails() public { + PackedUserOperation memory userOp = _userOp(hex"aabb", 0); + bytes32 userOpHash = ENTRYPOINT.getUserOpHash(userOp); + userOp.signature = _sign(guardianKeys[0], _finalHash(userOpHash)); + + vm.prank(WALLET); + assertEq(validator.validateUserOp(userOp, userOpHash), SIG_VALIDATION_FAILED_UINT, "threshold==0 -> fail"); + } + + /// @dev Signature length not a multiple of 65 -> fail (no revert). + function test_validateUserOp_SigLengthNotMultipleOf65_Fails() public { + _install(); + PackedUserOperation memory userOp = _userOp(hex"aabb", 0); + bytes32 userOpHash = ENTRYPOINT.getUserOpHash(userOp); + userOp.signature = hex"deadbeef"; // 4 bytes + + vm.prank(WALLET); + assertEq(validator.validateUserOp(userOp, userOpHash), SIG_VALIDATION_FAILED_UINT, "bad sig length"); + } + + /// @dev Empty signature -> sigCount == 0 -> fail (no revert). + function test_validateUserOp_EmptySignature_Fails() public { + _install(); + PackedUserOperation memory userOp = _userOp(hex"aabb", 0); + bytes32 userOpHash = ENTRYPOINT.getUserOpHash(userOp); + userOp.signature = ""; + + vm.prank(WALLET); + assertEq(validator.validateUserOp(userOp, userOpHash), SIG_VALIDATION_FAILED_UINT, "empty sig"); + } + + // ============ isValidSignatureWithSender (ERC-1271, ep-agnostic) ============ + + function test_isValidSignatureWithSender_ReturnsInvalid_WhenNotInstalled() public { + bytes32 hash = keccak256("not installed"); + bytes memory sig = _sign(guardianKeys[0], hash); + vm.prank(WALLET); + assertEq(validator.isValidSignatureWithSender(address(0), hash, sig), ERC1271_INVALID, "threshold==0"); + } + + function test_isValidSignatureWithSender_EmptyData_ReturnsInvalid() public { + _install(); + vm.prank(WALLET); + assertEq(validator.isValidSignatureWithSender(address(0), keccak256("empty"), ""), ERC1271_INVALID, "zero sigs"); + } + + function test_isValidSignatureWithSender_SingleSigBelowThreshold_ReturnsInvalid() public { + _install(); + bytes32 hash = keccak256("single"); + bytes memory sig = _sign(guardianKeys[2], hash); // W3=20 < 60 + vm.prank(WALLET); + assertEq(validator.isValidSignatureWithSender(address(0), hash, sig), ERC1271_INVALID, "below threshold"); + } + + function test_isValidSignatureWithSender_MultiSigMeetsThreshold_ReturnsMagicValue() public { + _install(); + bytes32 hash = keccak256("multi"); + // ascending signers: guardian0 then guardian1 (guardianAddrs sorted ascending) + bytes memory sigs = abi.encodePacked(_sign(guardianKeys[0], hash), _sign(guardianKeys[1], hash)); + vm.prank(WALLET); + assertEq(validator.isValidSignatureWithSender(address(0), hash, sigs), ERC1271_MAGICVALUE, "80 >= 60"); + } + + function test_isValidSignatureWithSender_OrderingViolation_ReturnsInvalid() public { + _install(); + bytes32 hash = keccak256("unordered"); + // descending order (guardian1 before guardian0) violates strictly-ascending; combined + // weight would be 80 but ordering rejects before the last-sig threshold check + bytes memory sigs = abi.encodePacked(_sign(guardianKeys[1], hash), _sign(guardianKeys[0], hash)); + vm.prank(WALLET); + assertEq(validator.isValidSignatureWithSender(address(0), hash, sigs), ERC1271_INVALID, "descending rejected"); + } + + /// @dev Ordering violation among NON-last signers (3 sigs, first two descending) -> INVALID. + /// Exercises the `_verifySorted` in-loop ordering early-return (not the last-sig path). + function test_isValidSignatureWithSender_NonLastOrderingViolation_ReturnsInvalid() public { + _install(); + bytes32 hash = keccak256("nonlast-order"); + // guardian1 then guardian0 (descending) as first two, guardian2 last -> in-loop violation + bytes memory sigs = + abi.encodePacked(_sign(guardianKeys[1], hash), _sign(guardianKeys[0], hash), _sign(guardianKeys[2], hash)); + vm.prank(WALLET); + assertEq( + validator.isValidSignatureWithSender(address(0), hash, sigs), ERC1271_INVALID, "non-last ordering rejected" + ); + } + + /// @dev A NON-last signer whose weight alone reaches threshold returns MAGICVALUE early, + /// before the last signature is processed. Exercises the in-loop threshold return. + function test_isValidSignatureWithSender_NonLastMeetsThreshold_ReturnsMagicValue() public { + // Install a set where guardian0 alone (weight 100) exceeds threshold 60, on a fresh sender. + address acct = address(0xBEEF); + (address big, uint256 bigKey) = makeAddrAndKey("bigGuardian"); + (address small, uint256 smallKey) = makeAddrAndKey("smallGuardian"); + // ensure big < small so big is a non-last signer in ascending order + if (big > small) { + (big, small) = (small, big); + (bigKey, smallKey) = (smallKey, bigKey); + } + address[] memory gs = new address[](2); + gs[0] = big; + gs[1] = small; + uint24[] memory ws = new uint24[](2); + ws[0] = 100; + ws[1] = 5; + vm.prank(acct); + validator.onInstall(abi.encode(gs, ws, uint24(60))); + + bytes32 hash = keccak256("nonlast-threshold"); + bytes memory sigs = abi.encodePacked(_sign(bigKey, hash), _sign(smallKey, hash)); + vm.prank(acct); + assertEq( + validator.isValidSignatureWithSender(address(0), hash, sigs), + ERC1271_MAGICVALUE, + "non-last signer meets threshold early" + ); + } + + function test_isValidSignatureWithSender_NonGuardianSigner_ReturnsInvalid() public { + _install(); + bytes32 hash = keccak256("stranger"); + (, uint256 strangerKey) = makeAddrAndKey("strangerSigner"); + bytes memory sig = _sign(strangerKey, hash); + vm.prank(WALLET); + assertEq(validator.isValidSignatureWithSender(address(0), hash, sig), ERC1271_INVALID, "zero weight"); + } + + /// @dev A NON-last signer with zero weight must REVERT ZeroWeightSigner. Installs a single + /// guardian with a deliberately high address on a fresh account, then finds a stranger key + /// that recovers to a lower address so it sorts FIRST (non-last). + function test_isValidSignatureWithSender_RevertWhen_NonLastSignerZeroWeight() public { + bytes32 hash = keccak256("griefing"); + + // Deterministically find a real guardian and a stranger with stranger < guardian. + (address realAddr, uint256 realKey) = makeAddrAndKey("griefing-real-guardian"); + address stranger; + uint256 strangerKey; + for (uint256 i = 0; i < 50; i++) { + (stranger, strangerKey) = makeAddrAndKey(string(abi.encodePacked("griefer", vm.toString(i)))); + if (stranger < realAddr) break; + } + require(stranger < realAddr, "could not construct witness"); + + address acct = address(0xCAFE); + address[] memory gs = new address[](1); + gs[0] = realAddr; + uint24[] memory ws = new uint24[](1); + ws[0] = 60; + vm.prank(acct); + validator.onInstall(abi.encode(gs, ws, uint24(60))); + + // stranger (zero weight, sorts first/non-last) then real guardian (last) + bytes memory sigs = abi.encodePacked(_sign(strangerKey, hash), _sign(realKey, hash)); + vm.prank(acct); + vm.expectRevert(WeightedECDSAValidator.ZeroWeightSigner.selector); + validator.isValidSignatureWithSender(address(0), hash, sigs); + } + + /// @dev All signers valid & distinct but combined weight below threshold -> INVALID + /// (exercises the final `return false` after the last-signature path). + function test_isValidSignatureWithSender_TwoLowWeight_BelowThreshold_ReturnsInvalid() public { + _install(); + bytes32 hash = keccak256("low-total"); + // guardian1 (30) + guardian2 (20) = 50 < 60, ascending order, last sig non-zero weight + bytes memory sigs = abi.encodePacked(_sign(guardianKeys[1], hash), _sign(guardianKeys[2], hash)); + vm.prank(WALLET); + assertEq(validator.isValidSignatureWithSender(address(0), hash, sigs), ERC1271_INVALID, "50 < 60 -> invalid"); + } + + // ============ EC-01 regression ============ + + /// @notice A single guardian's signature duplicated must NOT reach threshold by being counted + /// twice. The ordering guard (signer <= lastSigner) runs BEFORE weight is added, so the + /// second occurrence of the same signer is rejected. This is where EC-01 lived. + function test_EC01_isValidSignatureWithSender_DuplicateSingleGuardianSig_ReturnsInvalid_NotMagicValue() public { + _install(); + bytes32 hash = keccak256("EC01-dup"); + bytes memory sig = _sign(guardianKeys[0], hash); // W1=50, alone < 60 + bytes memory sigs = abi.encodePacked(sig, sig); // same guardian twice -> 100 if double-counted + + vm.prank(WALLET); + bytes4 result = validator.isValidSignatureWithSender(address(0), hash, sigs); + assertEq(result, ERC1271_INVALID, "EC-01: duplicate single-guardian sig rejected"); + assertTrue(result != ERC1271_MAGICVALUE, "EC-01: must never return MAGICVALUE for a duplicate"); + } +} + +/// @title WeightedECDSAValidatorV09Test +/// @notice Reuses the full suite but for the ep0.9 variant: the final signature signs the RAW +/// userOpHash. The wrong-convention test flips to the eth-signed hash. +contract WeightedECDSAValidatorV09Test is WeightedECDSAValidatorTest { + function setUp() public override { + super.setUp(); + domainName = "WeightedECDSAValidator"; // V09 keeps the base domain name (one-method subclass) + } + + function _deploy() internal override returns (WeightedECDSAValidator) { + return new WeightedECDSAValidatorV09(); + } + + function _finalHash(bytes32 userOpHash) internal pure override returns (bytes32) { + return userOpHash; // ep0.9: raw userOpHash + } + + function _wrongFinalHash(bytes32 userOpHash) internal pure override returns (bytes32) { + return ECDSA.toEthSignedMessageHash(userOpHash); + } +} diff --git a/test/base/PolicyTestBase.sol b/test/base/PolicyTestBase.sol index 2daf0f7..7237c27 100644 --- a/test/base/PolicyTestBase.sol +++ b/test/base/PolicyTestBase.sol @@ -39,7 +39,7 @@ abstract contract PolicyTestBase is ModuleTestBase { _afterInstallCheck(policyId()); } - function testPolicyOnInstallFailSameId() public payable { + function testPolicyOnInstallFailSameId() public payable virtual { IPolicy policyModule = IPolicy(address(module)); vm.startPrank(WALLET); policyModule.onInstall(abi.encodePacked(policyId(), installData())); diff --git a/test/btt/CallerPolicyValidation.t.sol b/test/btt/CallerPolicyValidation.t.sol index e34f97b..30cb1d5 100644 --- a/test/btt/CallerPolicyValidation.t.sol +++ b/test/btt/CallerPolicyValidation.t.sol @@ -34,7 +34,7 @@ contract CallerPolicyValidationTest is Test { bytes memory installData = abi.encodePacked(POLICY_ID, abi.encode(emptyCallers)); vm.startPrank(WALLET_1); - vm.expectRevert("Empty callers array"); + vm.expectRevert(CallerPolicy.EmptyCallers.selector); policy.onInstall(installData); vm.stopPrank(); } @@ -47,7 +47,7 @@ contract CallerPolicyValidationTest is Test { bytes memory installData = abi.encodePacked(POLICY_ID, abi.encode(callersWithZero)); vm.startPrank(WALLET_1); - vm.expectRevert("Zero address caller"); + vm.expectRevert(CallerPolicy.ZeroAddressCaller.selector); policy.onInstall(installData); vm.stopPrank(); } @@ -196,7 +196,7 @@ contract CallerPolicyValidationTest is Test { bytes memory installData = abi.encodePacked(POLICY_ID, abi.encode(callersWithZeroFirst)); vm.startPrank(WALLET_1); - vm.expectRevert("Zero address caller"); + vm.expectRevert(CallerPolicy.ZeroAddressCaller.selector); policy.onInstall(installData); vm.stopPrank(); } @@ -208,7 +208,7 @@ contract CallerPolicyValidationTest is Test { bytes memory installData = abi.encodePacked(POLICY_ID, abi.encode(singleZero)); vm.startPrank(WALLET_1); - vm.expectRevert("Zero address caller"); + vm.expectRevert(CallerPolicy.ZeroAddressCaller.selector); policy.onInstall(installData); vm.stopPrank(); } diff --git a/test/btt/DefaultSecurityHook.t.sol b/test/btt/DefaultSecurityHook.t.sol new file mode 100644 index 0000000..9ef35bd --- /dev/null +++ b/test/btt/DefaultSecurityHook.t.sol @@ -0,0 +1,908 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity ^0.8.20; + +import {Test} from "forge-std/Test.sol"; +import {DefaultSecurityHook} from "src/hooks/DefaultSecurityHook.sol"; +import {IModule} from "src/interfaces/IERC7579Modules.sol"; +import {MODULE_TYPE_HOOK} from "src/types/Constants.sol"; +import {LibERC7579} from "solady/accounts/LibERC7579.sol"; +import {IERC7579Execution, Execution} from "openzeppelin-contracts/contracts/interfaces/draft-IERC7579.sol"; +import {IERC20} from "openzeppelin-contracts/contracts/token/ERC20/IERC20.sol"; +import {IERC721} from "openzeppelin-contracts/contracts/token/ERC721/IERC721.sol"; +import {IERC1155} from "openzeppelin-contracts/contracts/token/ERC1155/IERC1155.sol"; +import {ERC20} from "openzeppelin-contracts/contracts/token/ERC20/ERC20.sol"; +import {ERC721} from "openzeppelin-contracts/contracts/token/ERC721/ERC721.sol"; +import {ERC1155} from "openzeppelin-contracts/contracts/token/ERC1155/ERC1155.sol"; + +/// @dev Mock module that responds to isModuleType without reverting. +contract MockModule is IModule { + function onInstall(bytes calldata) external payable override {} + function onUninstall(bytes calldata) external payable override {} + + function isModuleType(uint256) external pure override returns (bool) { + return true; + } +} + +/// @dev A contract that does NOT implement isModuleType (staticcall will revert). +contract NonModuleContract { + function doSomething() external pure returns (uint256) { + return 42; + } +} + +contract MockERC20 is ERC20 { + constructor() ERC20("MockToken", "MCK") {} + + function mint(address to, uint256 amount) external { + _mint(to, amount); + } +} + +contract MockERC721 is ERC721 { + constructor() ERC721("MockNFT", "MNFT") {} + + function mint(address to, uint256 tokenId) external { + _mint(to, tokenId); + } +} + +contract MockERC1155 is ERC1155 { + constructor() ERC1155("https://mock.uri/{id}") {} + + function mint(address to, uint256 id, uint256 amount) external { + _mint(to, id, amount, ""); + } +} + +contract DefaultSecurityHookBTTTest is Test { + DefaultSecurityHook public hook; + MockModule public mockModule; + NonModuleContract public nonModule; + MockERC20 public mockERC20; + MockERC721 public mockERC721; + MockERC1155 public mockERC1155; + + address public account; + address public randomTarget; + address public recipient; + + // Blocked selectors — derived from interfaces + // ERC-20 + bytes4 internal constant TRANSFER = IERC20.transfer.selector; + bytes4 internal constant APPROVE = IERC20.approve.selector; + bytes4 internal constant TRANSFER_FROM = IERC20.transferFrom.selector; + bytes4 internal constant INCREASE_ALLOWANCE = bytes4(keccak256("increaseAllowance(address,uint256)")); + bytes4 internal constant DECREASE_ALLOWANCE = bytes4(keccak256("decreaseAllowance(address,uint256)")); + + // ERC-721 (safeTransferFrom is overloaded, so compute from signatures) + bytes4 internal constant SAFE_TRANSFER_FROM = bytes4(keccak256("safeTransferFrom(address,address,uint256)")); + bytes4 internal constant SAFE_TRANSFER_FROM_WITH_DATA = + bytes4(keccak256("safeTransferFrom(address,address,uint256,bytes)")); + bytes4 internal constant SET_APPROVAL_FOR_ALL = IERC721.setApprovalForAll.selector; + + // ERC-1155 + bytes4 internal constant SAFE_TRANSFER_FROM_1155 = IERC1155.safeTransferFrom.selector; + bytes4 internal constant SAFE_BATCH_TRANSFER_FROM = IERC1155.safeBatchTransferFrom.selector; + + // An unblocked selector + bytes4 internal constant BALANCE_OF = IERC20.balanceOf.selector; + + event AllowlistSet(address indexed account, address indexed target, bytes4[] selectors); + event AllowlistRemoved(address indexed account, address indexed target); + event Initialized(address indexed account); + event Uninitialized(address indexed account); + + function setUp() public { + hook = new DefaultSecurityHook(); + mockModule = new MockModule(); + nonModule = new NonModuleContract(); + mockERC20 = new MockERC20(); + mockERC721 = new MockERC721(); + mockERC1155 = new MockERC1155(); + account = address(0xACC0); + randomTarget = address(nonModule); + recipient = address(0xBEEF); + } + + // ==================== Helper Functions ==================== + + function _install() internal { + vm.prank(account); + hook.onInstall(""); + } + + function _installWithConfig(DefaultSecurityHook.AllowlistConfig[] memory configs) internal { + vm.prank(account); + hook.onInstall(abi.encode(configs)); + } + + /// @dev Build msgData for a single-mode preCheck call. + function _singleMsgData(address target, uint256 value, bytes memory data) internal pure returns (bytes memory) { + bytes32 mode = + LibERC7579.encodeMode(LibERC7579.CALLTYPE_SINGLE, LibERC7579.EXECTYPE_DEFAULT, bytes4(0), bytes22(0)); + bytes memory executionData = abi.encodePacked(target, value, data); + return abi.encodeWithSelector(IERC7579Execution.execute.selector, mode, executionData); + } + + /// @dev Build msgData for a batch-mode preCheck call. + function _batchMsgData(Execution[] memory executions) internal pure returns (bytes memory) { + bytes32 mode = + LibERC7579.encodeMode(LibERC7579.CALLTYPE_BATCH, LibERC7579.EXECTYPE_DEFAULT, bytes4(0), bytes22(0)); + bytes memory executionData = abi.encode(executions); + return abi.encodeWithSelector(IERC7579Execution.execute.selector, mode, executionData); + } + + /// @dev Build msgData for a delegatecall-mode preCheck call. + function _delegatecallMsgData() internal pure returns (bytes memory) { + bytes32 mode = + LibERC7579.encodeMode(LibERC7579.CALLTYPE_DELEGATECALL, LibERC7579.EXECTYPE_DEFAULT, bytes4(0), bytes22(0)); + bytes memory executionData = abi.encodePacked(address(0), uint256(0)); + return abi.encodeWithSelector(IERC7579Execution.execute.selector, mode, executionData); + } + + /// @dev Helper to call preCheck from account context. + function _preCheck(bytes memory msgData) internal returns (bytes memory) { + vm.prank(account); + return hook.preCheck(address(0), 0, msgData); + } + + // ==================== onInstall Tests ==================== + + modifier whenCallingOnInstall() { + _; + } + + function test_GivenAccountIsAlreadyInitialized() external whenCallingOnInstall { + // it should revert with AlreadyInitialized + _install(); + + vm.prank(account); + vm.expectRevert(abi.encodeWithSelector(IModule.AlreadyInitialized.selector, account)); + hook.onInstall(""); + } + + function test_GivenDataIsEmpty() external whenCallingOnInstall { + // it should mark account as initialized + // it should emit Initialized event + vm.prank(account); + vm.expectEmit(true, false, false, false); + emit Initialized(account); + hook.onInstall(""); + + assertTrue(hook.isInitialized(account), "Account should be initialized"); + } + + function test_GivenDataContainsAllowlistConfigs() external whenCallingOnInstall { + // it should mark account as initialized + // it should set allowlist entries for each config + // it should emit Initialized event + DefaultSecurityHook.AllowlistConfig[] memory configs = new DefaultSecurityHook.AllowlistConfig[](2); + + bytes4[] memory selectors1 = new bytes4[](1); + selectors1[0] = TRANSFER; + configs[0] = DefaultSecurityHook.AllowlistConfig({target: randomTarget, selectors: selectors1}); + + bytes4[] memory selectors2 = new bytes4[](0); + configs[1] = DefaultSecurityHook.AllowlistConfig({target: address(0xBEEF), selectors: selectors2}); + + vm.prank(account); + vm.expectEmit(true, false, false, false); + emit Initialized(account); + hook.onInstall(abi.encode(configs)); + + assertTrue(hook.isInitialized(account), "Account should be initialized"); + assertTrue(hook.isAllowlisted(account, randomTarget), "randomTarget should be allowlisted"); + assertTrue(hook.isSelectorAllowed(account, randomTarget, TRANSFER), "TRANSFER selector should be allowed"); + assertFalse(hook.isSelectorAllowed(account, randomTarget, APPROVE), "APPROVE selector should not be allowed"); + assertTrue(hook.isAllowlisted(account, address(0xBEEF)), "0xBEEF should be allowlisted"); + assertTrue( + hook.isSelectorAllowed(account, address(0xBEEF), TRANSFER), "All selectors should be allowed for 0xBEEF" + ); + } + + // ==================== onUninstall Tests ==================== + + modifier whenCallingOnUninstall() { + _; + } + + function test_GivenAccountIsNotInitialized() external whenCallingOnUninstall { + // it should revert with NotInitialized + vm.prank(account); + vm.expectRevert(abi.encodeWithSelector(IModule.NotInitialized.selector, account)); + hook.onUninstall(""); + } + + function test_GivenDataIsEmpty_WhenCallingOnUninstall() external whenCallingOnUninstall { + // it should mark account as not initialized + // it should emit Uninitialized event + _install(); + + vm.prank(account); + vm.expectEmit(true, false, false, false); + emit Uninitialized(account); + hook.onUninstall(""); + + assertFalse(hook.isInitialized(account), "Account should not be initialized"); + } + + function test_GivenDataContainsTargetsToClean() external whenCallingOnUninstall { + // it should clear all allowlist entries automatically + // it should mark account as not initialized + // it should emit Uninitialized event + DefaultSecurityHook.AllowlistConfig[] memory configs = new DefaultSecurityHook.AllowlistConfig[](1); + bytes4[] memory sels = new bytes4[](0); + configs[0] = DefaultSecurityHook.AllowlistConfig({target: randomTarget, selectors: sels}); + _installWithConfig(configs); + + assertTrue(hook.isAllowlisted(account, randomTarget), "Should be allowlisted before uninstall"); + + vm.prank(account); + vm.expectEmit(true, false, false, false); + emit Uninitialized(account); + hook.onUninstall(""); + + assertFalse(hook.isInitialized(account), "Account should not be initialized"); + assertFalse(hook.isAllowlisted(account, randomTarget), "Allowlist should be cleared"); + } + + // ==================== isModuleType Tests ==================== + + modifier whenCallingIsModuleType() { + _; + } + + function test_GivenModuleTypeIdIsMODULE_TYPE_HOOK() external whenCallingIsModuleType { + // it should return true + assertTrue(hook.isModuleType(MODULE_TYPE_HOOK), "Should return true for MODULE_TYPE_HOOK"); + } + + function test_GivenModuleTypeIdIsNotMODULE_TYPE_HOOK() external whenCallingIsModuleType { + // it should return false + assertFalse(hook.isModuleType(1), "Should return false for MODULE_TYPE_VALIDATOR"); + assertFalse(hook.isModuleType(0), "Should return false for 0"); + assertFalse(hook.isModuleType(999), "Should return false for 999"); + } + + // ==================== preCheck DELEGATECALL Tests ==================== + + function test_WhenCallingPreCheckWithDELEGATECALLMode() external { + // it should revert with DelegateCallNotAllowed + bytes memory msgData = _delegatecallMsgData(); + + vm.prank(account); + vm.expectRevert(DefaultSecurityHook.DelegateCallNotAllowed.selector); + hook.preCheck(address(0), 0, msgData); + } + + // ==================== preCheck SINGLE Tests ==================== + + modifier whenCallingPreCheckWithSINGLEMode() { + _; + } + + function test_GivenTargetIsAllowlistedWithAllSelectors() external whenCallingPreCheckWithSINGLEMode { + // it should return empty bytes + DefaultSecurityHook.AllowlistConfig[] memory configs = new DefaultSecurityHook.AllowlistConfig[](1); + bytes4[] memory sels = new bytes4[](0); + configs[0] = DefaultSecurityHook.AllowlistConfig({target: address(mockERC20), selectors: sels}); + _installWithConfig(configs); + + // Even a blocked selector should pass when all selectors are allowed + bytes memory callData = abi.encodeCall(IERC20.transfer, (recipient, 100)); + bytes memory msgData = _singleMsgData(address(mockERC20), 0, callData); + bytes memory result = _preCheck(msgData); + assertEq(result, hex"", "Should return empty bytes"); + } + + function test_GivenTargetIsAllowlistedWithSpecificSelectorMatchingCall() + external + whenCallingPreCheckWithSINGLEMode + { + // it should return empty bytes + DefaultSecurityHook.AllowlistConfig[] memory configs = new DefaultSecurityHook.AllowlistConfig[](1); + bytes4[] memory sels = new bytes4[](1); + sels[0] = TRANSFER; + configs[0] = DefaultSecurityHook.AllowlistConfig({target: address(mockERC20), selectors: sels}); + _installWithConfig(configs); + + bytes memory callData = abi.encodeCall(IERC20.transfer, (recipient, 100)); + bytes memory msgData = _singleMsgData(address(mockERC20), 0, callData); + bytes memory result = _preCheck(msgData); + assertEq(result, hex"", "Should return empty bytes"); + } + + function test_GivenTargetIsAllowlistedWithSpecificSelectorNotMatchingCall() + external + whenCallingPreCheckWithSINGLEMode + { + // it should revert with TokenTransferNotAllowed + // Allowlist TRANSFER for the token, but call APPROVE (also blocked) + DefaultSecurityHook.AllowlistConfig[] memory configs = new DefaultSecurityHook.AllowlistConfig[](1); + bytes4[] memory sels = new bytes4[](1); + sels[0] = TRANSFER; + configs[0] = DefaultSecurityHook.AllowlistConfig({target: address(mockERC20), selectors: sels}); + _installWithConfig(configs); + + bytes memory callData = abi.encodeCall(IERC20.approve, (recipient, 100)); + bytes memory msgData = _singleMsgData(address(mockERC20), 0, callData); + vm.prank(account); + vm.expectRevert( + abi.encodeWithSelector(DefaultSecurityHook.TokenTransferNotAllowed.selector, address(mockERC20), APPROVE) + ); + hook.preCheck(address(0), 0, msgData); + } + + function test_GivenTargetIsSelf() external whenCallingPreCheckWithSINGLEMode { + // it should revert with SelfCallNotAllowed + _install(); + bytes memory msgData = _singleMsgData(account, 0, abi.encodeWithSelector(BALANCE_OF, address(1))); + vm.prank(account); + vm.expectRevert(DefaultSecurityHook.SelfCallNotAllowed.selector); + hook.preCheck(address(0), 0, msgData); + } + + function test_GivenTargetIsAModule() external whenCallingPreCheckWithSINGLEMode { + // it should revert with ModuleCallNotAllowed + _install(); + bytes memory msgData = _singleMsgData(address(mockModule), 0, abi.encodeWithSelector(BALANCE_OF, address(1))); + vm.prank(account); + vm.expectRevert(abi.encodeWithSelector(DefaultSecurityHook.ModuleCallNotAllowed.selector, address(mockModule))); + hook.preCheck(address(0), 0, msgData); + } + + function test_GivenValueIsGreaterThanZero() external whenCallingPreCheckWithSINGLEMode { + // it should revert with ETHTransferNotAllowed + _install(); + bytes memory msgData = _singleMsgData(randomTarget, 1 ether, hex""); + vm.prank(account); + vm.expectRevert( + abi.encodeWithSelector(DefaultSecurityHook.ETHTransferNotAllowed.selector, randomTarget, 1 ether) + ); + hook.preCheck(address(0), 0, msgData); + } + + function test_GivenSelectorIsERC20Transfer() external whenCallingPreCheckWithSINGLEMode { + // it should revert with TokenTransferNotAllowed + _install(); + bytes memory callData = abi.encodeCall(IERC20.transfer, (recipient, 100)); + bytes memory msgData = _singleMsgData(address(mockERC20), 0, callData); + vm.prank(account); + vm.expectRevert( + abi.encodeWithSelector(DefaultSecurityHook.TokenTransferNotAllowed.selector, address(mockERC20), TRANSFER) + ); + hook.preCheck(address(0), 0, msgData); + } + + function test_GivenSelectorIsERC20Approve() external whenCallingPreCheckWithSINGLEMode { + // it should revert with TokenTransferNotAllowed + _install(); + bytes memory callData = abi.encodeCall(IERC20.approve, (recipient, 100)); + bytes memory msgData = _singleMsgData(address(mockERC20), 0, callData); + vm.prank(account); + vm.expectRevert( + abi.encodeWithSelector(DefaultSecurityHook.TokenTransferNotAllowed.selector, address(mockERC20), APPROVE) + ); + hook.preCheck(address(0), 0, msgData); + } + + function test_GivenSelectorIsERC20TransferFrom() external whenCallingPreCheckWithSINGLEMode { + // it should revert with TokenTransferNotAllowed + _install(); + bytes memory callData = abi.encodeCall(IERC20.transferFrom, (account, recipient, 100)); + bytes memory msgData = _singleMsgData(address(mockERC20), 0, callData); + vm.prank(account); + vm.expectRevert( + abi.encodeWithSelector( + DefaultSecurityHook.TokenTransferNotAllowed.selector, address(mockERC20), TRANSFER_FROM + ) + ); + hook.preCheck(address(0), 0, msgData); + } + + function test_GivenSelectorIsERC20IncreaseAllowance() external whenCallingPreCheckWithSINGLEMode { + // it should revert with TokenTransferNotAllowed + _install(); + bytes memory callData = abi.encodeWithSelector(INCREASE_ALLOWANCE, recipient, 100); + bytes memory msgData = _singleMsgData(address(mockERC20), 0, callData); + vm.prank(account); + vm.expectRevert( + abi.encodeWithSelector( + DefaultSecurityHook.TokenTransferNotAllowed.selector, address(mockERC20), INCREASE_ALLOWANCE + ) + ); + hook.preCheck(address(0), 0, msgData); + } + + function test_GivenSelectorIsERC20DecreaseAllowance() external whenCallingPreCheckWithSINGLEMode { + // it should revert with TokenTransferNotAllowed + _install(); + bytes memory callData = abi.encodeWithSelector(DECREASE_ALLOWANCE, recipient, 100); + bytes memory msgData = _singleMsgData(address(mockERC20), 0, callData); + vm.prank(account); + vm.expectRevert( + abi.encodeWithSelector( + DefaultSecurityHook.TokenTransferNotAllowed.selector, address(mockERC20), DECREASE_ALLOWANCE + ) + ); + hook.preCheck(address(0), 0, msgData); + } + + function test_GivenSelectorIsERC721SafeTransferFrom() external whenCallingPreCheckWithSINGLEMode { + // it should revert with TokenTransferNotAllowed + _install(); + bytes memory callData = abi.encodeWithSelector(SAFE_TRANSFER_FROM, account, recipient, 1); + bytes memory msgData = _singleMsgData(address(mockERC721), 0, callData); + vm.prank(account); + vm.expectRevert( + abi.encodeWithSelector( + DefaultSecurityHook.TokenTransferNotAllowed.selector, address(mockERC721), SAFE_TRANSFER_FROM + ) + ); + hook.preCheck(address(0), 0, msgData); + } + + function test_GivenSelectorIsERC721SafeTransferFromWithData() external whenCallingPreCheckWithSINGLEMode { + // it should revert with TokenTransferNotAllowed + _install(); + bytes memory callData = abi.encodeWithSelector(SAFE_TRANSFER_FROM_WITH_DATA, account, recipient, 1, hex""); + bytes memory msgData = _singleMsgData(address(mockERC721), 0, callData); + vm.prank(account); + vm.expectRevert( + abi.encodeWithSelector( + DefaultSecurityHook.TokenTransferNotAllowed.selector, address(mockERC721), SAFE_TRANSFER_FROM_WITH_DATA + ) + ); + hook.preCheck(address(0), 0, msgData); + } + + function test_GivenSelectorIsERC721SetApprovalForAll() external whenCallingPreCheckWithSINGLEMode { + // it should revert with TokenTransferNotAllowed + _install(); + bytes memory callData = abi.encodeCall(IERC721.setApprovalForAll, (recipient, true)); + bytes memory msgData = _singleMsgData(address(mockERC721), 0, callData); + vm.prank(account); + vm.expectRevert( + abi.encodeWithSelector( + DefaultSecurityHook.TokenTransferNotAllowed.selector, address(mockERC721), SET_APPROVAL_FOR_ALL + ) + ); + hook.preCheck(address(0), 0, msgData); + } + + function test_GivenSelectorIsERC1155SafeTransferFrom() external whenCallingPreCheckWithSINGLEMode { + // it should revert with TokenTransferNotAllowed + _install(); + bytes memory callData = abi.encodeCall(IERC1155.safeTransferFrom, (account, recipient, 1, 1, hex"")); + bytes memory msgData = _singleMsgData(address(mockERC1155), 0, callData); + vm.prank(account); + vm.expectRevert( + abi.encodeWithSelector( + DefaultSecurityHook.TokenTransferNotAllowed.selector, address(mockERC1155), SAFE_TRANSFER_FROM_1155 + ) + ); + hook.preCheck(address(0), 0, msgData); + } + + function test_GivenSelectorIsERC1155SafeBatchTransferFrom() external whenCallingPreCheckWithSINGLEMode { + // it should revert with TokenTransferNotAllowed + _install(); + uint256[] memory ids = new uint256[](1); + ids[0] = 1; + uint256[] memory amounts = new uint256[](1); + amounts[0] = 1; + bytes memory callData = + abi.encodeCall(IERC1155.safeBatchTransferFrom, (account, recipient, ids, amounts, hex"")); + bytes memory msgData = _singleMsgData(address(mockERC1155), 0, callData); + vm.prank(account); + vm.expectRevert( + abi.encodeWithSelector( + DefaultSecurityHook.TokenTransferNotAllowed.selector, address(mockERC1155), SAFE_BATCH_TRANSFER_FROM + ) + ); + hook.preCheck(address(0), 0, msgData); + } + + function test_GivenCallHasNoBlockedSelectorAndNoValueAndTargetIsClean() external whenCallingPreCheckWithSINGLEMode { + // it should return empty bytes + _install(); + bytes memory msgData = _singleMsgData(randomTarget, 0, abi.encodeWithSelector(BALANCE_OF, address(1))); + bytes memory result = _preCheck(msgData); + assertEq(result, hex"", "Should return empty bytes for clean call"); + } + + function test_GivenCalldataIsLessThan4Bytes() external whenCallingPreCheckWithSINGLEMode { + // it should return empty bytes (no selector to match, and no value, clean target) + _install(); + // 3 bytes of calldata — less than 4 + bytes memory msgData = _singleMsgData(randomTarget, 0, hex"aabbcc"); + bytes memory result = _preCheck(msgData); + assertEq(result, hex"", "Should return empty bytes for short calldata"); + } + + // ==================== preCheck BATCH Tests ==================== + + modifier whenCallingPreCheckWithBATCHMode() { + _; + } + + function test_GivenAllCallsInBatchAreClean() external whenCallingPreCheckWithBATCHMode { + // it should return empty bytes + _install(); + + Execution[] memory execs = new Execution[](2); + execs[0] = Execution({target: randomTarget, value: 0, callData: abi.encodeWithSelector(BALANCE_OF, address(1))}); + execs[1] = Execution({target: randomTarget, value: 0, callData: abi.encodeWithSelector(BALANCE_OF, address(2))}); + + bytes memory msgData = _batchMsgData(execs); + bytes memory result = _preCheck(msgData); + assertEq(result, hex"", "Should return empty bytes for clean batch"); + } + + function test_GivenOneCallInBatchHasBlockedSelector() external whenCallingPreCheckWithBATCHMode { + // it should revert with TokenTransferNotAllowed + _install(); + + Execution[] memory execs = new Execution[](2); + execs[0] = Execution({target: randomTarget, value: 0, callData: abi.encodeWithSelector(BALANCE_OF, address(1))}); + execs[1] = Execution({ + target: address(mockERC20), value: 0, callData: abi.encodeCall(IERC20.transfer, (recipient, 100)) + }); + + bytes memory msgData = _batchMsgData(execs); + vm.prank(account); + vm.expectRevert( + abi.encodeWithSelector(DefaultSecurityHook.TokenTransferNotAllowed.selector, address(mockERC20), TRANSFER) + ); + hook.preCheck(address(0), 0, msgData); + } + + function test_GivenBatchHasAllowlistedAndBlockedCalls() external whenCallingPreCheckWithBATCHMode { + // it should revert for the blocked call + // Allowlist mockERC20 but not mockERC721 + DefaultSecurityHook.AllowlistConfig[] memory configs = new DefaultSecurityHook.AllowlistConfig[](1); + bytes4[] memory sels = new bytes4[](0); + configs[0] = DefaultSecurityHook.AllowlistConfig({target: address(mockERC20), selectors: sels}); + _installWithConfig(configs); + + Execution[] memory execs = new Execution[](2); + // This call is allowlisted (mockERC20 with all selectors) + execs[0] = Execution({ + target: address(mockERC20), value: 0, callData: abi.encodeCall(IERC20.transfer, (recipient, 100)) + }); + // This call is NOT allowlisted and has a blocked selector + execs[1] = Execution({ + target: address(mockERC721), + value: 0, + callData: abi.encodeCall(IERC721.setApprovalForAll, (recipient, true)) + }); + + bytes memory msgData = _batchMsgData(execs); + vm.prank(account); + vm.expectRevert( + abi.encodeWithSelector( + DefaultSecurityHook.TokenTransferNotAllowed.selector, address(mockERC721), SET_APPROVAL_FOR_ALL + ) + ); + hook.preCheck(address(0), 0, msgData); + } + + // ==================== postCheck Tests ==================== + + function test_WhenCallingPostCheck() external { + // it should not revert + hook.postCheck(hex""); + hook.postCheck(hex"1234"); + assertTrue(true, "postCheck should not revert"); + } + + // ==================== setAllowlist Tests ==================== + + modifier whenCallingSetAllowlist() { + _; + } + + function test_GivenCallerIsNotInitialized() external whenCallingSetAllowlist { + // it should revert with Unauthorized + bytes4[] memory sels = new bytes4[](0); + vm.prank(account); + vm.expectRevert(DefaultSecurityHook.Unauthorized.selector); + hook.setAllowlist(randomTarget, sels); + } + + function test_GivenSettingWithEmptySelectors() external whenCallingSetAllowlist { + // it should set allSelectorsAllowed to true + // it should emit AllowlistSet event + _install(); + + bytes4[] memory sels = new bytes4[](0); + vm.prank(account); + vm.expectEmit(true, true, false, true); + emit AllowlistSet(account, randomTarget, sels); + hook.setAllowlist(randomTarget, sels); + + assertTrue(hook.isAllowlisted(account, randomTarget), "Target should be allowlisted"); + assertTrue(hook.isSelectorAllowed(account, randomTarget, TRANSFER), "All selectors should be allowed"); + } + + function test_GivenSettingWithSpecificSelectors() external whenCallingSetAllowlist { + // it should set each selector as allowed + // it should set allSelectorsAllowed to false + // it should emit AllowlistSet event + _install(); + + bytes4[] memory sels = new bytes4[](2); + sels[0] = TRANSFER; + sels[1] = APPROVE; + + vm.prank(account); + vm.expectEmit(true, true, false, true); + emit AllowlistSet(account, randomTarget, sels); + hook.setAllowlist(randomTarget, sels); + + assertTrue(hook.isAllowlisted(account, randomTarget), "Target should be allowlisted"); + assertTrue(hook.isSelectorAllowed(account, randomTarget, TRANSFER), "TRANSFER should be allowed"); + assertTrue(hook.isSelectorAllowed(account, randomTarget, APPROVE), "APPROVE should be allowed"); + assertFalse(hook.isSelectorAllowed(account, randomTarget, TRANSFER_FROM), "TRANSFER_FROM should not be allowed"); + } + + // ==================== removeAllowlist Tests ==================== + + modifier whenCallingRemoveAllowlist() { + _; + } + + function test_GivenCallerIsNotInitialized_WhenCallingRemoveAllowlist() external whenCallingRemoveAllowlist { + // it should revert with Unauthorized + vm.prank(account); + vm.expectRevert(DefaultSecurityHook.Unauthorized.selector); + hook.removeAllowlist(randomTarget); + } + + function test_GivenRemovingExistingTarget() external whenCallingRemoveAllowlist { + // it should set allowed to false + // it should emit AllowlistRemoved event + _install(); + + bytes4[] memory sels = new bytes4[](0); + vm.prank(account); + hook.setAllowlist(randomTarget, sels); + + assertTrue(hook.isAllowlisted(account, randomTarget), "Target should be allowlisted before removal"); + + vm.prank(account); + vm.expectEmit(true, true, false, false); + emit AllowlistRemoved(account, randomTarget); + hook.removeAllowlist(randomTarget); + + assertFalse(hook.isAllowlisted(account, randomTarget), "Target should not be allowlisted after removal"); + } + + // ==================== isInitialized Tests ==================== + + modifier whenCallingIsInitialized() { + _; + } + + function test_GivenAccountIsInitialized() external whenCallingIsInitialized { + // it should return true + _install(); + assertTrue(hook.isInitialized(account), "Should return true for initialized account"); + } + + function test_GivenAccountIsNotInitialized_WhenCallingIsInitialized() external whenCallingIsInitialized { + // it should return false + assertFalse(hook.isInitialized(account), "Should return false for uninitialized account"); + } + + // ==================== isAllowlisted Tests ==================== + + modifier whenCallingIsAllowlisted() { + _; + } + + function test_GivenTargetIsAllowlisted() external whenCallingIsAllowlisted { + // it should return true + _install(); + bytes4[] memory sels = new bytes4[](0); + vm.prank(account); + hook.setAllowlist(randomTarget, sels); + + assertTrue(hook.isAllowlisted(account, randomTarget), "Should return true for allowlisted target"); + } + + function test_GivenTargetIsNotAllowlisted() external whenCallingIsAllowlisted { + // it should return false + assertFalse(hook.isAllowlisted(account, randomTarget), "Should return false for non-allowlisted target"); + } + + // ==================== isSelectorAllowed Tests ==================== + + modifier whenCallingIsSelectorAllowed() { + _; + } + + function test_GivenTargetIsNotAllowlisted_WhenCallingIsSelectorAllowed() external whenCallingIsSelectorAllowed { + // it should return false + assertFalse( + hook.isSelectorAllowed(account, randomTarget, TRANSFER), "Should return false when target not allowlisted" + ); + } + + function test_GivenTargetIsAllowlistedWithAllSelectors_WhenCallingIsSelectorAllowed() + external + whenCallingIsSelectorAllowed + { + // it should return true for any selector + _install(); + bytes4[] memory sels = new bytes4[](0); + vm.prank(account); + hook.setAllowlist(randomTarget, sels); + + assertTrue( + hook.isSelectorAllowed(account, randomTarget, TRANSFER), + "Should return true for any selector when all allowed" + ); + assertTrue( + hook.isSelectorAllowed(account, randomTarget, bytes4(0xdeadbeef)), + "Should return true for arbitrary selector when all allowed" + ); + } + + modifier givenTargetIsAllowlistedWithSpecificSelectors() { + _install(); + bytes4[] memory sels = new bytes4[](1); + sels[0] = TRANSFER; + vm.prank(account); + hook.setAllowlist(randomTarget, sels); + _; + } + + function test_GivenQueriedSelectorIsInTheList() + external + whenCallingIsSelectorAllowed + givenTargetIsAllowlistedWithSpecificSelectors + { + // it should return true + assertTrue(hook.isSelectorAllowed(account, randomTarget, TRANSFER), "Should return true for allowed selector"); + } + + function test_GivenQueriedSelectorIsNotInTheList() + external + whenCallingIsSelectorAllowed + givenTargetIsAllowlistedWithSpecificSelectors + { + // it should return false + assertFalse( + hook.isSelectorAllowed(account, randomTarget, APPROVE), "Should return false for non-allowed selector" + ); + } + + // ==================== S-01 Regression: Stale selectors cleared on update ==================== + + function test_S01_StaleSelectorsAreClearedOnAllowlistUpdate() external { + _install(); + + // Step 1: Allowlist with TRANSFER and APPROVE + bytes4[] memory sels1 = new bytes4[](2); + sels1[0] = TRANSFER; + sels1[1] = APPROVE; + vm.prank(account); + hook.setAllowlist(randomTarget, sels1); + + assertTrue(hook.isSelectorAllowed(account, randomTarget, TRANSFER), "TRANSFER should be allowed"); + assertTrue(hook.isSelectorAllowed(account, randomTarget, APPROVE), "APPROVE should be allowed"); + + // Step 2: Update to only TRANSFER + bytes4[] memory sels2 = new bytes4[](1); + sels2[0] = TRANSFER; + vm.prank(account); + hook.setAllowlist(randomTarget, sels2); + + // APPROVE must be cleared + assertTrue(hook.isSelectorAllowed(account, randomTarget, TRANSFER), "TRANSFER should still be allowed"); + assertFalse(hook.isSelectorAllowed(account, randomTarget, APPROVE), "APPROVE should be cleared after update"); + } + + function test_S01_StaleSelectorsAreClearedOnRemoveAllowlist() external { + _install(); + + // Allowlist with specific selectors + bytes4[] memory sels = new bytes4[](1); + sels[0] = TRANSFER; + vm.prank(account); + hook.setAllowlist(randomTarget, sels); + + assertTrue(hook.isSelectorAllowed(account, randomTarget, TRANSFER), "TRANSFER should be allowed"); + + // Remove allowlist + vm.prank(account); + hook.removeAllowlist(randomTarget); + + // Re-add allowlist with different selectors + bytes4[] memory sels2 = new bytes4[](1); + sels2[0] = APPROVE; + vm.prank(account); + hook.setAllowlist(randomTarget, sels2); + + // TRANSFER must not persist from the old allowlist + assertFalse( + hook.isSelectorAllowed(account, randomTarget, TRANSFER), "TRANSFER should not persist after remove+re-add" + ); + assertTrue(hook.isSelectorAllowed(account, randomTarget, APPROVE), "APPROVE should be allowed"); + } + + // ==================== S-02 Regression: Unknown call types revert ==================== + + function test_S02_UnknownCallTypeReverts() external { + _install(); + + // Build msgData with CALLTYPE_STATICCALL (0xfe) + bytes32 mode = + LibERC7579.encodeMode(LibERC7579.CALLTYPE_STATICCALL, LibERC7579.EXECTYPE_DEFAULT, bytes4(0), bytes22(0)); + bytes memory executionData = abi.encodePacked(randomTarget, uint256(0)); + bytes memory msgData = abi.encodeWithSelector(IERC7579Execution.execute.selector, mode, executionData); + + vm.prank(account); + vm.expectRevert(DefaultSecurityHook.UnsupportedCallType.selector); + hook.preCheck(address(0), 0, msgData); + } + + // ==================== S-03 Regression: onUninstall clears ALL state ==================== + + function test_S03_OnUninstallClearsAllTargetsWithoutCallerData() external { + // Install with two targets + DefaultSecurityHook.AllowlistConfig[] memory configs = new DefaultSecurityHook.AllowlistConfig[](2); + bytes4[] memory sels1 = new bytes4[](1); + sels1[0] = TRANSFER; + configs[0] = DefaultSecurityHook.AllowlistConfig({target: randomTarget, selectors: sels1}); + + address target2 = address(0xBEEF); + bytes4[] memory sels2 = new bytes4[](0); + configs[1] = DefaultSecurityHook.AllowlistConfig({target: target2, selectors: sels2}); + _installWithConfig(configs); + + assertTrue(hook.isAllowlisted(account, randomTarget), "randomTarget should be allowlisted"); + assertTrue(hook.isAllowlisted(account, target2), "target2 should be allowlisted"); + + // Uninstall with empty data -- should still clear everything + vm.prank(account); + hook.onUninstall(""); + + assertFalse(hook.isAllowlisted(account, randomTarget), "randomTarget should be cleared after uninstall"); + assertFalse(hook.isAllowlisted(account, target2), "target2 should be cleared after uninstall"); + assertFalse( + hook.isSelectorAllowed(account, randomTarget, TRANSFER), + "TRANSFER selector should be cleared after uninstall" + ); + } + + function test_S03_StaleStateDoesNotPersistAcrossReinstall() external { + // Install with target allowlisted + DefaultSecurityHook.AllowlistConfig[] memory configs1 = new DefaultSecurityHook.AllowlistConfig[](1); + bytes4[] memory sels1 = new bytes4[](1); + sels1[0] = TRANSFER; + configs1[0] = DefaultSecurityHook.AllowlistConfig({target: randomTarget, selectors: sels1}); + _installWithConfig(configs1); + + assertTrue(hook.isSelectorAllowed(account, randomTarget, TRANSFER), "TRANSFER should be allowed"); + + // Uninstall (empty data) + vm.prank(account); + hook.onUninstall(""); + + // Reinstall with different config (APPROVE only) + DefaultSecurityHook.AllowlistConfig[] memory configs2 = new DefaultSecurityHook.AllowlistConfig[](1); + bytes4[] memory sels2 = new bytes4[](1); + sels2[0] = APPROVE; + configs2[0] = DefaultSecurityHook.AllowlistConfig({target: randomTarget, selectors: sels2}); + _installWithConfig(configs2); + + // TRANSFER must NOT persist from the first installation + assertFalse( + hook.isSelectorAllowed(account, randomTarget, TRANSFER), "TRANSFER should not persist across reinstall" + ); + assertTrue(hook.isSelectorAllowed(account, randomTarget, APPROVE), "APPROVE should be allowed after reinstall"); + } +} diff --git a/test/btt/DefaultSecurityHook.t.tree b/test/btt/DefaultSecurityHook.t.tree new file mode 100644 index 0000000..fc811e5 --- /dev/null +++ b/test/btt/DefaultSecurityHook.t.tree @@ -0,0 +1,120 @@ +DefaultSecurityHookBTTTest +├── when calling onInstall +│ ├── given account is already initialized +│ │ └── it should revert with AlreadyInitialized +│ ├── given data is empty +│ │ ├── it should mark account as initialized +│ │ └── it should emit Initialized event +│ └── given data contains allowlist configs +│ ├── it should mark account as initialized +│ ├── it should set allowlist entries for each config +│ └── it should emit Initialized event +├── when calling onUninstall +│ ├── given account is not initialized +│ │ └── it should revert with NotInitialized +│ ├── given data is empty +│ │ ├── it should mark account as not initialized +│ │ └── it should emit Uninitialized event +│ └── given data contains targets to clean +│ ├── it should clear allowlist entries for each target +│ ├── it should mark account as not initialized +│ └── it should emit Uninitialized event +├── when calling isModuleType +│ ├── given moduleTypeId is MODULE_TYPE_HOOK +│ │ └── it should return true +│ └── given moduleTypeId is not MODULE_TYPE_HOOK +│ └── it should return false +├── when calling preCheck with DELEGATECALL mode +│ └── it should revert with DelegateCallNotAllowed +├── when calling preCheck with SINGLE mode +│ ├── given target is allowlisted with all selectors +│ │ └── it should return empty bytes +│ ├── given target is allowlisted with specific selector matching call +│ │ └── it should return empty bytes +│ ├── given target is allowlisted with specific selector not matching call +│ │ └── it should revert with TokenTransferNotAllowed +│ ├── given target is self +│ │ └── it should revert with SelfCallNotAllowed +│ ├── given target is a module +│ │ └── it should revert with ModuleCallNotAllowed +│ ├── given value is greater than zero +│ │ └── it should revert with ETHTransferNotAllowed +│ ├── given selector is ERC20 transfer +│ │ └── it should revert with TokenTransferNotAllowed +│ ├── given selector is ERC20 approve +│ │ └── it should revert with TokenTransferNotAllowed +│ ├── given selector is ERC20 transferFrom +│ │ └── it should revert with TokenTransferNotAllowed +│ ├── given selector is ERC20 increaseAllowance +│ │ └── it should revert with TokenTransferNotAllowed +│ ├── given selector is ERC20 decreaseAllowance +│ │ └── it should revert with TokenTransferNotAllowed +│ ├── given selector is ERC721 safeTransferFrom +│ │ └── it should revert with TokenTransferNotAllowed +│ ├── given selector is ERC721 safeTransferFromWithData +│ │ └── it should revert with TokenTransferNotAllowed +│ ├── given selector is ERC721 setApprovalForAll +│ │ └── it should revert with TokenTransferNotAllowed +│ ├── given selector is ERC1155 safeTransferFrom +│ │ └── it should revert with TokenTransferNotAllowed +│ ├── given selector is ERC1155 safeBatchTransferFrom +│ │ └── it should revert with TokenTransferNotAllowed +│ ├── given call has no blocked selector and no value and target is clean +│ │ └── it should return empty bytes +│ └── given calldata is less than 4 bytes +│ └── it should return empty bytes +├── when calling preCheck with BATCH mode +│ ├── given all calls in batch are clean +│ │ └── it should return empty bytes +│ ├── given one call in batch has blocked selector +│ │ └── it should revert with TokenTransferNotAllowed +│ └── given batch has allowlisted and blocked calls +│ └── it should revert for the blocked call +├── when calling postCheck +│ └── it should not revert +├── when calling setAllowlist +│ ├── given caller is not initialized +│ │ └── it should revert with Unauthorized +│ ├── given setting with empty selectors +│ │ ├── it should set allSelectorsAllowed to true +│ │ └── it should emit AllowlistSet event +│ └── given setting with specific selectors +│ ├── it should set each selector as allowed +│ ├── it should set allSelectorsAllowed to false +│ └── it should emit AllowlistSet event +├── when calling removeAllowlist +│ ├── given caller is not initialized +│ │ └── it should revert with Unauthorized +│ └── given removing existing target +│ ├── it should set allowed to false +│ └── it should emit AllowlistRemoved event +├── when calling isInitialized +│ ├── given account is initialized +│ │ └── it should return true +│ └── given account is not initialized +│ └── it should return false +├── when calling isAllowlisted +│ ├── given target is allowlisted +│ │ └── it should return true +│ └── given target is not allowlisted +│ └── it should return false +├── when calling isSelectorAllowed + ├── given target is not allowlisted + │ └── it should return false + ├── given target is allowlisted with all selectors + │ └── it should return true for any selector + └── given target is allowlisted with specific selectors + ├── given queried selector is in the list + │ └── it should return true + └── given queried selector is not in the list + └── it should return false +├── when updating an allowlist with fewer selectors +│ └── it should clear selectors omitted by the update +├── when removing and re-adding an allowlist with different selectors +│ └── it should not retain selectors from the removed allowlist +├── when calling preCheck with an unsupported call type +│ └── it should revert with UnsupportedCallType +├── when calling onUninstall with configured targets and empty data +│ └── it should clear every target and selector tracked for the account +└── when reinstalling after uninstall + └── it should not retain allowlist state from the previous installation diff --git a/test/btt/ECDSASigner.t.sol b/test/btt/ECDSASigner.t.sol index dfde846..170a592 100644 --- a/test/btt/ECDSASigner.t.sol +++ b/test/btt/ECDSASigner.t.sol @@ -120,7 +120,7 @@ contract ECDSASignerBTTTest is Test { _installSigner(); vm.startPrank(wallet); - vm.expectRevert("Already installed"); + vm.expectRevert(ECDSASigner.SignerAlreadySet.selector); ecdsaSigner.onInstall(abi.encodePacked(signerId, owner)); vm.stopPrank(); } @@ -394,9 +394,7 @@ contract ECDSASignerBTTTest is Test { vm.prank(wallet); uint256 result = ecdsaSigner.checkUserOpSignature(signerId, userOp, userOpHash); assertEq( - result, - SIG_VALIDATION_FAILED_UINT, - "Should return SIG_VALIDATION_FAILED_UINT after both branches fail" + result, SIG_VALIDATION_FAILED_UINT, "Should return SIG_VALIDATION_FAILED_UINT after both branches fail" ); } diff --git a/test/btt/ECDSAValidator.t.sol b/test/btt/ECDSAValidator.t.sol index 286dfd9..1ec9008 100644 --- a/test/btt/ECDSAValidator.t.sol +++ b/test/btt/ECDSAValidator.t.sol @@ -361,7 +361,7 @@ contract ECDSAValidatorBTTTest is Test { address notOwner = address(0x9999); vm.startPrank(wallet); - vm.expectRevert("ECDSAValidator: sender is not owner"); + vm.expectRevert(ECDSAValidator.SenderNotOwner.selector); ecdsaValidator.preCheck(notOwner, 0, ""); vm.stopPrank(); } @@ -440,9 +440,7 @@ contract ECDSAValidatorBTTTest is Test { vm.prank(wallet); uint256 result = ecdsaValidator.validateUserOp(userOp, userOpHash); assertEq( - result, - SIG_VALIDATION_FAILED_UINT, - "Should return SIG_VALIDATION_FAILED_UINT after both branches fail" + result, SIG_VALIDATION_FAILED_UINT, "Should return SIG_VALIDATION_FAILED_UINT after both branches fail" ); } diff --git a/test/btt/MultiOwnerValidator.t.sol b/test/btt/MultiOwnerValidator.t.sol new file mode 100644 index 0000000..aa4b231 --- /dev/null +++ b/test/btt/MultiOwnerValidator.t.sol @@ -0,0 +1,329 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.20; + +import {Test} from "forge-std/Test.sol"; +import {PackedUserOperation} from "account-abstraction/interfaces/PackedUserOperation.sol"; + +import {IModule, IStatelessValidator} from "src/interfaces/IERC7579Modules.sol"; +import { + ERC1271_INVALID, + ERC1271_MAGICVALUE, + MODULE_TYPE_STATELESS_VALIDATOR, + SIG_VALIDATION_FAILED_UINT +} from "src/types/Constants.sol"; +import {MultiOwnerValidator} from "src/validators/MultiOwnerValidator.sol"; + +contract BehaviorStatelessSigner is IStatelessValidator { + function onInstall(bytes calldata) external payable {} + + function onUninstall(bytes calldata) external payable {} + + function isModuleType(uint256 moduleTypeId) external pure returns (bool) { + return moduleTypeId == MODULE_TYPE_STATELESS_VALIDATOR; + } + + function validateSignatureWithData(bytes32 hash, bytes calldata signature, bytes calldata data) + external + pure + returns (bool) + { + return keccak256(signature) == keccak256(abi.encodePacked(hash, data)); + } +} + +contract BehaviorRevertingSigner is IStatelessValidator { + function onInstall(bytes calldata) external payable {} + + function onUninstall(bytes calldata) external payable {} + + function isModuleType(uint256 moduleTypeId) external pure returns (bool) { + return moduleTypeId == MODULE_TYPE_STATELESS_VALIDATOR; + } + + function validateSignatureWithData(bytes32, bytes calldata, bytes calldata) external pure returns (bool) { + revert("reverting signer"); + } +} + +contract MultiOwnerValidatorBehaviorTreeTest is Test { + address internal constant ACCOUNT = address(0xA11); + address internal constant OTHER_ACCOUNT = address(0xB22); + + bytes32 internal constant OWNER_ID = keccak256("owner"); + bytes32 internal constant OTHER_OWNER_ID = keccak256("other-owner"); + bytes32 internal constant THIRD_OWNER_ID = keccak256("third-owner"); + + MultiOwnerValidator internal validator; + BehaviorStatelessSigner internal firstSigner; + BehaviorStatelessSigner internal secondSigner; + BehaviorRevertingSigner internal revertingSigner; + + function setUp() public { + validator = new MultiOwnerValidator(); + firstSigner = new BehaviorStatelessSigner(); + secondSigner = new BehaviorStatelessSigner(); + revertingSigner = new BehaviorRevertingSigner(); + } + + modifier whenAccountIsInitialized() { + _install(ACCOUNT, _single(_config(OWNER_ID, address(firstSigner), hex"a1"))); + _; + } + + function test_RevertWhen_InstallingAnEmptyRegistry() external { + MultiOwnerValidator.OwnerConfig[] memory configs = new MultiOwnerValidator.OwnerConfig[](0); + vm.prank(ACCOUNT); + vm.expectRevert(MultiOwnerValidator.EmptyOwners.selector); + validator.onInstall(abi.encode(configs)); + } + + function test_RevertWhen_InstallingDuplicateOwnerIds() external { + MultiOwnerValidator.OwnerConfig[] memory configs = new MultiOwnerValidator.OwnerConfig[](2); + configs[0] = _config(OWNER_ID, address(firstSigner), hex"a1"); + configs[1] = _config(OWNER_ID, address(secondSigner), hex"b2"); + + vm.prank(ACCOUNT); + vm.expectRevert(abi.encodeWithSelector(MultiOwnerValidator.OwnerAlreadyExists.selector, OWNER_ID)); + validator.onInstall(abi.encode(configs)); + } + + function test_WhenInstallingDifferentStatelessSigners() external { + MultiOwnerValidator.OwnerConfig[] memory configs = new MultiOwnerValidator.OwnerConfig[](3); + configs[0] = _config(OWNER_ID, address(firstSigner), hex"a1"); + configs[1] = _config(OTHER_OWNER_ID, address(secondSigner), hex"b2"); + configs[2] = _config(THIRD_OWNER_ID, address(firstSigner), hex"c3"); + + _install(ACCOUNT, configs); + + assertTrue(validator.isInitialized(ACCOUNT)); + assertEq(validator.ownerCount(ACCOUNT), 3); + assertEq(validator.ownerIdAt(ACCOUNT, 0), OWNER_ID); + assertEq(validator.ownerIdAt(ACCOUNT, 1), OTHER_OWNER_ID); + assertEq(validator.ownerIdAt(ACCOUNT, 2), THIRD_OWNER_ID); + (address selected, bytes memory data) = validator.owners(ACCOUNT, OTHER_OWNER_ID); + assertEq(selected, address(secondSigner)); + assertEq(data, hex"b2"); + } + + function test_WhenAddingAnOwner() external whenAccountIsInitialized { + vm.prank(ACCOUNT); + validator.addOwner(_config(OTHER_OWNER_ID, address(secondSigner), hex"b2")); + + assertEq(validator.ownerCount(ACCOUNT), 2); + (address selected, bytes memory data) = validator.owners(ACCOUNT, OTHER_OWNER_ID); + assertEq(selected, address(secondSigner)); + assertEq(data, hex"b2"); + } + + function test_RevertWhen_AddingAnExistingOwnerId() external whenAccountIsInitialized { + vm.prank(ACCOUNT); + vm.expectRevert(abi.encodeWithSelector(MultiOwnerValidator.OwnerAlreadyExists.selector, OWNER_ID)); + validator.addOwner(_config(OWNER_ID, address(secondSigner), hex"b2")); + } + + function test_RevertWhen_AddingBeyondMaxOwners() external { + MultiOwnerValidator.OwnerConfig[] memory configs = new MultiOwnerValidator.OwnerConfig[](validator.MAX_OWNERS()); + for (uint256 i; i < configs.length; ++i) { + configs[i] = _config(bytes32(i + 1), address(firstSigner), abi.encode(i)); + } + _install(ACCOUNT, configs); + + vm.prank(ACCOUNT); + vm.expectRevert(MultiOwnerValidator.MaxOwnersExceeded.selector); + validator.addOwner(_config(bytes32(configs.length + 1), address(secondSigner), hex"ff")); + } + + function test_WhenUpdatingAnOwner() external whenAccountIsInitialized { + vm.prank(ACCOUNT); + validator.updateOwner(_config(OWNER_ID, address(secondSigner), hex"b2")); + + assertEq(validator.ownerCount(ACCOUNT), 1); + (address selected, bytes memory data) = validator.owners(ACCOUNT, OWNER_ID); + assertEq(selected, address(secondSigner)); + assertEq(data, hex"b2"); + + bytes32 hash = keccak256("updated owner"); + vm.startPrank(ACCOUNT); + assertEq( + validator.isValidSignatureWithSender(address(0), hash, _signature(OWNER_ID, hash, hex"a1")), ERC1271_INVALID + ); + assertEq( + validator.isValidSignatureWithSender(address(0), hash, _signature(OWNER_ID, hash, hex"b2")), + ERC1271_MAGICVALUE + ); + vm.stopPrank(); + } + + function test_RevertWhen_UpdatingAnUnknownOwner() external whenAccountIsInitialized { + vm.prank(ACCOUNT); + vm.expectRevert(abi.encodeWithSelector(MultiOwnerValidator.OwnerDoesNotExist.selector, OTHER_OWNER_ID)); + validator.updateOwner(_config(OTHER_OWNER_ID, address(secondSigner), hex"b2")); + } + + function test_WhenRemovingAnOwner() external whenAccountIsInitialized { + vm.prank(ACCOUNT); + validator.addOwner(_config(OTHER_OWNER_ID, address(secondSigner), hex"b2")); + + vm.prank(ACCOUNT); + validator.removeOwner(OWNER_ID); + + assertEq(validator.ownerCount(ACCOUNT), 1); + assertEq(validator.ownerIdAt(ACCOUNT, 0), OTHER_OWNER_ID); + (address selected, bytes memory data) = validator.owners(ACCOUNT, OWNER_ID); + assertEq(selected, address(0)); + assertEq(data.length, 0); + } + + function test_RevertWhen_RemovingTheLastOwner() external whenAccountIsInitialized { + vm.prank(ACCOUNT); + vm.expectRevert(MultiOwnerValidator.CannotRemoveLastOwner.selector); + validator.removeOwner(OWNER_ID); + } + + function test_WhenUninstallingTheRegistry() external whenAccountIsInitialized { + vm.prank(ACCOUNT); + validator.addOwner(_config(OTHER_OWNER_ID, address(secondSigner), hex"b2")); + + vm.prank(ACCOUNT); + validator.onUninstall(""); + + assertFalse(validator.isInitialized(ACCOUNT)); + assertEq(validator.ownerCount(ACCOUNT), 0); + (address first,) = validator.owners(ACCOUNT, OWNER_ID); + (address second,) = validator.owners(ACCOUNT, OTHER_OWNER_ID); + assertEq(first, address(0)); + assertEq(second, address(0)); + } + + function test_WhenValidatingWithAnyRegisteredStatelessSigner() external whenAccountIsInitialized { + vm.prank(ACCOUNT); + validator.addOwner(_config(OTHER_OWNER_ID, address(secondSigner), hex"b2")); + + bytes32 hash = keccak256("equal owner rights"); + vm.startPrank(ACCOUNT); + assertEq( + validator.isValidSignatureWithSender(address(0), hash, _signature(OWNER_ID, hash, hex"a1")), + ERC1271_MAGICVALUE + ); + assertEq( + validator.isValidSignatureWithSender(address(0), hash, _signature(OTHER_OWNER_ID, hash, hex"b2")), + ERC1271_MAGICVALUE + ); + vm.stopPrank(); + } + + function test_WhenOwnerIdAndValidationDataDoNotMatch() external whenAccountIsInitialized { + vm.prank(ACCOUNT); + validator.addOwner(_config(OTHER_OWNER_ID, address(secondSigner), hex"b2")); + + bytes32 hash = keccak256("owner binding"); + vm.startPrank(ACCOUNT); + assertEq( + validator.isValidSignatureWithSender(address(0), hash, _signature(OWNER_ID, hash, hex"b2")), ERC1271_INVALID + ); + assertEq( + validator.isValidSignatureWithSender(address(0), hash, _signature(OTHER_OWNER_ID, hash, hex"a1")), + ERC1271_INVALID + ); + vm.stopPrank(); + } + + function test_WhenAnOwnerIsRevoked() external whenAccountIsInitialized { + vm.prank(ACCOUNT); + validator.addOwner(_config(OTHER_OWNER_ID, address(secondSigner), hex"b2")); + vm.prank(ACCOUNT); + validator.removeOwner(OWNER_ID); + + bytes32 hash = keccak256("revoked owner"); + vm.prank(ACCOUNT); + assertEq( + validator.isValidSignatureWithSender(address(0), hash, _signature(OWNER_ID, hash, hex"a1")), ERC1271_INVALID + ); + } + + function test_WhenSignatureEnvelopeIsMalformedUnknownOrChildReverts() external whenAccountIsInitialized { + vm.prank(ACCOUNT); + validator.addOwner(_config(OTHER_OWNER_ID, address(revertingSigner), "")); + + bytes32 hash = keccak256("malformed envelope"); + vm.startPrank(ACCOUNT); + assertEq(validator.isValidSignatureWithSender(address(0), hash, hex"01"), ERC1271_INVALID); + assertEq( + validator.isValidSignatureWithSender(address(0), hash, _signature(bytes32(uint256(0xBAD)), hash, hex"a1")), + ERC1271_INVALID + ); + assertEq( + validator.isValidSignatureWithSender(address(0), hash, abi.encodePacked(OTHER_OWNER_ID)), ERC1271_INVALID + ); + vm.stopPrank(); + } + + function test_WhenUserOpSenderDoesNotMatchTheCallingAccount() external whenAccountIsInitialized { + bytes32 hash = keccak256("sender binding"); + PackedUserOperation memory userOp; + userOp.sender = OTHER_ACCOUNT; + userOp.signature = _signature(OWNER_ID, hash, hex"a1"); + + vm.prank(ACCOUNT); + assertEq(validator.validateUserOp(userOp, hash), SIG_VALIDATION_FAILED_UINT); + } + + function test_WhenTwoAccountsUseTheSameOwnerId() external { + _install(ACCOUNT, _single(_config(OWNER_ID, address(firstSigner), hex"a1"))); + _install(OTHER_ACCOUNT, _single(_config(OWNER_ID, address(secondSigner), hex"b2"))); + + bytes32 hash = keccak256("account separation"); + bytes memory firstSignature = _signature(OWNER_ID, hash, hex"a1"); + bytes memory secondSignature = _signature(OWNER_ID, hash, hex"b2"); + + vm.prank(ACCOUNT); + assertEq(validator.isValidSignatureWithSender(address(0), hash, firstSignature), ERC1271_MAGICVALUE); + vm.prank(ACCOUNT); + assertEq(validator.isValidSignatureWithSender(address(0), hash, secondSignature), ERC1271_INVALID); + vm.prank(OTHER_ACCOUNT); + assertEq(validator.isValidSignatureWithSender(address(0), hash, secondSignature), ERC1271_MAGICVALUE); + vm.prank(OTHER_ACCOUNT); + assertEq(validator.isValidSignatureWithSender(address(0), hash, firstSignature), ERC1271_INVALID); + } + + function test_RevertWhen_MutatingFromAnUninitializedAccount() external { + vm.startPrank(ACCOUNT); + vm.expectRevert(abi.encodeWithSelector(IModule.NotInitialized.selector, ACCOUNT)); + validator.addOwner(_config(OWNER_ID, address(firstSigner), hex"a1")); + vm.expectRevert(abi.encodeWithSelector(IModule.NotInitialized.selector, ACCOUNT)); + validator.updateOwner(_config(OWNER_ID, address(firstSigner), hex"a1")); + vm.expectRevert(abi.encodeWithSelector(IModule.NotInitialized.selector, ACCOUNT)); + validator.removeOwner(OWNER_ID); + vm.stopPrank(); + } + + function _install(address account, MultiOwnerValidator.OwnerConfig[] memory configs) internal { + vm.prank(account); + validator.onInstall(abi.encode(configs)); + } + + function _single(MultiOwnerValidator.OwnerConfig memory config) + internal + pure + returns (MultiOwnerValidator.OwnerConfig[] memory configs) + { + configs = new MultiOwnerValidator.OwnerConfig[](1); + configs[0] = config; + } + + function _config(bytes32 ownerId, address statelessValidator, bytes memory validationData) + internal + pure + returns (MultiOwnerValidator.OwnerConfig memory) + { + return MultiOwnerValidator.OwnerConfig(ownerId, statelessValidator, validationData); + } + + function _signature(bytes32 ownerId, bytes32 hash, bytes memory validationData) + internal + pure + returns (bytes memory) + { + return abi.encodePacked(ownerId, hash, validationData); + } +} diff --git a/test/btt/MultiOwnerValidator.tree b/test/btt/MultiOwnerValidator.tree new file mode 100644 index 0000000..00bd829 --- /dev/null +++ b/test/btt/MultiOwnerValidator.tree @@ -0,0 +1,51 @@ +MultiOwnerValidatorBehaviorTreeTest +├── when installing the owner registry +│ ├── when the registry is empty +│ │ └── it should revert with EmptyOwners +│ ├── when two entries have the same owner id +│ │ └── it should revert with OwnerAlreadyExists +│ └── when entries use different stateless signer modules +│ ├── it should initialize the account +│ ├── it should store every signer and validation-data pair +│ └── it should preserve their owner ids +├── when administering an initialized registry +│ ├── when adding a new owner +│ │ └── it should store the stateless signer configuration and increment owner count +│ ├── when adding an existing owner id +│ │ └── it should revert with OwnerAlreadyExists +│ ├── when adding beyond MAX_OWNERS +│ │ └── it should revert with MaxOwnersExceeded +│ ├── when updating an existing owner +│ │ ├── it should replace the delegated signer configuration immediately +│ │ └── it should not change owner count +│ ├── when updating an unknown owner +│ │ └── it should revert with OwnerDoesNotExist +│ ├── when removing one of multiple owners +│ │ ├── it should clear the removed owner +│ │ ├── it should decrement owner count +│ │ └── it should keep the enumerable index coherent +│ ├── when removing the final owner +│ │ └── it should revert with CannotRemoveLastOwner +│ └── when uninstalling the registry +│ └── it should clear every owner and the owner count +├── when administering an uninitialized registry +│ ├── when adding an owner +│ │ └── it should revert with NotInitialized +│ ├── when updating an owner +│ │ └── it should revert with NotInitialized +│ └── when removing an owner +│ └── it should revert with NotInitialized +├── when validating a signature +│ ├── when any registered stateless signer accepts +│ │ └── it should grant every selected owner equal rights +│ ├── when the owner id and validation data do not match +│ │ └── it should return ERC1271_INVALID +│ ├── when the selected owner has been revoked +│ │ └── it should return ERC1271_INVALID +│ ├── when the envelope is malformed, unknown, or the child reverts +│ │ └── it should return ERC1271_INVALID without reverting +│ └── when userOp.sender differs from the calling account +│ └── it should return SIG_VALIDATION_FAILED_UINT +└── when two accounts use the same owner id + ├── it should validate each account against only its own signer data + └── it should reject the other account's signer data diff --git a/test/btt/P256Signer.tree b/test/btt/P256Signer.tree new file mode 100644 index 0000000..b8f3fb0 --- /dev/null +++ b/test/btt/P256Signer.tree @@ -0,0 +1,45 @@ +P256SignerTest +├── when calling isModuleType with MODULE_TYPE_SIGNER +│ └── it should return true +├── when calling isModuleType with MODULE_TYPE_STATELESS_VALIDATOR +│ └── it should return true +├── when calling isModuleType with MODULE_TYPE_STATELESS_VALIDATOR_WITH_SENDER +│ └── it should return true +├── when calling onInstall with a valid signer id and P256 public key +│ ├── it should store the public key coordinates for the signer id +│ └── it should mark the signer id as initialized +├── when calling onInstall twice with the same signer id +│ └── it should revert +├── when calling onInstall with two different signer ids +│ └── it should initialize both signer ids independently +├── when calling onInstall with invalid data length +│ └── it should revert with InvalidDataLength +├── when calling onInstall with an off-curve public key +│ └── it should revert with InvalidPublicKey +├── when calling onUninstall for an initialized signer id +│ ├── it should clear the public key coordinates +│ └── it should mark the signer id as uninitialized +├── when calling checkUserOpSignature with a valid P256 signature +│ └── it should return SIG_VALIDATION_SUCCESS_UINT +├── when calling checkUserOpSignature with an invalid P256 signature +│ └── it should return SIG_VALIDATION_FAILED_UINT +├── when calling checkUserOpSignature before installation +│ └── it should return SIG_VALIDATION_FAILED_UINT without reverting +├── when calling checkSignature with a valid P256 signature +│ └── it should return ERC1271_MAGICVALUE +├── when calling checkSignature with an invalid P256 signature +│ └── it should return ERC1271_INVALID +├── when calling checkSignature before installation +│ └── it should return ERC1271_INVALID without reverting +├── when calling validateSignatureWithData with a valid P256 signature and public key +│ └── it should return true +├── when calling validateSignatureWithData with an invalid P256 signature +│ └── it should return false +├── when calling validateSignatureWithData with a caller-supplied key before installation +│ └── it should validate against the supplied key and return true +├── when calling validateSignatureWithData with a malformed signature +│ └── it should return false +├── when calling validateSignatureWithDataWithSender with a valid P256 signature and public key +│ └── it should return true +└── when calling validateSignatureWithDataWithSender with an invalid P256 signature + └── it should return false diff --git a/test/btt/P256Validator.tree b/test/btt/P256Validator.tree new file mode 100644 index 0000000..083a0ef --- /dev/null +++ b/test/btt/P256Validator.tree @@ -0,0 +1,47 @@ +P256ValidatorTest +├── when calling isModuleType with MODULE_TYPE_VALIDATOR +│ └── it should return true +├── when calling isModuleType with MODULE_TYPE_STATELESS_VALIDATOR +│ └── it should return true +├── when calling isModuleType with MODULE_TYPE_STATELESS_VALIDATOR_WITH_SENDER +│ └── it should return true +├── when calling onInstall with a valid P256 public key +│ ├── it should store the public key coordinates +│ └── it should mark the validator as initialized +├── when calling onInstall for an initialized account +│ └── it should revert +├── when calling onInstall with invalid data length +│ └── it should revert with InvalidDataLength +├── when calling onInstall with an off-curve public key +│ └── it should revert with InvalidPublicKey +├── when calling onUninstall for an initialized account +│ ├── it should clear the public key coordinates +│ └── it should mark the validator as uninitialized +├── when calling validateUserOp with a valid P256 signature +│ └── it should return SIG_VALIDATION_SUCCESS_UINT +├── when calling validateUserOp with an invalid P256 signature +│ └── it should return SIG_VALIDATION_FAILED_UINT +├── when calling validateUserOp before installation +│ └── it should return SIG_VALIDATION_FAILED_UINT without reverting +├── when calling isValidSignatureWithSender with a valid P256 signature +│ └── it should return ERC1271_MAGICVALUE +├── when calling isValidSignatureWithSender with an invalid P256 signature +│ └── it should return ERC1271_INVALID +├── when calling isValidSignatureWithSender before installation +│ └── it should return ERC1271_INVALID without reverting +├── when calling isValidSignatureWithSender with a malformed signature +│ └── it should return ERC1271_INVALID without reverting +├── when calling validateSignatureWithData with a valid P256 signature and public key +│ └── it should return true +├── when calling validateSignatureWithData with an invalid P256 signature +│ └── it should return false +├── when calling validateSignatureWithData with a caller-supplied key before installation +│ └── it should validate against the supplied key and return true +├── when calling validateSignatureWithData with malformed public-key data +│ └── it should return false +├── when calling validateSignatureWithData with a high-s signature +│ └── it should return false +├── when calling validateSignatureWithDataWithSender with a valid P256 signature and public key +│ └── it should return true +└── when calling validateSignatureWithDataWithSender with an invalid P256 signature + └── it should return false diff --git a/test/btt/TimelockSignaturePolicy.t.sol b/test/btt/TimelockSignaturePolicy.t.sol index c5d0289..ba51812 100644 --- a/test/btt/TimelockSignaturePolicy.t.sol +++ b/test/btt/TimelockSignaturePolicy.t.sol @@ -46,7 +46,7 @@ contract TimelockSignaturePolicyTest is Test { // Try to validate a signature - should always revert vm.prank(WALLET); - vm.expectRevert("TimelockPolicy: signature validation not supported"); + vm.expectRevert(TimelockPolicy.SignatureValidationNotSupported.selector); timelockPolicy.checkSignaturePolicy(policyId, address(0), testHash, ""); } @@ -57,7 +57,7 @@ contract TimelockSignaturePolicyTest is Test { // Try to validate a signature - should always revert vm.prank(WALLET); - vm.expectRevert("TimelockPolicy: signature validation not supported"); + vm.expectRevert(TimelockPolicy.SignatureValidationNotSupported.selector); timelockPolicy.checkSignaturePolicy(policyId, address(0), testHash, ""); } @@ -70,7 +70,7 @@ contract TimelockSignaturePolicyTest is Test { bytes memory data = abi.encode(DELAY, EXPIRATION_PERIOD); - vm.expectRevert("TimelockPolicy: stateless signature validation not supported"); + vm.expectRevert(TimelockPolicy.StatelessValidationNotSupported.selector); timelockPolicy.validateSignatureWithData(testHash, "", data); } @@ -83,7 +83,7 @@ contract TimelockSignaturePolicyTest is Test { bytes memory data = abi.encode(DELAY, EXPIRATION_PERIOD); - vm.expectRevert("TimelockPolicy: stateless signature validation not supported"); + vm.expectRevert(TimelockPolicy.StatelessValidationNotSupported.selector); timelockPolicy.validateSignatureWithDataWithSender(WALLET, testHash, "", data); } } diff --git a/test/btt/WebAuthnStateless.tree b/test/btt/WebAuthnStateless.tree new file mode 100644 index 0000000..4b5b917 --- /dev/null +++ b/test/btt/WebAuthnStateless.tree @@ -0,0 +1,20 @@ +WebAuthnStatelessTest +├── when querying the WebAuthnValidator module types +│ ├── it should advertise MODULE_TYPE_STATELESS_VALIDATOR +│ └── it should advertise MODULE_TYPE_STATELESS_VALIDATOR_WITH_SENDER +├── when querying the WebAuthnSigner module types +│ ├── it should advertise MODULE_TYPE_STATELESS_VALIDATOR +│ └── it should advertise MODULE_TYPE_STATELESS_VALIDATOR_WITH_SENDER +├── when calling validateSignatureWithData on WebAuthnValidator before installation +│ └── it should validate against the caller-supplied public key +├── when calling validateSignatureWithData on WebAuthnSigner before installation +│ └── it should validate against the caller-supplied public key +├── when calling validateSignatureWithDataWithSender with a caller-supplied public key +│ ├── WebAuthnValidator should return true +│ └── WebAuthnSigner should return true +├── when the signed WebAuthn challenge differs from the requested hash +│ ├── WebAuthnValidator should return false +│ └── WebAuthnSigner should return false +└── when calling stateless validation with invalid configuration data + ├── WebAuthnValidator should reject malformed data + └── WebAuthnSigner should reject zero public-key data diff --git a/test/btt/WeightedECDSADoubleCount.t.sol b/test/btt/WeightedECDSADoubleCount.t.sol index f642918..d55c51e 100644 --- a/test/btt/WeightedECDSADoubleCount.t.sol +++ b/test/btt/WeightedECDSADoubleCount.t.sol @@ -212,7 +212,7 @@ contract WeightedECDSADoubleCountTest is Test { userOp.signature = abi.encodePacked(sig1, sig2, sig3); vm.prank(wallet); - vm.expectRevert("Signers not sorted"); + vm.expectRevert(WeightedECDSASigner.SignersNotSorted.selector); signer.checkUserOpSignature(SIGNER_ID, userOp, userOpHash); } diff --git a/test/btt/WeightedECDSAGasGriefing.t.sol b/test/btt/WeightedECDSAGasGriefing.t.sol index b888845..c75a602 100644 --- a/test/btt/WeightedECDSAGasGriefing.t.sol +++ b/test/btt/WeightedECDSAGasGriefing.t.sol @@ -125,11 +125,7 @@ contract WeightedECDSAGasGriefingTest is Test { }); } - function _signUserOp(PackedUserOperation memory userOp, uint256 numSigners) - internal - view - returns (bytes memory) - { + function _signUserOp(PackedUserOperation memory userOp, uint256 numSigners) internal view returns (bytes memory) { bytes32 proposalHash = _computeProposalHash(userOp); bytes32 userOpHash = entrypoint.getUserOpHash(userOp); @@ -497,10 +493,7 @@ contract WeightedECDSAGasGriefingTest is Test { assertEq(result, SIG_VALIDATION_SUCCESS_UINT); } - function test_RevertWhen_Non_lastSignersAreNotInSortedOrder() - external - whenValidatingERC4337UserOp - { + function test_RevertWhen_Non_lastSignersAreNotInSortedOrder() external whenValidatingERC4337UserOp { _installSigner(5); PackedUserOperation memory userOp = _createUserOp(); @@ -521,9 +514,9 @@ contract WeightedECDSAGasGriefingTest is Test { userOp.signature = signatures; - // it should revert with "Signers not sorted" + // it should revert with SignersNotSorted vm.prank(WALLET); - vm.expectRevert("Signers not sorted"); + vm.expectRevert(WeightedECDSASigner.SignersNotSorted.selector); signer.checkUserOpSignature(SIGNER_ID, userOp, userOpHash); } } diff --git a/test/btt/WeightedECDSAInstall.t.sol b/test/btt/WeightedECDSAInstall.t.sol index b9a69cd..e69f2cf 100644 --- a/test/btt/WeightedECDSAInstall.t.sol +++ b/test/btt/WeightedECDSAInstall.t.sol @@ -56,7 +56,7 @@ contract WeightedECDSAInstallTest is Test { // it should revert vm.prank(WALLET); - vm.expectRevert("Length mismatch"); + vm.expectRevert(WeightedECDSASigner.LengthMismatch.selector); signer.onInstall(abi.encodePacked(SIGNER_ID, installData)); } @@ -71,7 +71,7 @@ contract WeightedECDSAInstallTest is Test { // it should revert vm.prank(WALLET); - vm.expectRevert("Guardian cannot be self"); + vm.expectRevert(WeightedECDSASigner.GuardianCannotBeSelf.selector); signer.onInstall(abi.encodePacked(SIGNER_ID, installData)); } @@ -86,7 +86,7 @@ contract WeightedECDSAInstallTest is Test { // it should revert vm.prank(WALLET); - vm.expectRevert("Guardian cannot be 0"); + vm.expectRevert(WeightedECDSASigner.ZeroAddressGuardian.selector); signer.onInstall(abi.encodePacked(SIGNER_ID, installData)); } @@ -101,7 +101,7 @@ contract WeightedECDSAInstallTest is Test { // it should revert vm.prank(WALLET); - vm.expectRevert("Weight cannot be 0"); + vm.expectRevert(WeightedECDSASigner.ZeroWeight.selector); signer.onInstall(abi.encodePacked(SIGNER_ID, installData)); } @@ -118,7 +118,7 @@ contract WeightedECDSAInstallTest is Test { // it should revert vm.prank(WALLET); - vm.expectRevert("Guardian already enabled"); + vm.expectRevert(WeightedECDSASigner.GuardianAlreadyEnabled.selector); signer.onInstall(abi.encodePacked(SIGNER_ID, installData)); } diff --git a/test/halmos/CallerPolicyHalmos.t.sol b/test/halmos/CallerPolicyHalmos.t.sol new file mode 100644 index 0000000..5ec3a62 --- /dev/null +++ b/test/halmos/CallerPolicyHalmos.t.sol @@ -0,0 +1,230 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import {SymTest} from "halmos-cheatcodes/SymTest.sol"; +import {PackedUserOperation} from "account-abstraction/interfaces/PackedUserOperation.sol"; +import {CallerPolicy, Status} from "src/policies/CallerPolicy.sol"; +import {SIG_VALIDATION_SUCCESS_UINT, SIG_VALIDATION_FAILED_UINT} from "src/types/Constants.sol"; + +// Minimal cheatcode surface. Inheriting forge-std `Test` pulls in a base constructor that calls +// vm.deployCode(string) (StdConfig), which Halmos 0.3.3 does not support and fails setUp(). +interface Vm { + function assume(bool) external pure; + function prank(address) external; + function etch(address, bytes calldata) external; + function store(address, bytes32, bytes32) external; +} + +/// @author taek +/// @notice Halmos proof harness for CallerPolicy access semantics (TF-CallerPolicy). +/// @dev Storage-layout facts (CallerPolicy declares two mappings, no other state): +/// slot 0: mapping(bytes32 id => mapping(address account => Status)) status +/// slot 1: mapping(bytes32 id => mapping(address caller => mapping(address wallet => bool))) allowedCaller +/// We write SYMBOLIC values into these slots (via keccak-derived keys that mirror Solidity's +/// layout) so status can be any of NA/Live/Deprecated and allowedCaller any bool — otherwise the +/// etched (all-zero) storage would fix status==NA and the Live branches would be vacuous. +contract CallerPolicyHalmos is SymTest { + Vm internal constant vm = Vm(address(uint160(uint256(keccak256("hevm cheat code"))))); + CallerPolicy internal policy; + + uint256 internal constant STATUS_SLOT = 0; + uint256 internal constant ALLOWED_SLOT = 1; + + function setUp() external { + // Halmos 0.3.3 cannot execute the via_ir creation bytecode (routes to unsupported + // deployCode(string)); place runtime code directly. CallerPolicy has an empty constructor + // (all state set later via onInstall / here via store), so etch is state-equivalent. + policy = CallerPolicy(address(uint160(uint256(keccak256("CallerPolicy"))))); + vm.etch(address(policy), type(CallerPolicy).runtimeCode); + } + + // mapping(bytes32 => mapping(address => Status)) : slot = keccak(account, keccak(id, base)) + function _statusSlot(bytes32 id, address account) internal pure returns (bytes32) { + bytes32 inner = keccak256(abi.encode(id, STATUS_SLOT)); + return keccak256(abi.encode(account, inner)); + } + + // mapping(bytes32 => mapping(address => mapping(address => bool))) + function _allowedSlot(bytes32 id, address caller, address wallet) internal pure returns (bytes32) { + bytes32 l1 = keccak256(abi.encode(id, ALLOWED_SLOT)); + bytes32 l2 = keccak256(abi.encode(caller, l1)); + return keccak256(abi.encode(wallet, l2)); + } + + // ============================================================================================ + // (a) checkSignaturePolicy: return == 0 IFF status[id][wallet]==Live && allowedCaller[id][sender][wallet] + // Two-directional equivalence read against storage directly (SPEC predicate, not impl re-run). + // ============================================================================================ + + /// @notice (a) checkSignaturePolicy returns 0 exactly when (Live && allowed), else 1. + function check_CallerPolicy_signatureAccess( + bytes32 id, + address wallet, + address sender, + uint8 statusRaw, + bool allowed, + bytes32 hash + ) external { + vm.assume(statusRaw <= 2); // NA=0, Live=1, Deprecated=2 + + // Seed symbolic storage. wallet is the ERC-1271 requester context => it is msg.sender. + vm.store(address(policy), _statusSlot(id, wallet), bytes32(uint256(statusRaw))); + vm.store(address(policy), _allowedSlot(id, sender, wallet), bytes32(uint256(allowed ? 1 : 0))); + + // SPEC predicate, read straight from storage — independent of the impl's control flow. + bool live = statusRaw == uint8(Status.Live); + bool expectSuccess = live && allowed; + + vm.prank(wallet); + uint256 ret = policy.checkSignaturePolicy(id, sender, hash, hex""); + + if (expectSuccess) { + assert(ret == 0); + } else { + assert(ret == 1); + } + } + + /// @notice (a) reachability: SUCCESS (Live && allowed) leaf is live. + function check_CallerPolicy_signatureAccess_reachable(bytes32 id, address wallet, address sender, bytes32 hash) + external + { + vm.store(address(policy), _statusSlot(id, wallet), bytes32(uint256(uint8(Status.Live)))); + vm.store(address(policy), _allowedSlot(id, sender, wallet), bytes32(uint256(1))); + + vm.prank(wallet); + uint256 ret = policy.checkSignaturePolicy(id, sender, hash, hex""); + // counterexample here proves the (Live && allowed) => 0 path is reachable (non-vacuous). + assert(ret != 0); + } + + /// @notice (a) reachability of failure mode #1: not-Live => 1 is live (Deprecated, allowed=true). + function check_CallerPolicy_signatureAccess_notLive_reachable( + bytes32 id, + address wallet, + address sender, + bytes32 hash + ) external { + vm.store(address(policy), _statusSlot(id, wallet), bytes32(uint256(uint8(Status.Deprecated)))); + vm.store(address(policy), _allowedSlot(id, sender, wallet), bytes32(uint256(1))); + + vm.prank(wallet); + uint256 ret = policy.checkSignaturePolicy(id, sender, hash, hex""); + assert(ret != 1); // counterexample => not-Live rejection path is reachable + } + + /// @notice (a) reachability of failure mode #2: Live-but-not-allowed => 1 is live. + function check_CallerPolicy_signatureAccess_notAllowed_reachable( + bytes32 id, + address wallet, + address sender, + bytes32 hash + ) external { + vm.store(address(policy), _statusSlot(id, wallet), bytes32(uint256(uint8(Status.Live)))); + vm.store(address(policy), _allowedSlot(id, sender, wallet), bytes32(uint256(0))); + + vm.prank(wallet); + uint256 ret = policy.checkSignaturePolicy(id, sender, hash, hex""); + assert(ret != 1); // counterexample => Live-but-not-allowed rejection path is reachable + } + + // ============================================================================================ + // (b) checkUserOpPolicy: return == 0 IFF status[id][msg.sender]==Live, else 1. + // ============================================================================================ + + /// @notice (b) checkUserOpPolicy returns 0 exactly when status[id][msg.sender]==Live, else 1. + function check_CallerPolicy_userOpAccess(bytes32 id, address account, uint8 statusRaw) external { + vm.assume(statusRaw <= 2); + vm.store(address(policy), _statusSlot(id, account), bytes32(uint256(statusRaw))); + + bool expectSuccess = statusRaw == uint8(Status.Live); // SPEC predicate from storage + + // PackedUserOperation content is irrelevant (checkUserOpPolicy ignores it); pass a zeroed op. + PackedUserOperation memory op; + vm.prank(account); + uint256 ret = policy.checkUserOpPolicy(id, op); + + if (expectSuccess) { + assert(ret == SIG_VALIDATION_SUCCESS_UINT); + } else { + assert(ret == SIG_VALIDATION_FAILED_UINT); + } + } + + /// @notice (b) reachability: SUCCESS (Live) leaf is live. + function check_CallerPolicy_userOpAccess_reachable(bytes32 id, address account) external { + vm.store(address(policy), _statusSlot(id, account), bytes32(uint256(uint8(Status.Live)))); + PackedUserOperation memory op; + vm.prank(account); + uint256 ret = policy.checkUserOpPolicy(id, op); + assert(ret != SIG_VALIDATION_SUCCESS_UINT); // counterexample => Live-success path reachable + } + + /// @notice (b) reachability of failure mode: not-Live => 1 is live (NA). + function check_CallerPolicy_userOpAccess_notLive_reachable(bytes32 id, address account) external { + vm.store(address(policy), _statusSlot(id, account), bytes32(uint256(uint8(Status.NA)))); + PackedUserOperation memory op; + vm.prank(account); + uint256 ret = policy.checkUserOpPolicy(id, op); + assert(ret != SIG_VALIDATION_FAILED_UINT); // counterexample => not-Live rejection path reachable + } + + // ============================================================================================ + // (c) validateSignatureWithDataWithSender(sender,...): return == true IFF sender ∈ decoded address[]. + // Bounded list length <= 3. + // ============================================================================================ + + /// @notice (c) stateless membership: true IFF sender is a member of the decoded allowlist (len<=3). + /// @dev The impl does `abi.decode(data,(address[]))`; a SYMBOLIC array length makes the internal + /// CALLDATACOPY size symbolic (Halmos NotConcreteError). We therefore branch on a symbolic + /// `len` into CONCRETELY-sized arrays so the decode size is concrete on every path, while still + /// covering all lengths 0..3. Halmos explores every branch => full bounded coverage. + function check_CallerPolicy_statelessMembership(uint256 len, address sender, address a0, address a1, address a2) + external + view + { + vm.assume(len <= 3); + + // Build a CONCRETELY-sized array per branch so the impl's abi.decode CALLDATACOPY size stays + // concrete (symbolic-size allocation triggers Halmos NotConcreteError). All lengths 0..3 covered. + address[] memory list; + if (len == 0) { + list = new address[](0); + } else if (len == 1) { + list = new address[](1); + list[0] = a0; + } else if (len == 2) { + list = new address[](2); + list[0] = a0; + list[1] = a1; + } else { + list = new address[](3); + list[0] = a0; + list[1] = a1; + list[2] = a2; + } + bytes memory data = abi.encode(list); + + // SPEC membership predicate computed independently of the impl loop. + bool expectMember = (len > 0 && a0 == sender) || (len > 1 && a1 == sender) || (len > 2 && a2 == sender); + + bool ret = policy.validateSignatureWithDataWithSender(sender, bytes32(0), hex"", data); + + assert(ret == expectMember); + } + + /// @notice (c) reachability: membership==true is live (len==1, a0==sender). + function check_CallerPolicy_statelessMembership_true_reachable(address sender) external view { + address[] memory list = new address[](1); + list[0] = sender; + bool ret = policy.validateSignatureWithDataWithSender(sender, bytes32(0), hex"", abi.encode(list)); + assert(!ret); // counterexample => membership-true path reachable + } + + /// @notice (c) reachability: membership==false is live (empty list). + function check_CallerPolicy_statelessMembership_false_reachable(address sender) external view { + address[] memory list = new address[](0); + bool ret = policy.validateSignatureWithDataWithSender(sender, bytes32(0), hex"", abi.encode(list)); + assert(ret); // counterexample => membership-false path reachable + } +} diff --git a/test/halmos/DefaultSecurityHookBatchHalmos.t.sol b/test/halmos/DefaultSecurityHookBatchHalmos.t.sol new file mode 100644 index 0000000..88664b9 --- /dev/null +++ b/test/halmos/DefaultSecurityHookBatchHalmos.t.sol @@ -0,0 +1,158 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import {SymTest} from "halmos-cheatcodes/SymTest.sol"; +import {DefaultSecurityHook} from "src/hooks/DefaultSecurityHook.sol"; + +// Minimal cheatcode surface. Inheriting forge-std `Test` pulls in a base constructor that calls +// vm.deployCode(string) (StdConfig), which Halmos 0.3.3 does not support and fails setUp(). +interface Vm { + function assume(bool) external pure; + function prank(address) external; + function etch(address, bytes calldata) external; +} + +/// @author taek +/// @notice Halmos proof harness for DSH-BATCH-01 THROUGH the real calldata decoder +/// (closes the Certora TCB caveat: "a decoder bug would escape this property"). +/// The batch enters via the REAL preCheck entry (DefaultSecurityHook.sol:136-141) so the +/// compiled solady LibERC7579.decodeBatch/getExecution calldata-pointer assembly is +/// exercised, not a Call[] struct model. +/// +/// TAUTOLOGY GUARD (per dispatch): the executionData is HAND-ENCODED word-by-word from the +/// published ERC-7579 / ABI `Execution[]` layout via abi.encodePacked (see _encodeBatch2) — +/// it is NOT produced by LibERC7579's encode helpers, and not even by solc's abi.encode of a +/// matching struct — so the decoder is cross-checked against a genuinely independent encoder. +/// +/// Property (iff, single biconditional): for a 2-element batch to non-allowlisted, +/// non-self, non-module targets, preCheck reverts iff ANY element violates a deny rule +/// (value_i > 0 or selector_i in the blocked set); otherwise it returns hex"". +contract DefaultSecurityHookBatchHalmos is SymTest { + Vm internal constant vm = Vm(address(uint160(uint256(keccak256("hevm cheat code"))))); + DefaultSecurityHook internal hook; + + // Distinct concrete addresses so target != msg.sender is structural (observable precondition + // "both targets != account, non-allowlisted"). Both targets get REVERT stubs etched so their + // isModuleType staticcall returns success==false => _isModule==false (non-module precondition). + address internal constant ACCOUNT = address(uint160(uint256(keccak256("batch.account")))); + address internal constant TARGET0 = address(uint160(uint256(keccak256("batch.target0")))); + address internal constant TARGET1 = address(uint160(uint256(keccak256("batch.target1")))); + + function setUp() external { + hook = DefaultSecurityHook(address(uint160(uint256(keccak256("DefaultSecurityHook"))))); + vm.etch(address(hook), type(DefaultSecurityHook).runtimeCode); + // REVERT stubs (PUSH1 0 PUSH1 0 REVERT): staticcall fails => not a module. + vm.etch(TARGET0, hex"60006000fd"); + vm.etch(TARGET1, hex"60006000fd"); + } + + /// @dev Independent SPEC restatement of the deny set (literal 4-byte constants, NOT read from + /// the impl's internal constants): ERC-20 transfer/approve/transferFrom/increaseAllowance/ + /// decreaseAllowance, ERC-721 safeTransferFrom x2 + setApprovalForAll, ERC-1155 + /// safeTransferFrom + safeBatchTransferFrom. + function _specBlocked(bytes4 s) internal pure returns (bool) { + return s == 0xa9059cbb || s == 0x095ea7b3 || s == 0x23b872dd || s == 0x39509351 || s == 0xa457c2d7 + || s == 0x42842e0e || s == 0xb88d4fde || s == 0xa22cb465 || s == 0xf242432a || s == 0x2eb2c2d6; + } + + /// @dev HAND-ENCODED ERC-7579 batch executionData for exactly 2 executions, each with a 4-byte + /// calldata payload. Layout derived from the published ABI encoding of Execution[] + /// (Execution = (address target, uint256 value, bytes data)), word by word: + /// [0x000] 0x20 offset to the array + /// [0x020] 2 array length (pointers.offset starts at 0x40) + /// [0x040] 0x40 elem0 offset, rel. to pointers.offset + /// [0x060] 0xe0 elem1 offset, rel. to pointers.offset (0x40 + elem0 size 0xa0) + /// elem_i (5 words = 0xa0): target | value | 0x60 (data offset rel. to elem start) + /// | 4 (data length) | selector right-padded to 32 bytes + /// Total 0x1c0 bytes. Deliberately NOT abi.encode of a struct array. + function _encodeBatch2(uint256 v0, bytes4 s0, uint256 v1, bytes4 s1) internal pure returns (bytes memory) { + return abi.encodePacked( + abi.encodePacked(uint256(0x20), uint256(2), uint256(0x40), uint256(0xe0)), + abi.encodePacked(uint256(uint160(TARGET0)), v0, uint256(0x60), uint256(4), bytes32(s0)), + abi.encodePacked(uint256(uint160(TARGET1)), v1, uint256(0x60), uint256(4), bytes32(s1)) + ); + } + + /// @dev Full preCheck msgData: [0:4] dummy execute selector, then ABI-encoded + /// (bytes32 mode, bytes executionData) — the assembly at :126-131 dereferences the + /// executionData offset word at msgData[36:68], so the inner bytes must be ABI-framed. + /// mode high byte 0x01 = CALLTYPE_BATCH. + function _buildBatchMsgData(uint256 v0, bytes4 s0, uint256 v1, bytes4 s1) internal view returns (bytes memory) { + bytes32 mode = bytes32(uint256(0x01) << 248); // CALLTYPE_BATCH + bytes memory param = abi.encodePacked(bytes4(0), abi.encode(mode, _encodeBatch2(v0, s0, v1, s1))); + return abi.encodeWithSelector(hook.preCheck.selector, address(0), uint256(0), param); + } + + /// @notice DSH-BATCH-01 through the REAL decoder (OBSERVABLE iff): with an initialized account + /// and a hand-encoded 2-element batch to non-allowlisted / non-self / non-module + /// targets, preCheck reverts iff ANY element has value>0 or a blocked selector + /// (spec-side deny set, independently restated); otherwise it returns hex"". + /// Both directions catch decoder bugs: a decoder that misreads value/selector flips the + /// revert side; a decoder that spuriously reverts (DecodingError) on well-formed input + /// flips the clean side. + function check_BatchDenyThroughRealDecoder() external { + vm.prank(ACCOUNT); + hook.onInstall(""); // initialized, NO allowlist entries => allowlist branch never returns + + uint256 v0 = svm.createUint256("v0"); + uint256 v1 = svm.createUint256("v1"); + bytes4 s0 = svm.createBytes4("s0"); + bytes4 s1 = svm.createBytes4("s1"); + + vm.prank(ACCOUNT); + (bool ok, bytes memory ret) = address(hook).call(_buildBatchMsgData(v0, s0, v1, s1)); + + bool bad = v0 > 0 || _specBlocked(s0) || v1 > 0 || _specBlocked(s1); + if (bad) { + assert(!ok); // any violating element => whole preCheck reverts + } else { + // clean batch => success AND return data is the ABI encoding of empty bytes + assert(ok); + assert(keccak256(ret) == keccak256(abi.encode(bytes("")))); + } + } + + /// @notice Reachability witness #1 (element-1-violates leg): v0==0, s0 pinned benign, v1>0 + /// symbolic. Guards on the revert leaf then asserts false — Halmos MUST emit a + /// counterexample proving the second batch element is genuinely decoded and enforced + /// (the loop iterates past i=0). NO counterexample => leg dead => VACUOUS. + function check_BatchDenyThroughRealDecoder_reachable_elem1Reverts() external { + vm.prank(ACCOUNT); + hook.onInstall(""); + + uint256 v1 = svm.createUint256("v1"); + vm.assume(v1 > 0); + + vm.prank(ACCOUNT); + (bool ok, bytes memory ret) = + address(hook).call(_buildBatchMsgData(0, bytes4(0x11223344), v1, bytes4(0x55667788))); + + // Exact leaf: ETHTransferNotAllowed(TARGET1, v1) — element 1, real decoded args. + if ( + !ok + && keccak256(ret) + == keccak256( + abi.encodeWithSelector(DefaultSecurityHook.ETHTransferNotAllowed.selector, TARGET1, v1) + ) + ) { + assert(false); + } + } + + /// @notice Reachability witness #2 (clean-batch success leg): both values 0, benign concrete + /// selectors. Guards on the success-with-empty-return leaf then asserts false — Halmos + /// MUST emit a counterexample proving a well-formed hand-encoded batch survives the + /// real decoder end-to-end. NO counterexample => success leg dead => VACUOUS. + function check_BatchDenyThroughRealDecoder_reachable_clean() external { + vm.prank(ACCOUNT); + hook.onInstall(""); + + vm.prank(ACCOUNT); + (bool ok, bytes memory ret) = + address(hook).call(_buildBatchMsgData(0, bytes4(0x11223344), 0, bytes4(0x55667788))); + + if (ok && keccak256(ret) == keccak256(abi.encode(bytes("")))) { + assert(false); + } + } +} diff --git a/test/halmos/DefaultSecurityHookBlockedSelectorHalmos.t.sol b/test/halmos/DefaultSecurityHookBlockedSelectorHalmos.t.sol new file mode 100644 index 0000000..c9dc75c --- /dev/null +++ b/test/halmos/DefaultSecurityHookBlockedSelectorHalmos.t.sol @@ -0,0 +1,202 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import {SymTest} from "halmos-cheatcodes/SymTest.sol"; +import {DefaultSecurityHook} from "src/hooks/DefaultSecurityHook.sol"; + +// Minimal cheatcode surface. Inheriting forge-std `Test` pulls in a base constructor that calls +// vm.deployCode(string) (StdConfig), which Halmos 0.3.3 does not support and fails setUp(). +interface Vm { + function assume(bool) external pure; + function prank(address) external; + function etch(address, bytes calldata) external; +} + +/// @author taek +/// @notice Halmos proof harness for the DefaultSecurityHook blocked-selector gate (spec +/// §4.5-4.8, §5.1; DSH-ALLOW-01). Own file per property cluster (same convention as +/// DefaultSecurityHookDenyETHHalmos). Etch-deploy is state-equivalent: the hook has no +/// constructor logic (all state via onInstall). +/// +/// Property: for an initialized account and a SINGLE call with target NOT allowlisted, +/// target != account, _isModule(target)==false, value==0 and data.length>=4, preCheck +/// reverts TokenTransferNotAllowed(target, selector) IFF the 4-byte selector is one of +/// the 10 spec-§4.8 blocked selectors; otherwise it succeeds. CONVERSE: a target +/// allowlisted with EMPTY selectors (allSelectorsAllowed) never reverts, for any +/// selector and any value. +contract DefaultSecurityHookBlockedSelectorHalmos is SymTest { + Vm internal constant vm = Vm(address(uint160(uint256(keccak256("hevm cheat code"))))); + DefaultSecurityHook internal hook; + + // Distinct concrete addresses so target != msg.sender is structurally guaranteed. TARGET gets + // a REVERT stub etched so its isModuleType staticcall returns success==false => + // _isModule(TARGET)==false, pinning the not-a-module precondition while the selector stays + // fully symbolic. + address internal constant ACCOUNT = address(uint160(uint256(keccak256("blocked.account")))); + address internal constant TARGET = address(uint160(uint256(keccak256("blocked.target")))); + + function setUp() external { + hook = DefaultSecurityHook(address(uint160(uint256(keccak256("DefaultSecurityHook"))))); + vm.etch(address(hook), type(DefaultSecurityHook).runtimeCode); + } + + /// @dev Etch a REVERT stub (PUSH1 0 PUSH1 0 REVERT) at TARGET so + /// target.staticcall(isModuleType,...) returns success==false => _isModule(TARGET)==false. + function _makeTargetNotModule() internal { + vm.etch(TARGET, hex"60006000fd"); + } + + /// @dev SPEC ORACLE (§4.8): the 10 blocked selectors as LITERAL constants transcribed from the + /// spec, deliberately NOT derived from IERC20/IERC721/IERC1155 `.selector` and NOT calling + /// the implementation's _isBlockedSelector — an independent enumeration so the check is + /// not tautological against the implementation's own constant folding. + function _specBlocked(bytes4 selector) internal pure returns (bool) { + return selector == bytes4(0xa9059cbb) // transfer(address,uint256) + || selector == bytes4(0x095ea7b3) // approve(address,uint256) + || selector == bytes4(0x23b872dd) // transferFrom(address,address,uint256) + || selector == bytes4(0x39509351) // increaseAllowance(address,uint256) + || selector == bytes4(0xa457c2d7) // decreaseAllowance(address,uint256) + || selector == bytes4(0x42842e0e) // safeTransferFrom(address,address,uint256) + || selector == bytes4(0xb88d4fde) // safeTransferFrom(address,address,uint256,bytes) + || selector == bytes4(0xa22cb465) // setApprovalForAll(address,bool) + || selector == bytes4(0xf242432a) // 1155 safeTransferFrom(addr,addr,uint256,uint256,bytes) + || selector == bytes4(0x2eb2c2d6); // 1155 safeBatchTransferFrom(addr,addr,uint[],uint[],bytes) + } + + /// @dev Build preCheck msgData for a CALLTYPE_SINGLE call (mode word all-zero => callType 0x00), + /// packed executionData = target(20) || value(32) || selector(4) = 0x38 bytes > 0x33, so + /// LibERC7579.decodeSingle succeeds. preCheck reads the inner `msgData` param as: [0:4] + /// dummy selector, [4:36] mode, [36:68] ABI offset for the executionData bytes, then + /// length + data — hence dummy-selector || abi.encode(mode, executionData). + function _buildSingleMsgData(address target, uint256 value, bytes4 selector) + internal + view + returns (bytes memory msgData) + { + bytes32 mode = bytes32(0); // high byte == 0x00 => CALLTYPE_SINGLE + bytes memory executionData = abi.encodePacked(target, value, selector); + bytes memory param = abi.encodePacked(bytes4(0), abi.encode(mode, executionData)); + msgData = abi.encodeWithSelector(hook.preCheck.selector, address(0), uint256(0), param); + } + + /// @notice OBSERVABLE, EXACT (iff): with ACCOUNT initialized (real onInstall), TARGET not + /// allowlisted (entry.allowed==false), TARGET != ACCOUNT, _isModule(TARGET)==false and + /// value==0, a SINGLE call with a fully symbolic 4-byte selector makes preCheck revert + /// with exactly TokenTransferNotAllowed(TARGET, selector) IF the selector is in the + /// spec-§4.8 10-selector set, and SUCCEED (no revert of any kind) otherwise. + /// Source: DefaultSecurityHook.sol:202-205 (_checkCall blocked-selector leg), + /// :214-219 (_isBlockedSelector), :112-147 (preCheck). The success side of the iff + /// rules out both false denies and shadowing by a different revert. + function check_BlockedSelectorDenyExact() external { + _makeTargetNotModule(); + + // Initialized via REAL onInstall; NO setAllowlist for TARGET => entry.allowed==false, so + // the allowlist-first branch (:187-190) cannot return and control reaches the gates. + vm.prank(ACCOUNT); + hook.onInstall(""); + + bytes4 selector = svm.createBytes4("selector"); // fully symbolic: covers all 2^32 selectors + + bytes memory msgData = _buildSingleMsgData(TARGET, 0, selector); + + vm.prank(ACCOUNT); + (bool ok, bytes memory ret) = address(hook).call(msgData); + + if (_specBlocked(selector)) { + // Deny side: exact revert, selector AND abi-encoded (target, selector) args. + assert(!ok); + assert( + keccak256(ret) + == keccak256( + abi.encodeWithSelector(DefaultSecurityHook.TokenTransferNotAllowed.selector, TARGET, selector) + ) + ); + } else { + // Exactness converse within the deny region: any NON-blocked selector sails through + // (no TokenTransferNotAllowed, no other revert). + assert(ok); + } + } + + /// @notice Reachability/vacuity witness for check_BlockedSelectorDenyExact: guards on the + /// exact TokenTransferNotAllowed revert leaf under the SAME preconditions, then asserts + /// false so Halmos MUST emit a counterexample (a concrete blocked selector reaching the + /// :204 revert — also witnessing that the module check CAN return false, i.e. the leaf + /// is not shadowed by ModuleCallNotAllowed). NO counterexample => leaf dead / + /// preconditions unsatisfiable (VACUOUS — report as such, not proven). + function check_BlockedSelectorDenyExact_reachable() external { + _makeTargetNotModule(); + + vm.prank(ACCOUNT); + hook.onInstall(""); + + bytes4 selector = svm.createBytes4("selector"); + + bytes memory msgData = _buildSingleMsgData(TARGET, 0, selector); + + vm.prank(ACCOUNT); + (bool ok, bytes memory ret) = address(hook).call(msgData); + + if ( + !ok + && keccak256(ret) + == keccak256( + abi.encodeWithSelector(DefaultSecurityHook.TokenTransferNotAllowed.selector, TARGET, selector) + ) + ) { + assert(false); + } + } + + /// @notice CONVERSE rule (spec §5.1, certora :93 counterpart): once TARGET is allowlisted with + /// EMPTY selectors (allSelectorsAllowed==true), preCheck NEVER reverts — for ANY + /// symbolic 4-byte selector (including the 10 blocked ones) and ANY symbolic value + /// (including value>0). Source: _checkCall :187-188 returns before every gate. + /// OBSERVABLE: asserts non-revert of the external call, not a re-read of allowlist + /// storage (non-tautological). + function check_BlockedSelectorAllowlistedNeverReverts() external { + _makeTargetNotModule(); + + vm.prank(ACCOUNT); + hook.onInstall(""); + // Blanket allowlist: empty selector array => allSelectorsAllowed==true. + vm.prank(ACCOUNT); + hook.setAllowlist(TARGET, new bytes4[](0)); + + bytes4 selector = svm.createBytes4("selector"); // symbolic: includes all blocked selectors + uint256 value = svm.createUint256("value"); // symbolic: includes value>0 + + bytes memory msgData = _buildSingleMsgData(TARGET, value, selector); + + vm.prank(ACCOUNT); + (bool ok,) = address(hook).call(msgData); + + assert(ok); + } + + /// @notice Pass-witness / reachability companion for the converse rule: guards on the + /// allowlisted-success branch (ok==true) under the SAME preconditions, then asserts + /// false so Halmos MUST emit a counterexample proving the success path is live (the + /// blanket-allowlist return at :188 is actually reached, the assert(ok) above is not + /// vacuously ranging over an empty path set). NO counterexample => VACUOUS. + function check_BlockedSelectorAllowlistedNeverReverts_reachable() external { + _makeTargetNotModule(); + + vm.prank(ACCOUNT); + hook.onInstall(""); + vm.prank(ACCOUNT); + hook.setAllowlist(TARGET, new bytes4[](0)); + + bytes4 selector = svm.createBytes4("selector"); + uint256 value = svm.createUint256("value"); + + bytes memory msgData = _buildSingleMsgData(TARGET, value, selector); + + vm.prank(ACCOUNT); + (bool ok,) = address(hook).call(msgData); + + if (ok) { + assert(false); + } + } +} diff --git a/test/halmos/DefaultSecurityHookDenyETHHalmos.t.sol b/test/halmos/DefaultSecurityHookDenyETHHalmos.t.sol new file mode 100644 index 0000000..23a886e --- /dev/null +++ b/test/halmos/DefaultSecurityHookDenyETHHalmos.t.sol @@ -0,0 +1,237 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import {SymTest} from "halmos-cheatcodes/SymTest.sol"; +import {DefaultSecurityHook} from "src/hooks/DefaultSecurityHook.sol"; + +// Minimal cheatcode surface. Inheriting forge-std `Test` pulls in a base constructor that calls +// vm.deployCode(string) (StdConfig), which Halmos 0.3.3 does not support and fails setUp(). +interface Vm { + function assume(bool) external pure; + function prank(address) external; + function etch(address, bytes calldata) external; +} + +/// @author taek +/// @notice Halmos proof harness for the DefaultSecurityHook ETH-transfer gate (_checkCall :199). +/// Split into its own file/contract (rather than DefaultSecurityHookHalmos) to avoid a +/// concurrent-edit race; the etch-deploy pattern is identical and state-equivalent +/// (DefaultSecurityHook has no constructor logic, all state via onInstall). +/// +/// Property: for a SINGLE call with value>0 to a target that is NOT allowlisted, NOT the +/// caller (target != msg.sender), and NOT a module (_isModule(target)==false), preCheck +/// reverts ETHTransferNotAllowed(target, value). The ETH check sits AFTER the module check +/// (:196), so the reachability witness MUST show _isModule can return false, else the +/// revert would be shadowed by ModuleCallNotAllowed. +contract DefaultSecurityHookDenyETHHalmos is SymTest { + Vm internal constant vm = Vm(address(uint160(uint256(keccak256("hevm cheat code"))))); + DefaultSecurityHook internal hook; + + // Distinct concrete addresses for account (msg.sender) and target so target != msg.sender is + // structurally guaranteed. TARGET gets a revert-stub etched inline so its isModuleType + // staticcall returns success==false => _isModule(TARGET)==false. This is the + // uninterpreted-staticcall model for this reachable leaf: the external call outcome is fixed to + // "not a module" while `value` and the call selector stay fully symbolic. + address internal constant ACCOUNT = address(uint160(uint256(keccak256("eth.account")))); + address internal constant TARGET = address(uint160(uint256(keccak256("eth.target")))); + + // Additional revert-stub targets for the symbolic-target generalization (SG-P3-1). Three + // distinct addresses with etched REVERT stubs; a symbolic target address is then constrained + // only by the OBSERVABLE precondition "the isModuleType staticcall fails" (ghost pre-flight), + // so Halmos's address resolution — not a hand-pinned constant — picks the satisfying targets. + address internal constant STUB_A = address(uint160(uint256(keccak256("eth.target.stubA")))); + address internal constant STUB_B = address(uint160(uint256(keccak256("eth.target.stubB")))); + address internal constant STUB_C = address(uint160(uint256(keccak256("eth.target.stubC")))); + + bytes4 internal constant IS_MODULE_TYPE = bytes4(keccak256("isModuleType(uint256)")); + + function setUp() external { + hook = DefaultSecurityHook(address(uint160(uint256(keccak256("DefaultSecurityHook"))))); + vm.etch(address(hook), type(DefaultSecurityHook).runtimeCode); + } + + /// @dev Etch a REVERT stub (PUSH1 0 PUSH1 0 REVERT) at TARGET so + /// target.staticcall(isModuleType,...) returns success==false => _isModule(TARGET)==false. + function _makeTargetNotModule() internal { + vm.etch(TARGET, hex"60006000fd"); + } + + /// @dev Build preCheck msgData for a CALLTYPE_SINGLE call (mode high byte 0x00, tail symbolic), + /// packed executionData = target(20) || value(32) || selector(4). Length 0x38 > 0x33 so + /// LibERC7579.decodeSingle succeeds. + function _buildSingleMsgData(address target, uint256 value) internal returns (bytes memory msgData) { + bytes32 mode = bytes32(0); // high byte == 0x00 => CALLTYPE_SINGLE + bytes4 selector = svm.createBytes4("selector"); + bytes memory executionData = abi.encodePacked(target, value, selector); + // preCheck reads the inner `msgData` param as: [0:4] dummy selector, [4:36] mode, + // [36:68] ABI offset for the executionData bytes, then length + data. So the param must be + // dummy-selector || abi.encode(mode, executionData) (proper ABI framing for the inner bytes). + bytes memory param = abi.encodePacked(bytes4(0), abi.encode(mode, executionData)); + msgData = abi.encodeWithSelector(hook.preCheck.selector, address(0), uint256(0), param); + } + + /// @notice OBSERVABLE: for a SINGLE call with value>0 to a target that is NOT allowlisted, NOT + /// the caller, and NOT a module, preCheck reverts with exactly + /// ETHTransferNotAllowed(target, value) — full ABI-encoded args matching the decoded + /// (target, value). Source: DefaultSecurityHook.sol:199. Asserts the specific selector + /// AND the encoded args over the full symbolic value>0 region (not a fixed constant), + /// so a different revert (ModuleCallNotAllowed, DecodingError) is a false pass. + function check_DenyETH() external { + _makeTargetNotModule(); + + // Installed but NO allowlist entry for TARGET => entry.allowed==false, so the allowlist-first + // branch (:187-190) cannot return regardless of the (symbolic) selector. + vm.prank(ACCOUNT); + hook.onInstall(""); + + uint256 value = svm.createUint256("value"); + vm.assume(value > 0); // ETH-transfer region, symbolic (covers all value>0) + + bytes memory msgData = _buildSingleMsgData(TARGET, value); + + vm.prank(ACCOUNT); + (bool ok, bytes memory ret) = address(hook).call(msgData); + + assert(!ok); + assert( + keccak256(ret) + == keccak256(abi.encodeWithSelector(DefaultSecurityHook.ETHTransferNotAllowed.selector, TARGET, value)) + ); + } + + /// @notice Reachability/vacuity witness for check_DenyETH: proves the value>0 / + /// not-allowlisted / not-self / not-module leg is LIVE. It depends on + /// _isModule(TARGET)==false: because the ETH check (:199) sits AFTER the module check + /// (:196), if the staticcall could not return success==false this revert would be + /// shadowed by ModuleCallNotAllowed and the leaf would be dead. Guards on the exact + /// ETHTransferNotAllowed leaf then asserts false, so Halmos MUST emit a counterexample; + /// NO counterexample => leaf dead / preconditions vacuous. + function check_DenyETH_reachable() external { + _makeTargetNotModule(); + + vm.prank(ACCOUNT); + hook.onInstall(""); + + uint256 value = svm.createUint256("value"); + vm.assume(value > 0); + + bytes memory msgData = _buildSingleMsgData(TARGET, value); + + vm.prank(ACCOUNT); + (bool ok, bytes memory ret) = address(hook).call(msgData); + + if ( + !ok + && keccak256(ret) + == keccak256( + abi.encodeWithSelector(DefaultSecurityHook.ETHTransferNotAllowed.selector, TARGET, value) + ) + ) { + assert(false); + } + } + + /// @dev Shared body for the symbolic-target property and its reachability companion: etch + /// REVERT stubs at three distinct addresses, install for ACCOUNT with NO allowlist, create + /// a SYMBOLIC target, and encode the preconditions observably: + /// - target != ACCOUNT (not-self) + /// - isAllowlisted(ACCOUNT, target) == false (observable view, holds via empty allowlist + /// storage for ALL targets — asserted through the contract's own view, not assumed + /// away by pinning a constant) + /// - _isModule(target) == false, expressed as a ghost pre-flight of the SAME staticcall + /// the hook performs (:208-212) with vm.assume(!success). Within any single path, + /// Halmos resolves the symbolic callee consistently, so the hook's own staticcall in + /// _checkCall agrees with the pre-flight. Targets resolving to codeless addresses or + /// to live isModuleType responders (e.g. the hook itself) have success==true and are + /// excluded — correctly, because for them the real contract reverts + /// ModuleCallNotAllowed BEFORE the ETH check and the stated precondition is false. + /// COVERAGE DISCLOSURE: Halmos 0.3.3 resolves symbolic call targets against deployed code; + /// the satisfying set here is the three etched stubs (plus any resolution Halmos adds). + /// The target ADDRESS is symbolic, but "has code whose isModuleType call reverts" is + /// modeled by these stubs — targets whose staticcall fails for other reasons (e.g. >30k + /// gas burn) share the same success==false observable and the same _checkCall branch. + function _denyETHSymbolicTarget() internal returns (address target, uint256 value, bool ok, bytes memory ret) { + vm.etch(STUB_A, hex"60006000fd"); + vm.etch(STUB_B, hex"60006000fd"); + vm.etch(STUB_C, hex"60006000fd"); + + vm.prank(ACCOUNT); + hook.onInstall(""); + + target = svm.createAddress("target"); + vm.assume(target != ACCOUNT); // not-self (observable precondition) + vm.assume(!hook.isAllowlisted(ACCOUNT, target)); // not-allowlisted (observable view) + + // Ghost pre-flight: same call shape as _isModule (:210). assume(!s) == precondition + // _isModule(target)==false, stated observably rather than by pinning the address. + (bool s,) = target.staticcall{gas: 30_000}(abi.encodeWithSelector(IS_MODULE_TYPE, uint256(0))); + vm.assume(!s); + + value = svm.createUint256("value"); + vm.assume(value > 0); + + bytes memory msgData = _buildSingleMsgData(target, value); + + vm.prank(ACCOUNT); + (ok, ret) = address(hook).call(msgData); + } + + /// @notice OBSERVABLE (SG-P3-1 generalization of check_DenyETH): for a SINGLE call with + /// value>0 to a SYMBOLIC target that is not allowlisted, not the caller, and not a + /// module (isModuleType staticcall fails), preCheck reverts with exactly + /// ETHTransferNotAllowed(target, value). Source: DefaultSecurityHook.sol:199. + /// Asserts revert selector + args only — no branch-order reimplementation. + function check_DenyETH_symbolicTarget() external { + (address target, uint256 value, bool ok, bytes memory ret) = _denyETHSymbolicTarget(); + + assert(!ok); + assert( + keccak256(ret) + == keccak256(abi.encodeWithSelector(DefaultSecurityHook.ETHTransferNotAllowed.selector, target, value)) + ); + } + + /// @notice Reachability/vacuity witness for check_DenyETH_symbolicTarget: SAME precondition + /// set (including the ghost staticcall assume), guards on the exact + /// ETHTransferNotAllowed leaf and asserts false. Halmos MUST emit a counterexample; + /// none => the ghost-constrained space is empty (vacuous), do NOT report proven. + function check_DenyETH_symbolicTarget_reachable() external { + (address target, uint256 value, bool ok, bytes memory ret) = _denyETHSymbolicTarget(); + + if ( + !ok + && keccak256(ret) + == keccak256( + abi.encodeWithSelector(DefaultSecurityHook.ETHTransferNotAllowed.selector, target, value) + ) + ) { + assert(false); + } + } + + /// @notice Guard-discrimination witness: the ETH gate is NOT trivially always-revert. With the + /// SAME target allowlisted for all selectors, preCheck does NOT revert even when value>0 + /// (allowlist-first branch :188 returns before the ETH check). Asserts false on the + /// non-revert leaf so a counterexample witnesses that the gate discriminates on allowlist + /// state. + function check_DenyETH_converseLive() external { + _makeTargetNotModule(); + + vm.prank(ACCOUNT); + hook.onInstall(""); + // Allow-all selectors for TARGET => allSelectorsAllowed, so :188 returns. + vm.prank(ACCOUNT); + hook.setAllowlist(TARGET, new bytes4[](0)); + + uint256 value = svm.createUint256("value"); + vm.assume(value > 0); + + bytes memory msgData = _buildSingleMsgData(TARGET, value); + + vm.prank(ACCOUNT); + (bool ok,) = address(hook).call(msgData); + + // ok==true (no revert) => gate discriminates. Assert false on that leaf for a CEX witness. + assert(!ok); + } +} diff --git a/test/halmos/DefaultSecurityHookDenyModuleHalmos.t.sol b/test/halmos/DefaultSecurityHookDenyModuleHalmos.t.sol new file mode 100644 index 0000000..3bee23a --- /dev/null +++ b/test/halmos/DefaultSecurityHookDenyModuleHalmos.t.sol @@ -0,0 +1,128 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import {SymTest} from "halmos-cheatcodes/SymTest.sol"; +import {DefaultSecurityHook} from "src/hooks/DefaultSecurityHook.sol"; + +// Minimal cheatcode surface. Inheriting forge-std `Test` pulls in a base constructor that calls +// vm.deployCode(string) (StdConfig), which Halmos 0.3.3 does not support and fails setUp(). +interface Vm { + function assume(bool) external pure; + function prank(address) external; + function etch(address, bytes calldata) external; +} + +/// @author taek +/// @notice Halmos proof harness for the DefaultSecurityHook module-call deny gate (_checkCall :196, +/// spec §4.3). Own file/contract per the per-gate convention (see DenyETH harness); the +/// etch-deploy pattern is identical and state-equivalent (DefaultSecurityHook has no +/// constructor logic, all state via onInstall). +/// +/// Property: for a SINGLE call to a target that is NOT allowlisted and NOT the caller, +/// whose isModuleType(0) staticcall SUCCEEDS within the 30k stipend (_isModule==true), +/// preCheck reverts ModuleCallNotAllowed(target) for ALL symbolic (value, selector) — +/// including value>0 and blocked token selectors, pinning the §5.2 check order (module +/// check :196 precedes ETH :199 and selector :202 checks). +/// +/// SCOPE: proves the CONDITIONAL deny branch only (isModuleType-succeeds => revert). The +/// heuristic's soundness against adversarial bytecode that REVERTS isModuleType (bypass) is +/// SG-B, not FV-decidable, and NOT claimed here. +contract DefaultSecurityHookDenyModuleHalmos is SymTest { + Vm internal constant vm = Vm(address(uint160(uint256(keccak256("hevm cheat code"))))); + DefaultSecurityHook internal hook; + + // Distinct concrete addresses for account (msg.sender) and target so target != msg.sender is + // structurally guaranteed. TARGET gets a SUCCEED-stub etched inline (returns 32 zero bytes for + // any calldata) so its isModuleType staticcall returns success==true => _isModule(TARGET)==true. + // Source :208-212 only checks staticcall success, not return data, so a trivial returner is a + // faithful "module-like" target; value and selector stay fully symbolic. + address internal constant ACCOUNT = address(uint160(uint256(keccak256("module.account")))); + address internal constant TARGET = address(uint160(uint256(keccak256("module.target")))); + + function setUp() external { + hook = DefaultSecurityHook(address(uint160(uint256(keccak256("DefaultSecurityHook"))))); + vm.etch(address(hook), type(DefaultSecurityHook).runtimeCode); + } + + /// @dev Etch a SUCCEED stub (PUSH1 0x20 PUSH1 0x00 RETURN — returns 32 zero bytes) at TARGET so + /// target.staticcall(isModuleType, 0) returns success==true => _isModule(TARGET)==true. + /// Well under the 30k stipend (:210). + function _makeTargetModule() internal { + vm.etch(TARGET, hex"60206000f3"); + } + + /// @dev Build preCheck msgData for a CALLTYPE_SINGLE call (mode high byte 0x00), + /// packed executionData = target(20) || value(32) || selector(4). Length 0x38 > 0x33 so + /// LibERC7579.decodeSingle succeeds. + function _buildSingleMsgData(address target, uint256 value, bytes4 selector) + internal + view + returns (bytes memory msgData) + { + bytes32 mode = bytes32(0); // high byte == 0x00 => CALLTYPE_SINGLE + bytes memory executionData = abi.encodePacked(target, value, selector); + // preCheck reads the inner `msgData` param as: [0:4] dummy selector, [4:36] mode, + // [36:68] ABI offset for the executionData bytes, then length + data. + bytes memory param = abi.encodePacked(bytes4(0), abi.encode(mode, executionData)); + msgData = abi.encodeWithSelector(hook.preCheck.selector, address(0), uint256(0), param); + } + + /// @notice OBSERVABLE: for a SINGLE call to a non-allowlisted, non-self target whose + /// isModuleType(0) staticcall succeeds, preCheck reverts with exactly + /// ModuleCallNotAllowed(target) for ALL symbolic (value, selector). Source :196. + /// Exact revert-data equality over the full symbolic region (value includes 0 and >0; + /// selector includes the blocked token set) simultaneously pins the check order: any + /// input where ETHTransferNotAllowed or TokenTransferNotAllowed fired instead would be + /// a counterexample. No branch logic is reimplemented here — only the observed revert + /// data is asserted. + function check_DenyModuleCall() external { + _makeTargetModule(); + + // Installed but NO allowlist entry for TARGET => entry.allowed==false, so the + // allowlist-first branch (:187-190) cannot return regardless of the symbolic selector. + vm.prank(ACCOUNT); + hook.onInstall(""); + + uint256 value = svm.createUint256("value"); + bytes4 selector = svm.createBytes4("selector"); + + bytes memory msgData = _buildSingleMsgData(TARGET, value, selector); + + vm.prank(ACCOUNT); + (bool ok, bytes memory ret) = address(hook).call(msgData); + + assert(!ok); + assert( + keccak256(ret) + == keccak256(abi.encodeWithSelector(DefaultSecurityHook.ModuleCallNotAllowed.selector, TARGET)) + ); + } + + /// @notice Reachability/vacuity witness for check_DenyModuleCall: guards on the exact + /// ModuleCallNotAllowed leaf under the SAME preconditions (installed account + + /// succeeding-stub target, no assumes) and asserts false, so Halmos MUST emit a + /// counterexample proving the leaf is live and that an initialized account and a + /// succeeding-stub target coexist. NO counterexample => leaf dead / setup vacuous. + function check_DenyModuleCall_reachable() external { + _makeTargetModule(); + + vm.prank(ACCOUNT); + hook.onInstall(""); + + uint256 value = svm.createUint256("value"); + bytes4 selector = svm.createBytes4("selector"); + + bytes memory msgData = _buildSingleMsgData(TARGET, value, selector); + + vm.prank(ACCOUNT); + (bool ok, bytes memory ret) = address(hook).call(msgData); + + if ( + !ok + && keccak256(ret) + == keccak256(abi.encodeWithSelector(DefaultSecurityHook.ModuleCallNotAllowed.selector, TARGET)) + ) { + assert(false); + } + } +} diff --git a/test/halmos/DefaultSecurityHookDoubleInstallHalmos.t.sol b/test/halmos/DefaultSecurityHookDoubleInstallHalmos.t.sol new file mode 100644 index 0000000..aaf29cd --- /dev/null +++ b/test/halmos/DefaultSecurityHookDoubleInstallHalmos.t.sol @@ -0,0 +1,77 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import {SymTest} from "halmos-cheatcodes/SymTest.sol"; +import {DefaultSecurityHook} from "src/hooks/DefaultSecurityHook.sol"; +import {IModule} from "src/interfaces/IERC7579Modules.sol"; + +// Minimal cheatcode surface. Inheriting forge-std `Test` pulls in a base constructor that calls +// vm.deployCode(string) (StdConfig), which Halmos 0.3.3 does not support and fails setUp(). +interface Vm { + function assume(bool) external pure; + function prank(address) external; + function etch(address, bytes calldata) external; +} + +/// @author taek +/// @notice Halmos proof harness for INV-07 leg (a): the re-initialization guard on onInstall +/// (DefaultSecurityHook.sol:79). A second onInstall from an already-initialized account +/// MUST revert with exactly AlreadyInitialized(account) — it must not succeed and must +/// not re-enter the config-decode loop. Empty first-install data isolates the guard from +/// config parsing (data.length==0 branch, :82). Own file/contract (etch-deploy pattern +/// identical to the sibling DefaultSecurityHook Halmos harnesses; no constructor logic). +contract DefaultSecurityHookDoubleInstallHalmos is SymTest { + Vm internal constant vm = Vm(address(uint160(uint256(keccak256("hevm cheat code"))))); + DefaultSecurityHook internal hook; + + function setUp() external { + hook = DefaultSecurityHook(address(uint160(uint256(keccak256("DefaultSecurityHook"))))); + vm.etch(address(hook), type(DefaultSecurityHook).runtimeCode); + } + + /// @notice OBSERVABLE (INV-07 leg a): a fresh symbolic account runs a real onInstall("") that + /// succeeds and flips isInitialized(account)==true; a SECOND onInstall() + /// from the same account reverts with exactly AlreadyInitialized(account). Asserts the + /// external revert-vs-success observable and the error selector literal only — it does + /// not read the `initialized[msg.sender]` slot nor recompute the guard condition + /// (non-tautological). Source: DefaultSecurityHook.sol:79. + function check_DoubleInstallReverts() external { + address account = svm.createAddress("account"); + bytes memory secondData = svm.createBytes(256, "secondData"); + + // Genuine spec precondition: a fresh account defaults to initialized==false. + vm.assume(!hook.isInitialized(account)); + + // First install: empty data => decode loop skipped, guard flips the flag. + vm.prank(account); + hook.onInstall(""); + + // Second install with ANY data must be rejected by the guard. + vm.prank(account); + (bool ok, bytes memory ret) = address(hook).call(abi.encodeCall(hook.onInstall, (secondData))); + + assert(!ok); + assert(keccak256(ret) == keccak256(abi.encodeWithSelector(IModule.AlreadyInitialized.selector, account))); + } + + /// @notice Reachability/vacuity witness (SAME precondition set): proves (1) the uninitialized + /// precondition is satisfiable — a fresh account exists — and (2) the FIRST onInstall + /// SUCCESS branch is genuinely taken, flipping isInitialized(account)==true on the + /// live (non-reverting) path. Guards on that live branch then asserts false so Halmos + /// MUST emit a counterexample; NO counterexample => the first install reverted or the + /// precondition is unsatisfiable (VACUOUS — report as such, not proven). + function check_DoubleInstallReverts_reachable() external { + address account = svm.createAddress("account"); + + // (1) satisfiability: a fresh, uninitialized account exists. + vm.assume(!hook.isInitialized(account)); + + // (2) path-liveness: the first-install SUCCESS branch is genuinely taken. + vm.prank(account); + hook.onInstall(""); + + if (hook.isInitialized(account)) { + assert(false); + } + } +} diff --git a/test/halmos/DefaultSecurityHookHalmos.t.sol b/test/halmos/DefaultSecurityHookHalmos.t.sol new file mode 100644 index 0000000..c3c7ec5 --- /dev/null +++ b/test/halmos/DefaultSecurityHookHalmos.t.sol @@ -0,0 +1,348 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import {SymTest} from "halmos-cheatcodes/SymTest.sol"; +import {DefaultSecurityHook} from "src/hooks/DefaultSecurityHook.sol"; + +// Minimal cheatcode surface. Inheriting forge-std `Test` pulls in a base constructor that calls +// vm.deployCode(string) (StdConfig), which Halmos 0.3.3 does not support and fails setUp(). +interface Vm { + function assume(bool) external pure; + function prank(address) external; + function etch(address, bytes calldata) external; +} + +/// @author taek +/// @notice Halmos proof harness for DefaultSecurityHook access control (req-14) and the +/// delegatecall guard. Deploys via etch because Halmos 0.3.3 cannot execute the +/// via_ir creation bytecode (routes to an unsupported deployCode(string) cheat); +/// DefaultSecurityHook has no constructor logic (all state via onInstall), so etch +/// is state-equivalent. +contract DefaultSecurityHookHalmos is SymTest { + Vm internal constant vm = Vm(address(uint160(uint256(keccak256("hevm cheat code"))))); + DefaultSecurityHook internal hook; + + function setUp() external { + hook = DefaultSecurityHook(address(uint160(uint256(keccak256("DefaultSecurityHook"))))); + vm.etch(address(hook), type(DefaultSecurityHook).runtimeCode); + } + + // ================================================================================== + // Delegatecall guard: preCheck always reverts DelegateCallNotAllowed for callType 0xff. + // ================================================================================== + + /// @notice preCheck ALWAYS reverts DelegateCallNotAllowed when the mode's callType byte + /// (bytes1(mode) == 0xff, CALLTYPE_DELEGATECALL), regardless of executionData, + /// allowlist state, or account — the delegatecall branch runs before the allowlist + /// branch, so allowlisting cannot bypass it. + function check_DelegateCallAlwaysReverts() external { + bytes memory executionData = svm.createBytes(64, "executionData"); + // mode is a 32-byte word; its high byte (bytes1(mode)) is the callType. Force it to 0xff + // (CALLTYPE_DELEGATECALL); the remaining mode bits are left symbolic. + uint256 modeTail = svm.createUint(248, "modeTail"); // low 31 bytes, symbolic + bytes32 mode = bytes32((uint256(0xff) << 248) | modeTail); + + // "Even fully allowlisted": install the account and allow-all a symbolic target. + address account = svm.createAddress("account"); + address target = svm.createAddress("target"); + vm.prank(account); + hook.onInstall(""); + vm.prank(account); + hook.setAllowlist(target, new bytes4[](0)); // empty => allSelectorsAllowed + + // preCheck's `msgData` param layout is [0:4] execute selector, [4:36] mode, [36:] data. + // getCallType reads bytes1(msgData[4:36]) == param byte[4]. The param MUST therefore start + // with a 4-byte (dummy) selector so `mode` lands at [4:36] and its high byte (0xff) is byte[4]. + bytes memory param = abi.encodePacked(bytes4(0), mode, executionData); + bytes memory msgData = abi.encodeWithSelector(hook.preCheck.selector, address(0), uint256(0), param); + + vm.prank(account); + (bool ok, bytes memory ret) = address(hook).call(msgData); + assert(!ok); + assert(bytes4(ret) == DefaultSecurityHook.DelegateCallNotAllowed.selector); + } + + /// @notice Reachability/vacuity witness for check_DelegateCallAlwaysReverts: proves the + /// precondition set (well-formed param with callType byte==0xff, installed + allowlisted + /// account) is satisfiable AND the DelegateCallNotAllowed revert path is actually + /// reached (not blocked by an earlier calldata-decode revert). Guards on the intended + /// revert leaf then asserts false, so Halmos MUST emit a counterexample; NO counterexample + /// => preconditions unsatisfiable / path dead (VACUOUS). + function check_DelegateCallAlwaysReverts_reachable() external { + bytes memory executionData = svm.createBytes(64, "executionData"); + uint256 modeTail = svm.createUint(248, "modeTail"); + bytes32 mode = bytes32((uint256(0xff) << 248) | modeTail); + + address account = svm.createAddress("account"); + address target = svm.createAddress("target"); + vm.prank(account); + hook.onInstall(""); + vm.prank(account); + hook.setAllowlist(target, new bytes4[](0)); + + bytes memory param = abi.encodePacked(bytes4(0), mode, executionData); + bytes memory msgData = abi.encodeWithSelector(hook.preCheck.selector, address(0), uint256(0), param); + + vm.prank(account); + (bool ok, bytes memory ret) = address(hook).call(msgData); + + // Only proceed on the intended live revert leaf; assert false to force a counterexample. + if (!ok && bytes4(ret) == DefaultSecurityHook.DelegateCallNotAllowed.selector) { + assert(false); + } + } + + // ================================================================================== + // req-14: allowlist-write access control (uninitialized caller cannot write). + // ================================================================================== + + /// @notice req-14 (OBSERVABLE): setAllowlist reverts Unauthorized when msg.sender is + /// UNINITIALIZED (initialized[caller]==false). Source guard: + /// DefaultSecurityHook.sol:154 `if (!initialized[msg.sender]) revert Unauthorized();`. + /// Asserts the revert selector, not a recompute of the init flag (non-tautological). + function check_SetAllowlistRevertsWhenUninitialized() external { + address caller = svm.createAddress("caller"); + address target = svm.createAddress("target"); + + // Genuine spec precondition: a fresh account defaults to initialized==false. + vm.assume(!hook.isInitialized(caller)); + + bytes4[] memory sels = new bytes4[](1); + sels[0] = svm.createBytes4("selector"); + + vm.prank(caller); + (bool ok, bytes memory ret) = address(hook).call(abi.encodeCall(hook.setAllowlist, (target, sels))); + + // OBSERVABLE postcondition: the call reverts with exactly Unauthorized(). + assert(!ok); + assert(bytes4(ret) == DefaultSecurityHook.Unauthorized.selector); + } + + /// @notice Reachability witness for req-14: proves an INITIALIZED caller CAN successfully + /// setAllowlist (the revert is a genuine guard, not universal) AND the uninitialized + /// precondition is satisfiable. Asserts false on the success leaf so Halmos MUST emit + /// a counterexample; no CEX => path dead / precondition vacuous. + function check_SetAllowlistRevertsWhenUninitialized_reachable() external { + address caller = svm.createAddress("caller"); + address target = svm.createAddress("target"); + + // Same uninitialized precondition must be satisfiable... + vm.assume(!hook.isInitialized(caller)); + + // ...and an initialized caller CAN write. onInstall flips initialized[caller]=true. + vm.prank(caller); + hook.onInstall(""); + + bytes4[] memory sels = new bytes4[](1); + sels[0] = svm.createBytes4("selector"); + + vm.prank(caller); + (bool ok,) = address(hook).call(abi.encodeCall(hook.setAllowlist, (target, sels))); + + // ok==true means the write succeeded => guard is a genuine, live gate. + // Assert false on the success leaf so a counterexample witnesses reachability. + assert(!ok); + } + + // ================================================================================== + // Lifecycle: onInstall -> onUninstall roundtrip returns isInitialized to false. + // ================================================================================== + + /// @notice Init lifecycle (OBSERVABLE): starting from a symbolic (fresh) + /// account, an onInstall followed by onUninstall returns isInitialized(account) + /// to false. Source: onInstall :80 sets initialized=true, onUninstall :102 sets + /// it back to false. onInstall data kept empty (data.length==0 branch, :82) so + /// the AllowlistConfig decode loop is skipped — the flag roundtrip is independent + /// of config parsing. Asserts the observable isInitialized() view, not the raw slot. + function check_InstallUninstallRoundtrip() external { + address account = svm.createAddress("account"); + + // Genuine spec precondition: a fresh account defaults to initialized==false. + vm.assume(!hook.isInitialized(account)); + + vm.prank(account); + hook.onInstall(""); + + vm.prank(account); + hook.onUninstall(""); + + // OBSERVABLE postcondition: the roundtrip leaves the account un-initialized. + assert(!hook.isInitialized(account)); + } + + /// @notice Reachability/vacuity witness for check_InstallUninstallRoundtrip: proves the + /// fresh-account precondition is satisfiable AND that both the onInstall success + /// path (initialized false -> true) and the onUninstall success path are actually + /// taken (neither reverts). Asserts isInitialized(account)==true immediately after + /// onInstall (before onUninstall) on the live path, then asserts false so Halmos + /// MUST emit a counterexample. No CEX => a path reverted / precondition unsatisfiable + /// (VACUOUS). + function check_InstallUninstallRoundtrip_reachable() external { + address account = svm.createAddress("account"); + + vm.assume(!hook.isInitialized(account)); + + vm.prank(account); + hook.onInstall(""); + + // Success path of onInstall was taken: flag flipped to true. + if (hook.isInitialized(account)) { + vm.prank(account); + hook.onUninstall(""); + // Both success paths live; force a counterexample to witness reachability. + assert(false); + } + } + + // ================================================================================== + // Self-call gate: preCheck reverts SelfCallNotAllowed for a SINGLE call whose decoded + // target == the account (msg.sender), when that (self,selector) pair is NOT allowlisted. + // ================================================================================== + + /// @notice preCheck reverts SelfCallNotAllowed when the SINGLE-call decoded target equals the + /// account (msg.sender) and self is NOT allowlisted for the call. Source: + /// DefaultSecurityHook.sol:193 `if (target == msg.sender) revert SelfCallNotAllowed()`, + /// reached because the allowlist-first branch (:187-190) does not return for a + /// non-allowlisted entry. Asserts the specific revert selector (non-tautological): a + /// different revert (e.g. UnsupportedCallType, DecodingError) would be a false pass. + function check_DenySelfCall() external { + // Symbolic value and 4-byte data so the gate holds for any selector/value. + uint256 value = svm.createUint256("value"); + bytes4 selector = svm.createBytes4("selector"); + + address account = svm.createAddress("account"); + vm.prank(account); + hook.onInstall(""); + // NOT allowlisted: no setAllowlist call => allowlist[account][account].allowed == false, + // so the allowlist-first branch is skipped and control reaches the self-call gate. + + // executionData for a single call: abi.encodePacked(target(20), value(32), data). + // target == account == msg.sender pins the self-call precondition. + bytes memory executionData = abi.encodePacked(account, value, selector); + + // mode with callType byte == 0x00 (CALLTYPE_SINGLE); remaining bytes symbolic. + uint256 modeTail = svm.createUint(248, "modeTail"); + bytes32 mode = bytes32(modeTail); // high byte (callType) == 0x00 = SINGLE + + // preCheck reads msgData as [0:4] dummy selector, then ABI-encoded (bytes32 mode, bytes + // executionData) at [4:]; it resolves executionData via the ABI offset word at [36:68], so + // for the SINGLE branch (which dereferences executionData) it MUST be ABI-encoded + // (offset+length+data), NOT packed (unlike the delegatecall harness which never reads it). + bytes memory param = abi.encodePacked(bytes4(0), abi.encode(mode, executionData)); + bytes memory msgData = abi.encodeWithSelector(hook.preCheck.selector, address(0), uint256(0), param); + + vm.prank(account); + (bool ok, bytes memory ret) = address(hook).call(msgData); + + assert(!ok); + assert(bytes4(ret) == DefaultSecurityHook.SelfCallNotAllowed.selector); + } + + /// @notice Reachability/vacuity witness for check_DenySelfCall: guards the intended + /// SelfCallNotAllowed revert leaf (SINGLE mode, target==self, not allowlisted) then + /// asserts false, so Halmos MUST emit a counterexample. NO counterexample => the leaf + /// is dead / preconditions unsatisfiable (VACUOUS, report as such — not proven). + function check_DenySelfCall_reachable() external { + uint256 value = svm.createUint256("value"); + bytes4 selector = svm.createBytes4("selector"); + + address account = svm.createAddress("account"); + vm.prank(account); + hook.onInstall(""); + + bytes memory executionData = abi.encodePacked(account, value, selector); + + uint256 modeTail = svm.createUint(248, "modeTail"); + bytes32 mode = bytes32(modeTail); + + bytes memory param = abi.encodePacked(bytes4(0), abi.encode(mode, executionData)); + bytes memory msgData = abi.encodeWithSelector(hook.preCheck.selector, address(0), uint256(0), param); + + vm.prank(account); + (bool ok, bytes memory ret) = address(hook).call(msgData); + + // Only proceed on the intended live revert leaf; assert false to force a counterexample. + if (!ok && bytes4(ret) == DefaultSecurityHook.SelfCallNotAllowed.selector) { + assert(false); + } + } + + // ================================================================================== + // Unsupported callType dispatch: preCheck reverts UnsupportedCallType for ANY callType + // that is not SINGLE (0x00), BATCH (0x01), or DELEGATECALL (0xff). Source: :112-147, + // else-branch revert at :143. + // ================================================================================== + + /// @notice preCheck reverts EXACTLY UnsupportedCallType() when the mode's callType byte + /// (bytes1(mode), read by LibERC7579.getCallType) is NONE of CALLTYPE_SINGLE (0x00), + /// CALLTYPE_BATCH (0x01), or CALLTYPE_DELEGATECALL (0xff). The excluded set forces the + /// else-branch at :143 to be the only reachable leaf; asserting the specific + /// UnsupportedCallType selector (not delegatecall's revert) keeps this non-tautological. + function check_UnsupportedCallTypeReverts() external { + bytes memory executionData = svm.createBytes(64, "executionData"); + // callType is the HIGH byte of the 32-byte mode word (bytes1(mode)). Make it symbolic and + // exclude the three handled types so only the else-branch (:143) can be reached. + uint256 callTypeByte = svm.createUint(8, "callTypeByte"); + vm.assume(callTypeByte != 0x00); // != CALLTYPE_SINGLE + vm.assume(callTypeByte != 0x01); // != CALLTYPE_BATCH + vm.assume(callTypeByte != 0xff); // != CALLTYPE_DELEGATECALL + uint256 modeTail = svm.createUint(248, "modeTail"); // low 31 bytes symbolic + bytes32 mode = bytes32((callTypeByte << 248) | modeTail); + + // Even for an installed + fully-allowlisted account, dispatch happens before allowlist logic. + address account = svm.createAddress("account"); + address target = svm.createAddress("target"); + vm.prank(account); + hook.onInstall(""); + vm.prank(account); + hook.setAllowlist(target, new bytes4[](0)); + + // preCheck reads msgData[4:] as ABI-encoded (bytes32 mode, bytes executionData): the + // executionData OFFSET word at msgData[36:68] must be the concrete 0x40, so use abi.encode + // (NOT abi.encodePacked) for the (mode, executionData) tail — the assembly at :126-131 + // runs BEFORE the else at :143 and dereferences that offset, needing it concrete. + bytes memory param = abi.encodePacked(bytes4(0), abi.encode(mode, executionData)); + bytes memory msgData = abi.encodeWithSelector(hook.preCheck.selector, address(0), uint256(0), param); + + vm.prank(account); + (bool ok, bytes memory ret) = address(hook).call(msgData); + + // OBSERVABLE: reverts with EXACTLY UnsupportedCallType (the :143 leaf, not delegatecall's). + assert(!ok); + assert(bytes4(ret) == DefaultSecurityHook.UnsupportedCallType.selector); + } + + /// @notice Reachability/vacuity witness for check_UnsupportedCallTypeReverts: proves at least + /// one non-{single,batch,delegatecall} callType value exists and actually reaches the + /// UnsupportedCallType leaf (not blocked by an earlier decode revert). Guards on the + /// intended leaf then asserts false so Halmos MUST emit a counterexample; no CEX => + /// excluded set empty / else-branch dead (VACUOUS). + function check_UnsupportedCallTypeReverts_reachable() external { + bytes memory executionData = svm.createBytes(64, "executionData"); + uint256 callTypeByte = svm.createUint(8, "callTypeByte"); + vm.assume(callTypeByte != 0x00); + vm.assume(callTypeByte != 0x01); + vm.assume(callTypeByte != 0xff); + uint256 modeTail = svm.createUint(248, "modeTail"); + bytes32 mode = bytes32((callTypeByte << 248) | modeTail); + + address account = svm.createAddress("account"); + address target = svm.createAddress("target"); + vm.prank(account); + hook.onInstall(""); + vm.prank(account); + hook.setAllowlist(target, new bytes4[](0)); + + // abi.encode (not packed): concrete executionData offset word for the :126-131 assembly. + bytes memory param = abi.encodePacked(bytes4(0), abi.encode(mode, executionData)); + bytes memory msgData = abi.encodeWithSelector(hook.preCheck.selector, address(0), uint256(0), param); + + vm.prank(account); + (bool ok, bytes memory ret) = address(hook).call(msgData); + + // Only the intended live revert leaf reaches assert(false) => forces a counterexample. + if (!ok && bytes4(ret) == DefaultSecurityHook.UnsupportedCallType.selector) { + assert(false); + } + } +} diff --git a/test/halmos/DefaultSecurityHookRemoveAllowlistHalmos.t.sol b/test/halmos/DefaultSecurityHookRemoveAllowlistHalmos.t.sol new file mode 100644 index 0000000..608822e --- /dev/null +++ b/test/halmos/DefaultSecurityHookRemoveAllowlistHalmos.t.sol @@ -0,0 +1,206 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import {SymTest} from "halmos-cheatcodes/SymTest.sol"; +import {DefaultSecurityHook} from "src/hooks/DefaultSecurityHook.sol"; + +// Minimal cheatcode surface. Inheriting forge-std `Test` pulls in a base constructor that calls +// vm.deployCode(string) (StdConfig), which Halmos 0.3.3 does not support and fails setUp(). +interface Vm { + function assume(bool) external pure; + function prank(address) external; + function etch(address, bytes calldata) external; +} + +/// @author taek +/// @notice Halmos proof harness for removeAllowlist correctness (spec §5.3) — the uncovered +/// half of allowlist management. Own file/contract (etch-deploy pattern identical to +/// DefaultSecurityHookHalmos; state-equivalent, no constructor logic). +/// +/// (a) ACCESS: removeAllowlist(target) reverts Unauthorized() when +/// initialized[msg.sender]==false (src:160), mirroring the proven setAllowlist gate. +/// (b) DENY RESTORED: after a real setAllowlist(target, selectors) (symbolic list, +/// length<=2, incl. the empty/blanket case) followed by removeAllowlist(target), +/// the allowlist is observably gone — isAllowlisted==false, isSelectorAllowed==false +/// for a symbolic selector — and a _checkCall-routed SINGLE call to target with +/// value>0 (symbolic selector, incl. the pre-remove-allowlisted one) reverts +/// ETHTransferNotAllowed again, i.e. no stale allowed/allSelectorsAllowed/selectors +/// bit survives _clearAllowlist (src:248-260). Asserted exclusively via public views +/// and observable reverts (no internal-slot reads => non-tautological). +contract DefaultSecurityHookRemoveAllowlistHalmos is SymTest { + Vm internal constant vm = Vm(address(uint160(uint256(keccak256("hevm cheat code"))))); + DefaultSecurityHook internal hook; + + // Distinct concrete addresses so target != msg.sender is structural. TARGET gets a REVERT + // stub etched so its isModuleType staticcall fails => _isModule(TARGET)==false (non-module). + address internal constant ACCOUNT = address(uint160(uint256(keccak256("remove.account")))); + address internal constant TARGET = address(uint160(uint256(keccak256("remove.target")))); + + function setUp() external { + hook = DefaultSecurityHook(address(uint160(uint256(keccak256("DefaultSecurityHook"))))); + vm.etch(address(hook), type(DefaultSecurityHook).runtimeCode); + // REVERT stub (PUSH1 0 PUSH1 0 REVERT): staticcall success==false => not a module. + vm.etch(TARGET, hex"60006000fd"); + } + + // ================================================================================== + // (a) ACCESS: removeAllowlist reverts Unauthorized for an uninitialized caller. + // ================================================================================== + + /// @notice OBSERVABLE: removeAllowlist(target) reverts with exactly Unauthorized() when + /// initialized[msg.sender]==false. Source: DefaultSecurityHook.sol:160 + /// `if (!initialized[msg.sender]) revert Unauthorized();`. Mirror of the proven + /// setAllowlist gate (DSH-ACCESS-01); asserts the revert selector, not a recompute + /// of the init flag. + function check_RemoveAllowlistRevertsWhenUninitialized() external { + address caller = svm.createAddress("caller"); + address target = svm.createAddress("target"); + + // Genuine spec precondition: a fresh account defaults to initialized==false. + vm.assume(!hook.isInitialized(caller)); + + vm.prank(caller); + (bool ok, bytes memory ret) = address(hook).call(abi.encodeCall(hook.removeAllowlist, (target))); + + assert(!ok); + assert(bytes4(ret) == DefaultSecurityHook.Unauthorized.selector); + } + + /// @notice Reachability/vacuity witness for (a): the uninitialized precondition is + /// satisfiable AND an INITIALIZED caller CAN successfully removeAllowlist (the + /// revert is a genuine gate, not universal). Asserts false on the success leaf so + /// Halmos MUST emit a counterexample; no CEX => path dead / precondition vacuous. + function check_RemoveAllowlistRevertsWhenUninitialized_reachable() external { + address caller = svm.createAddress("caller"); + address target = svm.createAddress("target"); + + // Same uninitialized precondition must be satisfiable... + vm.assume(!hook.isInitialized(caller)); + + // ...and an initialized caller CAN remove. onInstall flips initialized[caller]=true. + vm.prank(caller); + hook.onInstall(""); + + vm.prank(caller); + (bool ok,) = address(hook).call(abi.encodeCall(hook.removeAllowlist, (target))); + + // ok==true means the remove succeeded => guard is a genuine, live gate. + assert(!ok); + } + + // ================================================================================== + // (b) DENY RESTORED: setAllowlist then removeAllowlist leaves no observable allow bit. + // ================================================================================== + + /// @dev Build a symbolic selector list of symbolic length n <= 2 (n==0 is the empty/blanket + /// allSelectorsAllowed case) and return it with s0 (first element when n>=1). + /// Explicit if/else fork per length so each Halmos path has a CONCRETE array length + /// (a symbolic `new bytes4[](n)` hits NotConcreteError: symbolic CALLDATACOPY size); + /// all three lengths are still covered, as separate symbolic paths. + function _symbolicSelectors() internal returns (bytes4[] memory sels, bytes4 s0) { + uint256 n = svm.createUint(2, "n"); // 2-bit symbolic: 0..3 + vm.assume(n <= 2); + s0 = svm.createBytes4("s0"); + if (n == 0) { + sels = new bytes4[](0); // blanket: allSelectorsAllowed + } else if (n == 1) { + sels = new bytes4[](1); + sels[0] = s0; + } else { + sels = new bytes4[](2); + sels[0] = s0; + sels[1] = svm.createBytes4("s1"); + } + } + + /// @dev preCheck msgData for CALLTYPE_SINGLE (mode high byte 0x00), packed executionData = + /// target(20) || value(32) || selector(4); param = dummySelector || abi.encode(mode, ed). + function _buildSingleMsgData(address target, uint256 value, bytes4 selector) + internal + view + returns (bytes memory msgData) + { + bytes32 mode = bytes32(0); // CALLTYPE_SINGLE + bytes memory executionData = abi.encodePacked(target, value, selector); + bytes memory param = abi.encodePacked(bytes4(0), abi.encode(mode, executionData)); + msgData = abi.encodeWithSelector(hook.preCheck.selector, address(0), uint256(0), param); + } + + /// @dev Shared (b) pipeline: onInstall -> setAllowlist(TARGET, symbolic sels) -> + /// removeAllowlist(TARGET) -> follow-up preCheck with value>0 and the pre-remove + /// allowed selector (s0 when n>=1, fully symbolic when n==0/blanket). Returns the + /// observable pin (allowed-after-set), the follow-up call result, and the query + /// selector inputs so both the main check and the reachability companion use the + /// IDENTICAL precondition set. + function _setThenRemove() internal returns (bool allowedAfterSet, bool ok, bytes memory ret, uint256 value) { + (bytes4[] memory sels, bytes4 s0) = _symbolicSelectors(); + + vm.prank(ACCOUNT); + hook.onInstall(""); + vm.prank(ACCOUNT); + hook.setAllowlist(TARGET, sels); + + // Observable pin: the pre-remove state really is allowlisted. + allowedAfterSet = hook.isAllowlisted(ACCOUNT, TARGET); + vm.assume(allowedAfterSet); + + vm.prank(ACCOUNT); + hook.removeAllowlist(TARGET); + + // Follow-up _checkCall-routed call: value>0, selector = the one that WAS allowed + // pre-remove (s0 when the list is non-empty; any symbolic selector in the blanket case). + value = svm.createUint256("value"); + vm.assume(value > 0); + bytes4 callSel = sels.length == 0 ? svm.createBytes4("anySel") : s0; + bytes memory msgData = _buildSingleMsgData(TARGET, value, callSel); + + vm.prank(ACCOUNT); + (ok, ret) = address(hook).call(msgData); + } + + /// @notice OBSERVABLE (spec §5.3 DENY RESTORED): for an initialized ACCOUNT that ran a real + /// setAllowlist(TARGET, selectors) (symbolic list, length<=2, incl. empty/blanket) + /// and was observably allowlisted, after removeAllowlist(TARGET): + /// isAllowlisted==false, isSelectorAllowed==false for a symbolic selector, and the + /// follow-up SINGLE preCheck to TARGET with value>0 and the previously-allowed + /// selector reverts with exactly ETHTransferNotAllowed(TARGET, value) — no stale + /// allowed/allSelectorsAllowed/selectors[s] bit survives _clearAllowlist (:248-260). + /// All three legs are the ONE dispatched postcondition conjunction; asserted via + /// public views + the observable revert only. + function check_RemoveAllowlistRestoresDeny() external { + (, bool ok, bytes memory ret, uint256 value) = _setThenRemove(); + + // View leg 1: entry no longer allowlisted. + assert(!hook.isAllowlisted(ACCOUNT, TARGET)); + // View leg 2: no selector (symbolic, incl. the ones just set) is allowed. + bytes4 sQ = svm.createBytes4("sQ"); + assert(!hook.isSelectorAllowed(ACCOUNT, TARGET, sQ)); + // Revert leg: the follow-up call is denied again with the exact ETH-gate error (:199), + // proving the allowlist-first branch (:187-190) no longer returns early. + assert(!ok); + assert( + keccak256(ret) + == keccak256(abi.encodeWithSelector(DefaultSecurityHook.ETHTransferNotAllowed.selector, TARGET, value)) + ); + } + + /// @notice Reachability/vacuity witness for (b), SAME precondition pipeline: proves + /// (i) the setAllowlist=>isAllowlisted==true pre-state pin is satisfiable and + /// (ii) the post-remove ETHTransferNotAllowed deny leaf is actually reached (not + /// shadowed by SelfCall/ModuleCall/decode reverts). Guards on the intended leaf + /// then asserts false, so Halmos MUST emit a counterexample; NO counterexample => + /// preconditions unsatisfiable or leaf dead (VACUOUS — report as such, not proven). + function check_RemoveAllowlistRestoresDeny_reachable() external { + (bool allowedAfterSet, bool ok, bytes memory ret, uint256 value) = _setThenRemove(); + + if ( + allowedAfterSet && !ok + && keccak256(ret) + == keccak256( + abi.encodeWithSelector(DefaultSecurityHook.ETHTransferNotAllowed.selector, TARGET, value) + ) + ) { + assert(false); + } + } +} diff --git a/test/halmos/ECDSASignerNullMatchHalmos.t.sol b/test/halmos/ECDSASignerNullMatchHalmos.t.sol new file mode 100644 index 0000000..edda384 --- /dev/null +++ b/test/halmos/ECDSASignerNullMatchHalmos.t.sol @@ -0,0 +1,167 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import {SymTest} from "halmos-cheatcodes/SymTest.sol"; +import {PackedUserOperation} from "account-abstraction/interfaces/PackedUserOperation.sol"; +import {ECDSASigner} from "src/signers/ECDSASigner.sol"; +import { + SIG_VALIDATION_SUCCESS_UINT, + SIG_VALIDATION_FAILED_UINT, + ERC1271_MAGICVALUE, + ERC1271_INVALID +} from "src/types/Constants.sol"; + +// Minimal cheatcode surface. Inheriting forge-std `Test` pulls in a base constructor that calls +// vm.deployCode(string) (StdConfig), which Halmos 0.3.3 does not support and fails setUp(). +interface Vm { + function assume(bool) external pure; + function prank(address) external; + function etch(address, bytes calldata) external; +} + +/// @author taek +/// @notice Halmos proof harness for ECDSASigner's anti-null-match guard. +/// Proves the observable return codes of checkUserOpSignature / checkSignature match the +/// predicate (owner != 0 && ecrecover-match), with ECDSA recovery as an uninterpreted oracle +/// (Halmos models the ecrecover precompile as an uninterpreted function). +contract ECDSASignerNullMatchHalmos is SymTest { + Vm internal constant vm = Vm(address(uint160(uint256(keccak256("hevm cheat code"))))); + ECDSASigner internal signerc; + + // Fixed caller so the (id, wallet) storage slot is concrete-keyed (Halmos-friendly). + address internal constant CALLER = address(0xCA11); + + function setUp() external { + // Halmos 0.3.3 cannot execute ECDSASigner's via_ir creation bytecode (routes to an + // unsupported deployCode(string) cheat). ECDSASigner has no constructor logic (empty ctor, + // inherits SignerBase), so placing the runtime code directly is state-equivalent. + signerc = ECDSASigner(address(uint160(uint256(keccak256("ECDSASigner"))))); + vm.etch(address(signerc), type(ECDSASigner).runtimeCode); + } + + // Installs a concrete-but-symbolic-valued owner for (id, CALLER) via onInstall. + // Only installs when owner != 0 (the contract rejects the zero-address signer). + function _install(bytes32 id, address owner) internal { + vm.assume(owner != address(0)); + bytes memory data = abi.encodePacked(id, bytes20(owner)); + vm.prank(CALLER); + signerc.onInstall(data); + } + + function _userOp(bytes memory sig) internal pure returns (PackedUserOperation memory op) { + op.signature = sig; + } + + // --------------------------------------------------------------------------------------------- + // checkUserOpSignature + // --------------------------------------------------------------------------------------------- + + /// @notice checkUserOpSignature returns SUCCESS iff owner != 0 AND recovery matches owner; + /// when owner == 0 (unset) it must return FAILED regardless of the signature. + /// Observable: the return code equals the (owner-set && recover-match) predicate, where + /// the recover-match is witnessed by the contract's own _verifySignature semantics — the + /// harness never recomputes recovery, it reads owner from storage and lets the SUCCESS + /// branch itself certify the match (any SUCCESS with owner==0 falsifies the guard). + function check_checkUserOpSignature_nullMatchGuard(bytes32 id, address owner, bytes memory sig) external { + // owner is the value we will store; owner == 0 models the UNSET slot (never installed). + if (owner != address(0)) { + _install(id, owner); + } + // else: slot left untouched => signer[id][CALLER] == address(0) (unset). + + PackedUserOperation memory op = _userOp(sig); + + vm.prank(CALLER); + uint256 ret = signerc.checkUserOpSignature(id, op, keccak256(sig)); + + // Read the on-chain owner (0 if unset) directly from the contract. + address stored = signerc.signer(id, CALLER); + + // Core guard (contrapositive): SUCCESS => signer was set (non-null). + // If owner is unset, SUCCESS is impossible; if a failed recovery returned address(0) that + // matched an unset slot, this would fire. + if (ret == SIG_VALIDATION_SUCCESS_UINT) { + assert(stored != address(0)); + } else { + // The only non-SUCCESS code this function emits is FAILED. + assert(ret == SIG_VALIDATION_FAILED_UINT); + } + } + + /// @notice Unset-signer branch: when the slot was never installed, checkUserOpSignature MUST + /// return FAILED for every signature. Single observable assertion. + function check_checkUserOpSignature_unsetFails(bytes32 id, bytes memory sig) external { + // Slot deliberately left unset (no _install). + PackedUserOperation memory op = _userOp(sig); + + vm.prank(CALLER); + uint256 ret = signerc.checkUserOpSignature(id, op, keccak256(sig)); + + assert(ret == SIG_VALIDATION_FAILED_UINT); + } + + // --------------------------------------------------------------------------------------------- + // checkSignature (ERC-1271 analogue) + // --------------------------------------------------------------------------------------------- + + /// @notice checkSignature returns MAGICVALUE => signer was set (non-null); otherwise INVALID. + function check_checkSignature_nullMatchGuard( + bytes32 id, + address owner, + address sender, + bytes32 hash, + bytes memory sig + ) external { + if (owner != address(0)) { + _install(id, owner); + } + + vm.prank(CALLER); + bytes4 ret = signerc.checkSignature(id, sender, hash, sig); + + address stored = signerc.signer(id, CALLER); + + if (ret == ERC1271_MAGICVALUE) { + assert(stored != address(0)); + } else { + assert(ret == ERC1271_INVALID); + } + } + + /// @notice Unset-signer branch: checkSignature MUST return INVALID when the slot is unset. + function check_checkSignature_unsetFails(bytes32 id, address sender, bytes32 hash, bytes memory sig) external { + vm.prank(CALLER); + bytes4 ret = signerc.checkSignature(id, sender, hash, sig); + + assert(ret == ERC1271_INVALID); + } + + // --------------------------------------------------------------------------------------------- + // REACHABILITY / NON-VACUITY WITNESSES + // --------------------------------------------------------------------------------------------- + + /// @notice Witness: the SUCCESS leaf of checkUserOpSignature is LIVE (owner set, recovery matches). + /// Asserts false on the SUCCESS return; a counterexample proves the path is satisfiable. + function check_checkUserOpSignature_successReachable(bytes32 id, address owner, bytes memory sig) external { + _install(id, owner); // owner != 0 enforced inside + + PackedUserOperation memory op = _userOp(sig); + + vm.prank(CALLER); + uint256 ret = signerc.checkUserOpSignature(id, op, keccak256(sig)); + + // If Halmos can satisfy owner == ecrecover(hash, sig), this fires (path live => non-vacuous). + assert(ret != SIG_VALIDATION_SUCCESS_UINT); + } + + /// @notice Witness: the unset-signer FAILED leaf is LIVE. Slot unset, assert not-FAILED so a + /// counterexample proves the unset path is reachable (non-vacuous). + function check_checkUserOpSignature_unsetReachable(bytes32 id, bytes memory sig) external { + PackedUserOperation memory op = _userOp(sig); + + vm.prank(CALLER); + uint256 ret = signerc.checkUserOpSignature(id, op, keccak256(sig)); + + assert(ret != SIG_VALIDATION_FAILED_UINT); + } +} diff --git a/test/halmos/ECDSAValidatorAuthGateHalmos.t.sol b/test/halmos/ECDSAValidatorAuthGateHalmos.t.sol new file mode 100644 index 0000000..a54fe3f --- /dev/null +++ b/test/halmos/ECDSAValidatorAuthGateHalmos.t.sol @@ -0,0 +1,122 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import {SymTest} from "halmos-cheatcodes/SymTest.sol"; +import {PackedUserOperation} from "account-abstraction/interfaces/PackedUserOperation.sol"; +import {ECDSAValidator} from "src/validators/ECDSAValidator.sol"; +import {SIG_VALIDATION_SUCCESS_UINT, SIG_VALIDATION_FAILED_UINT} from "src/types/Constants.sol"; + +/// @author taek +/// @notice Halmos proof harness for ECDSAValidator.validateUserOp authorization gating. +/// ECDSA recovery is modeled as an uninterpreted oracle (Halmos models the ecrecover +/// precompile as an uninterpreted function, deterministic per (hash, sig)). The harness +/// never recomputes recovery inside an assertion — it reads the stored owner and lets the +/// contract's own SUCCESS branch certify the recover-match. +// Minimal cheatcode surface. Inheriting forge-std `Test` pulls in a base constructor that calls +// vm.deployCode(string) (StdConfig), which Halmos 0.3.3 does not support and fails setUp(). +interface Vm { + function assume(bool) external pure; + function prank(address) external; + function etch(address, bytes calldata) external; +} + +contract ECDSAValidatorAuthGateHalmos is SymTest { + Vm internal constant vm = Vm(address(uint160(uint256(keccak256("hevm cheat code"))))); + ECDSAValidator internal validator; + + // Fixed caller so the storage slot ecdsaValidatorStorage[CALLER] is concrete-keyed (Halmos-friendly). + address internal constant CALLER = address(0xCA11); + + function setUp() external { + // Halmos 0.3.3 cannot execute ECDSAValidator's via_ir creation bytecode (routes to an + // unsupported deployCode(string) cheat). ECDSAValidator has an empty constructor, so placing + // the runtime code directly is state-equivalent (sound vm.etch deploy). + validator = ECDSAValidator(address(uint160(uint256(keccak256("ECDSAValidator"))))); + vm.etch(address(validator), type(ECDSAValidator).runtimeCode); + } + + // Installs a symbolic-valued owner for CALLER via onInstall. onInstall rejects owner == 0. + function _install(address owner) internal { + vm.assume(owner != address(0)); + vm.prank(CALLER); + validator.onInstall(abi.encodePacked(bytes20(owner))); + } + + function _userOp(bytes memory sig) internal pure returns (PackedUserOperation memory op) { + op.signature = sig; + } + + // --------------------------------------------------------------------------------------------- + // CORE PROPERTY + // --------------------------------------------------------------------------------------------- + + /// @notice validateUserOp returns SUCCESS => owner was set (non-null); otherwise it returns + /// FAILED. Contrapositive of "success => (owner!=0 && recovered==owner)": the observable + /// SUCCESS return certifies owner!=0 (the recovered==owner half is enforced by the + /// contract's SUCCESS branch itself; recover stays an uninterpreted oracle, never + /// recomputed in the assertion). owner is symbolic (may be 0), signature is symbolic. + function check_ValidateUserOpAuthGate(address owner, bytes memory sig) external { + // owner == 0 models the UNSET slot (never installed); owner != 0 installs it. + if (owner != address(0)) { + _install(owner); + } + + PackedUserOperation memory op = _userOp(sig); + + vm.prank(CALLER); + uint256 ret = validator.validateUserOp(op, keccak256(sig)); + + (address stored) = validator.ecdsaValidatorStorage(CALLER); + + if (ret == SIG_VALIDATION_SUCCESS_UINT) { + // SUCCESS is impossible when owner is unset: the address(0) early-fail guard + // prevents a failed recovery (which returns address(0)) matching an unset slot. + assert(stored != address(0)); + } else { + // The only non-SUCCESS code this function emits is FAILED. + assert(ret == SIG_VALIDATION_FAILED_UINT); + } + } + + /// @notice owner == 0 (unset) => validateUserOp returns FAILED for every signature. This is the + /// anti-address(0)-match guard as a standalone observable claim. + function check_ValidateUserOpUnsetFails(bytes memory sig) external { + // Slot deliberately left unset (no _install). + PackedUserOperation memory op = _userOp(sig); + + vm.prank(CALLER); + uint256 ret = validator.validateUserOp(op, keccak256(sig)); + + assert(ret == SIG_VALIDATION_FAILED_UINT); + } + + // --------------------------------------------------------------------------------------------- + // REACHABILITY / NON-VACUITY WITNESSES + // --------------------------------------------------------------------------------------------- + + /// @notice Witness: the SUCCESS leaf is LIVE (owner set, uninterpreted recover matches owner). + /// Asserts false on the SUCCESS return; a counterexample proves the path is satisfiable + /// (non-vacuous). If NO counterexample, the SUCCESS path is unreachable => vacuous. + function check_ValidateUserOpAuthGate_reachable(address owner, bytes memory sig) external { + _install(owner); // owner != 0 enforced inside + + PackedUserOperation memory op = _userOp(sig); + + vm.prank(CALLER); + uint256 ret = validator.validateUserOp(op, keccak256(sig)); + + // If Halmos can satisfy owner == recover(hash, sig), this fires (path live => non-vacuous). + assert(ret != SIG_VALIDATION_SUCCESS_UINT); + } + + /// @notice Witness: the unset-owner FAILED leaf is LIVE. Slot unset, assert not-FAILED so a + /// counterexample proves the owner==0 fail path is reachable (non-vacuous). + function check_ValidateUserOpUnsetFails_reachable(bytes memory sig) external { + PackedUserOperation memory op = _userOp(sig); + + vm.prank(CALLER); + uint256 ret = validator.validateUserOp(op, keccak256(sig)); + + assert(ret != SIG_VALIDATION_FAILED_UINT); + } +} diff --git a/test/halmos/ECDSAValidatorGateHalmos.t.sol b/test/halmos/ECDSAValidatorGateHalmos.t.sol new file mode 100644 index 0000000..eadfea0 --- /dev/null +++ b/test/halmos/ECDSAValidatorGateHalmos.t.sol @@ -0,0 +1,180 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +/// @author taek + +import {SymTest} from "halmos-cheatcodes/SymTest.sol"; +import {ECDSAValidator} from "src/validators/ECDSAValidator.sol"; +import {ERC1271_MAGICVALUE, ERC1271_INVALID} from "src/types/Constants.sol"; + +// Minimal cheatcode surface. Inheriting forge-std `Test` pulls in a base constructor that calls +// vm.deployCode(string) (StdConfig), which Halmos 0.3.3 does not support and fails setUp(). +interface Vm { + function assume(bool) external pure; + function prank(address) external; + function etch(address, bytes calldata) external; + function store(address, bytes32, bytes32) external; + function load(address, bytes32) external view returns (bytes32); +} + +/// @notice Halmos proof harness for the three ECDSAValidator access gates: +/// (a) isValidSignatureWithSender returns MAGICVALUE only if owner != 0 (gate at line 97/98) +/// (b) preCheck reverts SenderNotOwner iff msgSender != owner (require at line 120) +/// (c) onInstall reverts ZeroAddressOwner when decoded owner == 0 (require at line 41) +/// +/// MODELING (recover treated as an uninterpreted oracle — see TCB note): +/// `_verifySignature` calls `ECDSA.tryRecoverCalldata`, which routes to the ecrecover precompile +/// (staticcall to address 1). Halmos models ecrecover as an UNINTERPRETED function, so calling the +/// REAL contract with a symbolic (hash, sig) yields `recovered` as an oracle: the same (hash, sig) +/// always recovers the same address, and no concrete constraint is placed on what that address is. +/// This lets us prove the OBSERVABLE gate (return / revert selector) without recomputing ecrecover. +contract ECDSAValidatorGateHalmos is SymTest { + Vm internal constant vm = Vm(address(uint160(uint256(keccak256("hevm cheat code"))))); + ECDSAValidator internal validator; + + // The smart account under whose storage slot the owner is registered. + address internal constant ACCOUNT = address(0xACC); + + function setUp() external { + // Halmos 0.3.3 cannot execute via_ir creation bytecode (routes to an unsupported + // deployCode(string) cheat), so place the runtime code directly. ECDSAValidator has an + // empty constructor (all state set via onInstall / vm.store), so etch is state-equivalent. + validator = ECDSAValidator(address(uint160(uint256(keccak256("ECDSAValidator"))))); + vm.etch(address(validator), type(ECDSAValidator).runtimeCode); + } + + // Writes `owner` into ecdsaValidatorStorage[ACCOUNT].owner directly (bypasses onInstall's + // owner!=0 guard so we can also test the owner==0 branch of (a)). mapping(address => struct{address}) + // at declaration slot 0: slot = keccak256(abi.encode(ACCOUNT, uint256(0))); struct field 0 is `owner`. + function _setOwner(address owner) internal { + bytes32 slot = keccak256(abi.encode(ACCOUNT, uint256(0))); + vm.store(address(validator), slot, bytes32(uint256(uint160(owner)))); + } + + // ------------------------------------------------------------------------------------------- + // (a) isValidSignatureWithSender: MAGICVALUE => owner != 0 (and owner == 0 => INVALID) + // ------------------------------------------------------------------------------------------- + + /// @notice (a) The ERC-1271 gate: whenever the real function returns MAGICVALUE, the stored owner + /// is non-zero. Owner, sender, hash and sig are all symbolic; recover is the ecrecover + /// oracle. Observable postcondition (line 97 gate): MAGICVALUE => owner != 0. + function check_ecdsaGate_magicValueImpliesOwnerSet(address owner, address sender, bytes32 hash, bytes memory sig) + external + { + _setOwner(owner); + + vm.prank(ACCOUNT); + bytes4 result = validator.isValidSignatureWithSender(sender, hash, sig); + + // Gate: a valid result is impossible with an unset owner. + assert(!(result == ERC1271_MAGICVALUE && owner == address(0))); + // Complement (line 97): unset owner always yields INVALID (never any other bytes4). + assert(!(owner == address(0) && result != ERC1271_INVALID)); + } + + /// @notice (a) Reachability witness: MAGICVALUE is reachable with owner != 0 AND recovered == owner. + /// We pin owner to the ecrecover oracle result for THIS (hash, sig): if that value is + /// non-zero, the raw-hash branch of _verifySignature must return true => MAGICVALUE. + /// Asserting `result != MAGICVALUE` here MUST yield a counterexample (path is live). + function check_ecdsaGate_magicValueReachable(bytes32 hash, bytes memory sig) external { + // recovered = the (uninterpreted) ecrecover oracle for (hash, sig). + address recovered = _recoverOracle(hash, sig); + vm.assume(recovered != address(0)); // the only precondition needed for a valid signature + + _setOwner(recovered); // owner matches the recovered signer => _verifySignature true branch + + vm.prank(ACCOUNT); + bytes4 result = validator.isValidSignatureWithSender(address(0xB0B), hash, sig); + + // Counterexample expected: MAGICVALUE IS reachable (owner != 0, recovered == owner). + assert(result != ERC1271_MAGICVALUE); + } + + // Exposes the same ecrecover oracle the contract uses for the raw hash (solady tryRecoverCalldata). + // Uses the identical staticcall-to-precompile-1 path, so Halmos unifies it with the in-contract call. + function _recoverOracle(bytes32 hash, bytes memory sig) internal view returns (address result) { + // 65-byte form: v = sig[64], r = sig[0:32], s = sig[32:64] (mirrors solady case 65). + assembly { + let len := mload(sig) + if eq(len, 65) { + let m := mload(0x40) + mstore(0x00, hash) + mstore(0x20, byte(0, mload(add(sig, add(0x20, 0x40))))) // v + mstore(0x40, mload(add(sig, 0x20))) // r + mstore(0x60, mload(add(sig, add(0x20, 0x20)))) // s + pop(staticcall(gas(), 1, 0x00, 0x80, 0x40, 0x20)) + mstore(0x60, 0) + result := mload(xor(0x60, returndatasize())) + mstore(0x40, m) + } + } + } + + // ------------------------------------------------------------------------------------------- + // (b) preCheck: reverts SenderNotOwner iff msgSender != owner (both directions) + // ------------------------------------------------------------------------------------------- + + /// @notice (b) preCheck reverts SenderNotOwner iff msgSender != owner. Asserts BOTH directions: + /// msgSender == owner => no revert; msgSender != owner => revert with SenderNotOwner. + function check_ecdsaGate_preCheckSenderEqOwner(address owner, address msgSender) external { + _setOwner(owner); + + vm.prank(ACCOUNT); + (bool ok, bytes memory ret) = + address(validator).call(abi.encodeCall(ECDSAValidator.preCheck, (msgSender, 0, hex""))); + + if (msgSender == owner) { + // Forward direction: equal => the require passes => no revert. + assert(ok); + } else { + // Reverse direction: unequal => revert, and specifically with SenderNotOwner(). + assert(!ok); + assert(bytes4(ret) == ECDSAValidator.SenderNotOwner.selector); + } + } + + /// @notice (b) Reachability witness: the non-revert path (msgSender == owner) is live. + /// Asserting `!ok` on the equal branch MUST yield a counterexample (proves it can succeed). + function check_ecdsaGate_preCheckReachable(address owner) external { + _setOwner(owner); + + vm.prank(ACCOUNT); + (bool ok,) = address(validator).call(abi.encodeCall(ECDSAValidator.preCheck, (owner, 0, hex""))); + + // Counterexample expected: preCheck DOES succeed when msgSender == owner (path is live). + assert(!ok); + } + + // ------------------------------------------------------------------------------------------- + // (c) onInstall: owner == 0 reverts ZeroAddressOwner; length != 20 reverts InvalidDataLength + // ------------------------------------------------------------------------------------------- + + /// @notice (c) onInstall with a well-formed (length-20) payload whose decoded owner is zero + /// reverts ZeroAddressOwner. Length is fixed to 20 so we isolate the owner==0 gate + /// (line 41) from the length gate (line 39). ACCOUNT is uninitialized (owner slot 0). + function check_ecdsaGate_onInstallZeroOwnerReverts(bytes32 tail) external { + // 20-byte payload with all-zero owner bytes; `tail` is unused entropy proving the revert + // does not depend on payload content beyond the 20 owner bytes being zero. + tail; // silence unused warning; kept symbolic to widen the input space + bytes memory data = new bytes(20); // all zero => decoded owner == address(0) + + vm.prank(ACCOUNT); + (bool ok, bytes memory ret) = address(validator).call(abi.encodeCall(ECDSAValidator.onInstall, (data))); + + assert(!ok); + assert(bytes4(ret) == ECDSAValidator.ZeroAddressOwner.selector); + } + + /// @notice (c) Reachability witness: onInstall SUCCEEDS with a length-20, non-zero-owner payload, + /// proving the revert in the property above is discriminating (not a universal revert). + /// Asserting `!ok` MUST yield a counterexample. + function check_ecdsaGate_onInstallReachable(address owner) external { + vm.assume(owner != address(0)); + bytes memory data = abi.encodePacked(owner); // exactly 20 bytes, non-zero owner + + vm.prank(ACCOUNT); + (bool ok,) = address(validator).call(abi.encodeCall(ECDSAValidator.onInstall, (data))); + + assert(!ok); + } +} diff --git a/test/halmos/GasPolicyBudgetHalmos.t.sol b/test/halmos/GasPolicyBudgetHalmos.t.sol new file mode 100644 index 0000000..c8b4844 --- /dev/null +++ b/test/halmos/GasPolicyBudgetHalmos.t.sol @@ -0,0 +1,87 @@ +pragma solidity ^0.8.0; + +import {Test} from "forge-std/Test.sol"; +import {SymTest} from "halmos-cheatcodes/SymTest.sol"; +import {PackedUserOperation} from "account-abstraction/interfaces/PackedUserOperation.sol"; +import {GasPolicy, GasPolicyConfig, Status} from "src/policies/GasPolicy.sol"; + +/// @author taek +contract GasPolicyBudgetHalmos is SymTest, Test { + GasPolicy policy; + + function setUp() external { + // vm.etch (not `new`) — halmos 0.3.3 falls back to the unsupported deployCode cheat when + // symbolically executing CREATE for this via_ir creation code. Etching runtimeCode sidesteps it. + policy = GasPolicy(address(0xAAAA)); + vm.etch(address(policy), type(GasPolicy).runtimeCode); + } + + // Builds a fully symbolic userOp and installs a symbolic, Live config for (id, sender). + // Returns the pre-decrement `allowed`. + function _prime(bytes32 id, address sender) + internal + returns (PackedUserOperation memory userOp, uint128 allowedPre) + { + // Symbolic, Live config. Installing via _policyOninstall keeps the storage layout honest + // (status = Live, allowed/enforcePaymaster/allowedPaymaster symbolic). + uint128 allowed = uint128(svm.createUint(128, "allowed")); + bool enforcePaymaster = svm.createBool("enforcePaymaster"); + address allowedPaymaster = svm.createAddress("allowedPaymaster"); + vm.prank(sender); + policy.onInstall(abi.encode(id, allowed, enforcePaymaster, allowedPaymaster)); + allowedPre = allowed; + + userOp.sender = svm.createAddress("uo.sender"); + userOp.nonce = svm.createUint256("uo.nonce"); + userOp.initCode = svm.createBytes(0, "uo.initCode"); + userOp.callData = svm.createBytes(0, "uo.callData"); + userOp.accountGasLimits = svm.createBytes32("uo.accountGasLimits"); + userOp.preVerificationGas = svm.createUint256("uo.preVerificationGas"); + userOp.gasFees = svm.createBytes32("uo.gasFees"); + userOp.paymasterAndData = svm.createBytes(64, "uo.paymasterAndData"); + userOp.signature = svm.createBytes(0, "uo.signature"); + } + + /// @notice After checkUserOpPolicy (success, fail-return, or caught revert), the stored budget + /// `allowed` for (id, sender) is <= its pre-call value. + function check_BudgetMonotonicNonIncreasing(bytes32 id, address sender) external { + (PackedUserOperation memory userOp, uint128 allowedPre) = _prime(id, sender); + + vm.prank(sender); + try policy.checkUserOpPolicy(id, userOp) returns ( + uint256 + ) { + // success or fail-return path + } + catch { + // revert-caught path + } + + (uint128 allowedPost,,) = policy.gasPolicyConfig(id, sender); + assertLe(allowedPost, allowedPre); + } + + /// @notice Vacuity/reachability witness: an accepted op that STRICTLY decreases allowed must + /// exist. Asserts the negation (accept AND post < pre) so a counterexample proves the + /// strict-decrement path is live and non-vacuous. + /// @dev Gas fields are kept narrow (<=64-bit) so the nonlinear maxAmount multiply stays + /// tractable for the solver; the config (allowed) stays fully symbolic. This constrains + /// only the WITNESS search space, not the property (the property proof above is unrestricted). + function check_BudgetMonotonicNonIncreasing_reachable(bytes32 id, address sender) external { + uint128 allowedPre = 1_000_000; + vm.prank(sender); + policy.onInstall(abi.encode(id, allowedPre, false, address(0))); + + // Concrete witness: verificationGasLimit=0, callGasLimit=1000, maxFeePerGas=1, + // preVerificationGas=0 => maxAmount = 1000, which is <= allowed and > 0. + PackedUserOperation memory userOp; + userOp.accountGasLimits = bytes32(uint256(1000)); // low 128 bits = callGasLimit + userOp.gasFees = bytes32(uint256(1)); // low 128 bits = maxFeePerGas + + vm.prank(sender); + uint256 ret = policy.checkUserOpPolicy(id, userOp); + + (uint128 allowedPost,,) = policy.gasPolicyConfig(id, sender); + assertFalse(ret == 0 && allowedPost < allowedPre); + } +} diff --git a/test/halmos/GasPolicyHalmos.t.sol b/test/halmos/GasPolicyHalmos.t.sol new file mode 100644 index 0000000..805181d --- /dev/null +++ b/test/halmos/GasPolicyHalmos.t.sol @@ -0,0 +1,185 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import {SymTest} from "halmos-cheatcodes/SymTest.sol"; +import {PackedUserOperation} from "account-abstraction/interfaces/PackedUserOperation.sol"; +import {GasPolicy, GasPolicyConfig, Status} from "src/policies/GasPolicy.sol"; +import {SIG_VALIDATION_SUCCESS_UINT, SIG_VALIDATION_FAILED_UINT} from "src/types/Constants.sol"; + +// Minimal cheatcode surface. Inheriting forge-std `Test` pulls in a base constructor that calls +// vm.deployCode(string) (StdConfig), which Halmos 0.3.3 does not support and fails setUp(). +interface Vm { + function assume(bool) external pure; + function prank(address) external; + function etch(address, bytes calldata) external; +} + +/// @author taek +/// @notice Halmos proof harness for GasPolicy.checkUserOpPolicy budget accounting. +contract GasPolicyHalmos is SymTest { + Vm internal constant vm = Vm(address(uint160(uint256(keccak256("hevm cheat code"))))); + GasPolicy internal policy; + + // Fixed identifiers so storage reads/writes are concrete-keyed (Halmos-friendly). + bytes32 internal constant ID = bytes32(uint256(0xABCD)); + address internal constant CALLER = address(0xCA11); + + function setUp() external { + // Halmos 0.3.3 cannot execute GasPolicy's via_ir creation bytecode (routes to an + // unsupported deployCode(string) cheat), so place the runtime code directly. GasPolicy has + // no constructor logic (all state is set later via onInstall), so etch is state-equivalent. + policy = GasPolicy(address(uint160(uint256(keccak256("GasPolicy"))))); + vm.etch(address(policy), type(GasPolicy).runtimeCode); + } + + // Installs the policy for (ID, CALLER) with a symbolic budget and paymaster disabled, + // so the paymaster branch cannot interfere with the pure budget-accounting property. + function _install(uint128 allowed) internal { + bytes memory data = abi.encodePacked(ID, abi.encode(allowed, false, address(0))); + vm.prank(CALLER); + policy.onInstall(data); + } + + // Builds a PackedUserOperation whose gas-relevant fields carry the given symbolic values. + // verificationGasLimit occupies the high 128 bits of accountGasLimits, callGasLimit the low 128. + // maxFeePerGas occupies the low 128 bits of gasFees. + function _userOp( + uint256 preVerificationGas, + uint128 verificationGasLimit, + uint128 callGasLimit, + uint128 maxFeePerGas + ) internal pure returns (PackedUserOperation memory op) { + op.accountGasLimits = bytes32((uint256(verificationGasLimit) << 128) | uint256(callGasLimit)); + op.preVerificationGas = preVerificationGas; + op.gasFees = bytes32(uint256(maxFeePerGas)); // high 128 (priority fee) left zero, unused + } + + /// @notice Budget decreases by exactly the TRUE uint256 cost, and no over-cap op passes. + /// Combines success-exactness (a), over-cap rejection (b), and monotonicity (c) into the single + /// invariant "post == pre - trueCost on success, never SUCCESS when trueCost > pre, post <= pre". + function check_gasPolicy_noUnderCharge( + uint128 allowed, + uint256 preVerificationGas, + uint128 verificationGasLimit, + uint128 callGasLimit, + uint128 maxFeePerGas + ) external { + // Bound operands so the TRUE product is representable in uint256 (dispatch: avoid ~2^320 wrap). + // sum <= 2^128 and maxFeePerGas <= 2^128 => product <= 2^256, still >> 2^128 (over-cap region). + uint256 sum = uint256(preVerificationGas) + uint256(verificationGasLimit) + uint256(callGasLimit); + vm.assume(sum <= (uint256(1) << 128)); + // trueCost independently computed by the harness in full uint256 (NOT read from the contract). + uint256 trueCost = sum * uint256(maxFeePerGas); + + _install(allowed); + + PackedUserOperation memory op = _userOp(preVerificationGas, verificationGasLimit, callGasLimit, maxFeePerGas); + + vm.prank(CALLER); + (bool ok, bytes memory ret) = address(policy).call(abi.encodeCall(policy.checkUserOpPolicy, (ID, op))); + + (uint128 allowedPost,,) = policy.gasPolicyConfig(ID, CALLER); + + if (ok) { + uint256 result = abi.decode(ret, (uint256)); + if (result == SIG_VALIDATION_SUCCESS_UINT) { + // (a) success => true cost within budget and budget decremented by TRUE cost. + assert(trueCost <= allowed); + assert(uint256(allowedPost) == uint256(allowed) - trueCost); + } else { + // FAILED path leaves budget untouched. + assert(uint256(allowedPost) == uint256(allowed)); + } + // (b) an over-cap op must never reach SUCCESS. + assert(!(trueCost > allowed && result == SIG_VALIDATION_SUCCESS_UINT)); + } else { + // Revert (e.g. 0.8 overflow) leaves state unchanged. + assert(uint256(allowedPost) == uint256(allowed)); + } + // (c) monotone non-increasing budget. + assert(uint256(allowedPost) <= uint256(allowed)); + } + + /// @notice Reachability witness: SUCCESS path is live. Asserts false on the SUCCESS leaf under the + /// SAME precondition set; a counterexample proves the success path is satisfiable (non-vacuous). + function check_gasPolicy_noUnderCharge_reachable( + uint128 allowed, + uint256 preVerificationGas, + uint128 verificationGasLimit, + uint128 callGasLimit, + uint128 maxFeePerGas + ) external { + uint256 sum = uint256(preVerificationGas) + uint256(verificationGasLimit) + uint256(callGasLimit); + vm.assume(sum <= (uint256(1) << 128)); + + _install(allowed); + PackedUserOperation memory op = _userOp(preVerificationGas, verificationGasLimit, callGasLimit, maxFeePerGas); + + vm.prank(CALLER); + uint256 result = policy.checkUserOpPolicy(ID, op); + + // If SUCCESS is reachable, Halmos yields a counterexample here (proves path liveness). + assert(result != SIG_VALIDATION_SUCCESS_UINT); + } + + /// @notice Boundary reachability witness: the truncation boundary (trueCost == 2^128, low128 == 0) + /// must be REJECTED. Asserts false on the SUCCESS leaf for that exact input; a counterexample would + /// mean it was accepted (impl bug). NO counterexample => it is rejected as required. + /// verificationGasLimit = 2^80, maxFeePerGas = 2^48 => product = 2^128 (low 128 bits all zero). + function check_gasPolicy_truncationBoundary_rejected(uint128 allowed) external { + _install(allowed); + PackedUserOperation memory op = _userOp(0, uint128(uint256(1) << 80), 0, uint128(uint256(1) << 48)); + + vm.prank(CALLER); + (bool ok, bytes memory ret) = address(policy).call(abi.encodeCall(policy.checkUserOpPolicy, (ID, op))); + + // trueCost == 2^128 > allowed (allowed <= type(uint128).max < 2^128) => must NOT succeed. + // If uint128 truncation were used instead, low128 == 0 would make maxAmount == 0 and this + // would incorrectly SUCCEED. + if (ok) { + uint256 result = abi.decode(ret, (uint256)); + assert(result != SIG_VALIDATION_SUCCESS_UINT); + } + } + + // --------------------------------------------------------------------------------------------- + // SUB-LEMMA: the uint128 truncation boundary is closed (family P = 2^128 + r * 2^48). + // --------------------------------------------------------------------------------------------- + + /// @notice Sub-lemma: for the operand family whose TRUE uint256 product P >= 2^128, and any + /// uint128 budget (allowed < 2^128 < P), checkUserOpPolicy rejects AND leaves the budget + /// untouched. Base P = (2^80) * (2^48) = 2^128; symbolic remainder r in [0, 2^47) gives + /// P = (2^80 + r) * 2^48 = 2^128 + r*2^48 >= 2^128. Observable: not SUCCESS AND no decrement. + function check_gasPolicy_truncationBoundaryFamily_rejectsNoDecrement(uint128 allowed, uint256 r) external { + vm.assume(r < (uint256(1) << 47)); // keep preVerificationGas small: P just above 2^128, no wrap + + _install(allowed); + (uint128 allowedPre,,) = policy.gasPolicyConfig(ID, CALLER); + + // verificationGasLimit = 2^80, maxFeePerGas = 2^48, preVerificationGas = r, callGasLimit = 0. + PackedUserOperation memory op = _userOp(r, uint128(uint256(1) << 80), 0, uint128(uint256(1) << 48)); + + vm.prank(CALLER); + uint256 result = policy.checkUserOpPolicy(ID, op); + + (uint128 allowedPost,,) = policy.gasPolicyConfig(ID, CALLER); + + // Fixed reject outcome at/above the numeric boundary; budget must not be decremented. + assert(result != SIG_VALIDATION_SUCCESS_UINT && allowedPost == allowedPre); + } + + /// @notice Reachability witness for the sub-lemma: a NON-boundary op (small product P <= allowed) + /// DOES return SUCCESS, proving the reject branch is discriminating (not a universal + /// revert/reject). Asserts false on the SUCCESS leaf; a counterexample => path is live. + function check_gasPolicy_truncationBoundaryFamily_rejectsNoDecrement_reachable(uint128 allowed) external { + vm.assume(allowed >= 1000); // budget large enough to admit a tiny op + + _install(allowed); + + PackedUserOperation memory op; // all-zero gas fields => P = 0 <= allowed => SUCCESS branch + vm.prank(CALLER); + uint256 result = policy.checkUserOpPolicy(ID, op); + + assert(result != SIG_VALIDATION_SUCCESS_UINT); + } +} diff --git a/test/halmos/MultiOwnerValidatorHalmos.t.sol b/test/halmos/MultiOwnerValidatorHalmos.t.sol new file mode 100644 index 0000000..bb0ef3c --- /dev/null +++ b/test/halmos/MultiOwnerValidatorHalmos.t.sol @@ -0,0 +1,230 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.20; + +import {SymTest} from "halmos-cheatcodes/SymTest.sol"; +import {PackedUserOperation} from "account-abstraction/interfaces/PackedUserOperation.sol"; + +import {IStatelessValidator} from "src/interfaces/IERC7579Modules.sol"; +import { + ERC1271_INVALID, + ERC1271_MAGICVALUE, + MODULE_TYPE_STATELESS_VALIDATOR, + SIG_VALIDATION_FAILED_UINT +} from "src/types/Constants.sol"; +import {MultiOwnerValidator} from "src/validators/MultiOwnerValidator.sol"; + +interface Vm { + function assume(bool) external pure; + function prank(address) external; + function etch(address, bytes calldata) external; +} + +/// @notice Deterministic stateless-validator boundary for the registry proofs. +/// @dev A signature is accepted exactly when it equals the supplied validation data. +contract MultiOwnerStatelessSignerHalmosStub is IStatelessValidator { + function onInstall(bytes calldata) external payable {} + + function onUninstall(bytes calldata) external payable {} + + function isModuleType(uint256 moduleTypeId) external pure returns (bool) { + return moduleTypeId == MODULE_TYPE_STATELESS_VALIDATOR; + } + + function validateSignatureWithData(bytes32, bytes calldata signature, bytes calldata data) + external + pure + returns (bool) + { + return keccak256(signature) == keccak256(data); + } +} + +/// @title MultiOwnerValidatorHalmos +/// @author taek +/// @notice Symbolic storage, lifecycle, dispatch, selection, and account-isolation properties for +/// the stateless-signer multi-owner root validator. +/// @dev TCB / MODELING: the registry and external dispatch execute unchanged. The selected +/// `IStatelessValidator` is modeled as a deterministic oracle that accepts exactly when the +/// owner signature equals its supplied validation data. The properties prove registry and +/// dispatch correctness, not the soundness of an arbitrary child signer. +contract MultiOwnerValidatorHalmos is SymTest { + Vm internal constant vm = Vm(address(uint160(uint256(keccak256("hevm cheat code"))))); + + address internal constant ACCOUNT = address(0xA11); + address internal constant OTHER_ACCOUNT = address(0xB22); + bytes32 internal constant FIXED_ID = bytes32(uint256(0x1111)); + bytes32 internal constant SECOND_ID = bytes32(uint256(0x2222)); + + MultiOwnerValidator internal validator; + address internal statelessSigner; + + function setUp() external { + validator = MultiOwnerValidator(address(uint160(uint256(keccak256("MultiOwnerValidator"))))); + statelessSigner = address(uint160(uint256(keccak256("MultiOwnerStatelessSigner")))); + vm.etch(address(validator), type(MultiOwnerValidator).runtimeCode); + vm.etch(statelessSigner, type(MultiOwnerStatelessSignerHalmosStub).runtimeCode); + } + + function check_InstallStoresExactlyTheScopedRegistry( + bytes32 firstId, + bytes32 secondId, + address firstOwner, + address secondOwner + ) external { + vm.assume(firstId != bytes32(0) && secondId != bytes32(0)); + vm.assume(firstId != secondId); + vm.assume(firstOwner != address(0) && secondOwner != address(0)); + + MultiOwnerValidator.OwnerConfig[] memory configs = new MultiOwnerValidator.OwnerConfig[](2); + configs[0] = _config(firstId, firstOwner); + configs[1] = _config(secondId, secondOwner); + + vm.prank(ACCOUNT); + validator.onInstall(abi.encode(configs)); + + assert(validator.isInitialized(ACCOUNT)); + assert(validator.ownerCount(ACCOUNT) == 2); + assert(validator.ownerIdAt(ACCOUNT, 0) == firstId); + assert(validator.ownerIdAt(ACCOUNT, 1) == secondId); + (address firstSigner, bytes memory firstData) = validator.owners(ACCOUNT, firstId); + (address secondSigner, bytes memory secondData) = validator.owners(ACCOUNT, secondId); + assert(firstSigner == statelessSigner && keccak256(firstData) == keccak256(abi.encode(firstOwner))); + assert(secondSigner == statelessSigner && keccak256(secondData) == keccak256(abi.encode(secondOwner))); + + assert(!validator.isInitialized(OTHER_ACCOUNT)); + assert(validator.ownerCount(OTHER_ACCOUNT) == 0); + (address otherSigner, bytes memory otherData) = validator.owners(OTHER_ACCOUNT, firstId); + assert(otherSigner == address(0) && otherData.length == 0); + } + + function check_AddUpdateRemovePreservesCountAndEnumeration( + address firstOwner, + address secondOwner, + address rotatedOwner + ) external { + vm.assume(firstOwner != address(0) && secondOwner != address(0) && rotatedOwner != address(0)); + + _installOne(ACCOUNT, FIXED_ID, firstOwner); + + vm.prank(ACCOUNT); + validator.addOwner(_config(SECOND_ID, secondOwner)); + assert(validator.ownerCount(ACCOUNT) == 2); + + vm.prank(ACCOUNT); + validator.updateOwner(_config(SECOND_ID, rotatedOwner)); + assert(validator.ownerCount(ACCOUNT) == 2); + (address rotatedSigner, bytes memory rotatedData) = validator.owners(ACCOUNT, SECOND_ID); + assert(rotatedSigner == statelessSigner && keccak256(rotatedData) == keccak256(abi.encode(rotatedOwner))); + + vm.prank(ACCOUNT); + validator.removeOwner(FIXED_ID); + assert(validator.ownerCount(ACCOUNT) == 1); + assert(validator.ownerIdAt(ACCOUNT, 0) == SECOND_ID); + (address removedSigner, bytes memory removedData) = validator.owners(ACCOUNT, FIXED_ID); + assert(removedSigner == address(0) && removedData.length == 0); + } + + function check_LastOwnerCannotBeRemoved(address owner) external { + vm.assume(owner != address(0)); + _installOne(ACCOUNT, FIXED_ID, owner); + + vm.prank(ACCOUNT); + (bool ok, bytes memory returndata) = address(validator).call(abi.encodeCall(validator.removeOwner, (FIXED_ID))); + + assert(!ok); + assert(_selector(returndata) == MultiOwnerValidator.CannotRemoveLastOwner.selector); + assert(validator.ownerCount(ACCOUNT) == 1); + assert(validator.isInitialized(ACCOUNT)); + } + + function check_UninstallClearsEveryOwner(address firstOwner, address secondOwner) external { + vm.assume(firstOwner != address(0) && secondOwner != address(0)); + + MultiOwnerValidator.OwnerConfig[] memory configs = new MultiOwnerValidator.OwnerConfig[](2); + configs[0] = _config(FIXED_ID, firstOwner); + configs[1] = _config(SECOND_ID, secondOwner); + vm.prank(ACCOUNT); + validator.onInstall(abi.encode(configs)); + + vm.prank(ACCOUNT); + validator.onUninstall(""); + + assert(!validator.isInitialized(ACCOUNT)); + assert(validator.ownerCount(ACCOUNT) == 0); + (address firstSigner, bytes memory firstData) = validator.owners(ACCOUNT, FIXED_ID); + (address secondSigner, bytes memory secondData) = validator.owners(ACCOUNT, SECOND_ID); + assert(firstSigner == address(0) && firstData.length == 0); + assert(secondSigner == address(0) && secondData.length == 0); + } + + function check_SameOwnerIdIsSeparatedAcrossAccounts(address firstOwner, address secondOwner) external { + vm.assume(firstOwner != address(0) && secondOwner != address(0)); + + _installOne(ACCOUNT, FIXED_ID, firstOwner); + _installOne(OTHER_ACCOUNT, FIXED_ID, secondOwner); + + (, bytes memory firstData) = validator.owners(ACCOUNT, FIXED_ID); + (, bytes memory secondData) = validator.owners(OTHER_ACCOUNT, FIXED_ID); + assert(keccak256(firstData) == keccak256(abi.encode(firstOwner))); + assert(keccak256(secondData) == keccak256(abi.encode(secondOwner))); + } + + function check_SelectedOwnerRoutesItsExactValidationData(bytes32 hash, address owner, address otherOwner) external { + vm.assume(owner != address(0) && otherOwner != address(0)); + vm.assume(owner != otherOwner); + _installOne(ACCOUNT, FIXED_ID, owner); + + vm.prank(ACCOUNT); + bytes4 accepted = + validator.isValidSignatureWithSender(address(0), hash, abi.encodePacked(FIXED_ID, abi.encode(owner))); + vm.prank(ACCOUNT); + bytes4 rejected = + validator.isValidSignatureWithSender(address(0), hash, abi.encodePacked(FIXED_ID, abi.encode(otherOwner))); + + assert(accepted == ERC1271_MAGICVALUE); + assert(rejected == ERC1271_INVALID); + } + + function check_UnknownOwnerCanNeverValidate(bytes32 unknownId, bytes32 hash, address owner) external { + vm.assume(owner != address(0)); + vm.assume(unknownId != FIXED_ID); + _installOne(ACCOUNT, FIXED_ID, owner); + + bytes memory signature = abi.encodePacked(unknownId, abi.encode(owner)); + vm.prank(ACCOUNT); + bytes4 result = validator.isValidSignatureWithSender(address(0), hash, signature); + assert(result == ERC1271_INVALID); + } + + function check_UserOpSenderMustEqualCallingAccount(bytes32 hash, bytes32 selectedId, address owner) external { + vm.assume(owner != address(0)); + _installOne(ACCOUNT, FIXED_ID, owner); + + PackedUserOperation memory userOp; + userOp.sender = OTHER_ACCOUNT; + userOp.signature = abi.encodePacked(selectedId, abi.encode(owner)); + + vm.prank(ACCOUNT); + uint256 result = validator.validateUserOp(userOp, hash); + assert(result == SIG_VALIDATION_FAILED_UINT); + } + + function _installOne(address account, bytes32 ownerId, address owner) internal { + MultiOwnerValidator.OwnerConfig[] memory configs = new MultiOwnerValidator.OwnerConfig[](1); + configs[0] = _config(ownerId, owner); + vm.prank(account); + validator.onInstall(abi.encode(configs)); + } + + function _config(bytes32 ownerId, address owner) internal view returns (MultiOwnerValidator.OwnerConfig memory) { + return MultiOwnerValidator.OwnerConfig(ownerId, statelessSigner, abi.encode(owner)); + } + + function _selector(bytes memory returndata) internal pure returns (bytes4 result) { + if (returndata.length >= 4) { + assembly ("memory-safe") { + result := mload(add(returndata, 0x20)) + } + } + } +} diff --git a/test/halmos/P256ModuleHalmos.t.sol b/test/halmos/P256ModuleHalmos.t.sol new file mode 100644 index 0000000..bb6ab04 --- /dev/null +++ b/test/halmos/P256ModuleHalmos.t.sol @@ -0,0 +1,321 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.20; + +import {SymTest} from "halmos-cheatcodes/SymTest.sol"; +import {PackedUserOperation} from "account-abstraction/interfaces/PackedUserOperation.sol"; +import {P256Validator} from "src/validators/P256Validator.sol"; +import {P256Signer} from "src/signers/P256Signer.sol"; +import {SIG_VALIDATION_SUCCESS_UINT, SIG_VALIDATION_FAILED_UINT, ERC1271_INVALID} from "src/types/Constants.sol"; + +interface Vm { + function assume(bool) external pure; + function prank(address) external; + function etch(address, bytes calldata) external; + function store(address, bytes32, bytes32) external; +} + +/// @notice Executable model of the RIP-7212/EIP-7951 verifier boundary. +/// @dev Slot zero is the symbolic verifier result for ordinary inputs. +contract P256PrecompileHalmosStub { + fallback() external { + assembly ("memory-safe") { + let result := sload(0) + let isProbe := + and( + and( + eq(calldataload(0), 0xbb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023), + eq(calldataload(0x20), 5) + ), + and( + and( + eq(calldataload(0x40), 1), + eq(calldataload(0x60), 0xa71af64de5126a4a4e02b7922d66ce9415ce88a4c9d25514d91082c8725ac957) + ), + eq(calldataload(0x80), 0x5d47723c8fbe580bb369fec9c2665d8e30a435b9932645482e7c9f11e872296b) + ) + ) + if isProbe { result := 1 } + mstore(0, result) + return(0, 0x20) + } + } +} + +/// @author taek +/// @notice Halmos proofs for P256Validator and P256Signer lifecycle, storage scoping, and +/// stateless-dispatch correctness. +/// +/// TCB / MODELING: the production module bytecode, P256Validation public-key gate, Solady +/// low-s check, and storage accesses execute unchanged. Only the native +/// verifier at address(0x100) is modeled as a deterministic boolean oracle. These properties +/// prove the module logic around the cryptographic boundary, not P-256 soundness itself. +contract P256ModuleHalmos is SymTest { + Vm internal constant vm = Vm(address(uint160(uint256(keccak256("hevm cheat code"))))); + + address internal constant PRECOMPILE = address(0x100); + address internal constant CALLER = address(0xCA11); + address internal constant OTHER = address(0xB0B); + bytes32 internal constant ID = bytes32(uint256(0x1234)); + bytes32 internal constant OTHER_ID = bytes32(uint256(0x5678)); + + uint256 internal constant GX = 0x6B17D1F2E12C4247F8BCE6E563A440F277037D812DEB33A0F4A13945D898C296; + uint256 internal constant GY = 0x4FE342E2FE1A7F9B8EE7EB4A7C0F9E162BCE33576B315ECECBB6406837BF51F5; + uint256 internal constant N = 0xFFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC632551; + uint256 internal constant HALF_N = N / 2; + + bytes4 internal constant ALREADY_INITIALIZED = bytes4(keccak256("AlreadyInitialized(address)")); + bytes4 internal constant NOT_INITIALIZED = bytes4(keccak256("NotInitialized(address)")); + bytes4 internal constant INVALID_DATA_LENGTH = bytes4(keccak256("InvalidDataLength()")); + bytes4 internal constant INVALID_PUBLIC_KEY = bytes4(keccak256("InvalidPublicKey()")); + + P256Validator internal validator; + P256Signer internal signer; + + function setUp() external { + // Both production constructors only probe address(0x100). Etching runtime code after + // installing the modeled precompile is state-equivalent to a successful deployment. + P256PrecompileHalmosStub stub = + P256PrecompileHalmosStub(address(uint160(uint256(keccak256("P256PrecompileHalmosStub"))))); + vm.etch(address(stub), type(P256PrecompileHalmosStub).runtimeCode); + vm.etch(PRECOMPILE, address(stub).code); + + validator = P256Validator(address(uint160(uint256(keccak256("P256Validator"))))); + vm.etch(address(validator), type(P256Validator).runtimeCode); + + signer = P256Signer(address(uint160(uint256(keccak256("P256Signer"))))); + vm.etch(address(signer), type(P256Signer).runtimeCode); + } + + function _setOracle(bool result) internal { + vm.store(PRECOMPILE, bytes32(0), bytes32(uint256(result ? 1 : 0))); + } + + function _key() internal pure returns (bytes memory) { + return abi.encode(GX, GY); + } + + function _signerInstallData(bytes32 id) internal pure returns (bytes memory) { + return abi.encodePacked(id, abi.encode(GX, GY)); + } + + function _signature(uint256 r, uint256 s) internal pure returns (bytes memory) { + return abi.encode(bytes32(r), bytes32(s)); + } + + function _selector(bytes memory returndata) internal pure returns (bytes4 result) { + if (returndata.length >= 4) { + assembly ("memory-safe") { + result := mload(add(returndata, 0x20)) + } + } + } + + // ============================================================================================= + // LIFECYCLE AND STORAGE SEPARATION + // ============================================================================================= + + function check_Validator_lifecycleAndAccountSeparation() external { + vm.prank(CALLER); + validator.onInstall(_key()); + + (uint256 x, uint256 y) = validator.p256ValidatorStorage(CALLER); + assert(x == GX && y == GY); + assert(validator.isInitialized(CALLER)); + + (uint256 otherX, uint256 otherY) = validator.p256ValidatorStorage(OTHER); + assert(otherX == 0 && otherY == 0); + assert(!validator.isInitialized(OTHER)); + + vm.prank(CALLER); + validator.onUninstall(""); + (x, y) = validator.p256ValidatorStorage(CALLER); + assert(x == 0 && y == 0); + assert(!validator.isInitialized(CALLER)); + } + + function check_Validator_lifecycleGuards() external { + vm.prank(CALLER); + (bool ok, bytes memory ret) = address(validator).call(abi.encodeCall(validator.onInstall, (hex"01"))); + assert(!ok && _selector(ret) == INVALID_DATA_LENGTH); + + vm.prank(CALLER); + (ok, ret) = address(validator).call(abi.encodeCall(validator.onInstall, (abi.encode(uint256(0), uint256(0))))); + assert(!ok && _selector(ret) == INVALID_PUBLIC_KEY); + + vm.prank(CALLER); + validator.onInstall(_key()); + vm.prank(CALLER); + (ok, ret) = address(validator).call(abi.encodeCall(validator.onInstall, (_key()))); + assert(!ok && _selector(ret) == ALREADY_INITIALIZED); + + vm.prank(OTHER); + (ok, ret) = address(validator).call(abi.encodeCall(validator.onUninstall, (""))); + assert(!ok && _selector(ret) == NOT_INITIALIZED); + } + + function check_Signer_lifecycleAndKeySeparation() external { + vm.prank(CALLER); + signer.onInstall(_signerInstallData(ID)); + + (uint256 x, uint256 y) = signer.p256SignerStorage(ID, CALLER); + assert(x == GX && y == GY); + assert(signer.isInitialized(ID, CALLER)); + + (uint256 otherAccountX, uint256 otherAccountY) = signer.p256SignerStorage(ID, OTHER); + assert(otherAccountX == 0 && otherAccountY == 0); + (uint256 otherIdX, uint256 otherIdY) = signer.p256SignerStorage(OTHER_ID, CALLER); + assert(otherIdX == 0 && otherIdY == 0); + + vm.prank(CALLER); + signer.onUninstall(abi.encodePacked(ID)); + (x, y) = signer.p256SignerStorage(ID, CALLER); + assert(x == 0 && y == 0); + assert(!signer.isInitialized(ID, CALLER)); + } + + function check_Signer_lifecycleGuards() external { + vm.prank(CALLER); + (bool ok, bytes memory ret) = + address(signer).call(abi.encodeCall(signer.onInstall, (abi.encodePacked(ID, hex"01")))); + assert(!ok && _selector(ret) == INVALID_DATA_LENGTH); + + vm.prank(CALLER); + (ok, ret) = address(signer) + .call(abi.encodeCall(signer.onInstall, (abi.encodePacked(ID, abi.encode(uint256(0), uint256(0)))))); + assert(!ok && _selector(ret) == INVALID_PUBLIC_KEY); + + vm.prank(CALLER); + signer.onInstall(_signerInstallData(ID)); + vm.prank(CALLER); + (ok, ret) = address(signer).call(abi.encodeCall(signer.onInstall, (_signerInstallData(ID)))); + assert(!ok && _selector(ret) == ALREADY_INITIALIZED); + + vm.prank(CALLER); + (ok, ret) = address(signer).call(abi.encodeCall(signer.onUninstall, (abi.encodePacked(OTHER_ID)))); + assert(!ok && _selector(ret) == NOT_INITIALIZED); + } + + // ============================================================================================= + // STATELESS ORACLE PLUMBING AND LOCAL GATES + // ============================================================================================= + + function check_StatelessOraclePlumbing( + bytes32 hash, + uint256 r, + uint256 s, + bool oracleResult, + address requestingProtocol + ) external { + vm.assume(r > 0 && r < N); + vm.assume(s > 0 && s <= HALF_N); + _setOracle(oracleResult); + + bytes memory signature = _signature(r, s); + bytes memory key = _key(); + + bool validatorDirect = validator.validateSignatureWithData(hash, signature, key); + bool validatorWithSender = + validator.validateSignatureWithDataWithSender(requestingProtocol, hash, signature, key); + bool signerDirect = signer.validateSignatureWithData(hash, signature, key); + bool signerWithSender = signer.validateSignatureWithDataWithSender(requestingProtocol, hash, signature, key); + + assert(validatorDirect == oracleResult); + assert(validatorWithSender == oracleResult); + assert(signerDirect == oracleResult); + assert(signerWithSender == oracleResult); + } + + function check_StatelessLocalGuards(bytes32 hash) external { + _setOracle(true); + bytes memory validSignature = _signature(1, 1); + bytes memory validKey = _key(); + + assert(!validator.validateSignatureWithData(hash, validSignature, hex"01")); + assert(!signer.validateSignatureWithData(hash, validSignature, hex"01")); + + bytes memory invalidKey = abi.encode(uint256(0), uint256(0)); + assert(!validator.validateSignatureWithData(hash, validSignature, invalidKey)); + assert(!signer.validateSignatureWithData(hash, validSignature, invalidKey)); + + assert(!validator.validateSignatureWithData(hash, hex"01", validKey)); + assert(!signer.validateSignatureWithData(hash, hex"01", validKey)); + + bytes memory highSSignature = _signature(1, HALF_N + 1); + assert(!validator.validateSignatureWithData(hash, highSSignature, validKey)); + assert(!signer.validateSignatureWithData(hash, highSSignature, validKey)); + } + + function check_StatelessIgnoresInstalledState(bytes32 hash, bool oracleResult) external { + _setOracle(oracleResult); + bytes memory signature = _signature(1, 1); + bytes memory key = _key(); + + bool validatorBefore = validator.validateSignatureWithData(hash, signature, key); + bool signerBefore = signer.validateSignatureWithData(hash, signature, key); + + vm.prank(CALLER); + validator.onInstall(_key()); + vm.prank(CALLER); + signer.onInstall(_signerInstallData(ID)); + + bool validatorAfter = validator.validateSignatureWithData(hash, signature, key); + bool signerAfter = signer.validateSignatureWithData(hash, signature, key); + + assert(validatorBefore == validatorAfter); + assert(signerBefore == signerAfter); + assert(validatorAfter == signerAfter); + } + + // ============================================================================================= + // STATEFUL STORAGE GATES + // ============================================================================================= + + function check_StatefulValidationUsesOnlyScopedKey(bytes32 hash, bool oracleResult) external { + _setOracle(oracleResult); + bytes memory signature = _signature(1, 1); + PackedUserOperation memory userOp; + userOp.signature = signature; + + vm.prank(CALLER); + validator.onInstall(_key()); + vm.prank(CALLER); + signer.onInstall(_signerInstallData(ID)); + + vm.prank(CALLER); + uint256 validatorConfigured = validator.validateUserOp(userOp, hash); + assert(validatorConfigured == (oracleResult ? SIG_VALIDATION_SUCCESS_UINT : SIG_VALIDATION_FAILED_UINT)); + + vm.prank(OTHER); + assert(validator.validateUserOp(userOp, hash) == SIG_VALIDATION_FAILED_UINT); + + vm.prank(CALLER); + uint256 signerConfigured = signer.checkUserOpSignature(ID, userOp, hash); + assert(signerConfigured == (oracleResult ? SIG_VALIDATION_SUCCESS_UINT : SIG_VALIDATION_FAILED_UINT)); + + vm.prank(CALLER); + assert(signer.checkUserOpSignature(OTHER_ID, userOp, hash) == SIG_VALIDATION_FAILED_UINT); + vm.prank(OTHER); + assert(signer.checkUserOpSignature(ID, userOp, hash) == SIG_VALIDATION_FAILED_UINT); + + vm.prank(OTHER); + assert(validator.isValidSignatureWithSender(address(0), hash, signature) == ERC1271_INVALID); + vm.prank(OTHER); + assert(signer.checkSignature(ID, address(0), hash, signature) == ERC1271_INVALID); + } + + // ============================================================================================= + // NON-VACUITY WITNESSES (counterexamples expected) + // ============================================================================================= + + function check_StatelessAcceptReachable(bytes32 hash) external { + _setOracle(true); + bool result = validator.validateSignatureWithData(hash, _signature(1, 1), _key()); + assert(!result); + } + + function check_StatelessRejectReachable(bytes32 hash) external { + _setOracle(false); + bool result = signer.validateSignatureWithData(hash, _signature(1, 1), _key()); + assert(result); + } +} diff --git a/test/halmos/RateLimitPolicyHalmos.t.sol b/test/halmos/RateLimitPolicyHalmos.t.sol new file mode 100644 index 0000000..1501ca8 --- /dev/null +++ b/test/halmos/RateLimitPolicyHalmos.t.sol @@ -0,0 +1,127 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import {StdAssertions} from "forge-std/StdAssertions.sol"; +import {Vm} from "forge-std/Vm.sol"; +import {SymTest} from "halmos-cheatcodes/SymTest.sol"; +import {PackedUserOperation} from "account-abstraction/interfaces/PackedUserOperation.sol"; +import {RateLimitPolicy} from "src/policies/RateLimitPolicy.sol"; + +/// @author taek +/// @notice Halmos proof for RateLimitPolicy: storedCount never exceeds the configured initialCount cap. +/// @dev Inherits StdAssertions (not Test) — forge-std 1.11 Test.setUp triggers an unsupported +/// deployCode cheatcode under halmos 0.3.3, aborting every path in setUp(). +/// The contract-under-test is placed via `vm.etch(runtimeCode)` rather than `new`: under +/// foundry nightly 1.7.2 halmos 0.3.3 lowers `new C()` to the unsupported deployCode(string) +/// cheatcode, and raw CREATE hits an artifact-path mismatch. RateLimitPolicy has an empty +/// constructor (no immutables / no ctor state), so etching runtime code is behaviorally identical. +contract RateLimitPolicyHalmos is SymTest, StdAssertions { + // hevm cheat-code address; StdAssertions declares its own `vm` privately, so redeclare here. + Vm internal constant vm = Vm(address(uint160(uint256(keccak256("hevm cheat code"))))); + + RateLimitPolicy internal constant policy = RateLimitPolicy(address(0xBEEF)); + + function setUp() external { + vm.etch(address(policy), type(RateLimitPolicy).runtimeCode); + } + + // Installs a Live config with symbolic interval/initialCount for `id`, sender = this harness. + function _install(bytes32 id, uint48 interval, uint48 initialCount) internal { + policy.onInstall(abi.encodePacked(id, interval, initialCount)); + } + + function _emptyOp() internal pure returns (PackedUserOperation memory op) {} + + function _initialCount(bytes32 id) internal view returns (uint48) { + (, uint48 initialCount) = policy.rateLimitConfigs(id, address(this)); + return initialCount; + } + + function _storedCount(bytes32 id) internal view returns (uint48) { + (uint48 storedCount,) = policy.rateLimitState(id, address(this)); + return storedCount; + } + + // storage slot of rateLimitState[id][address(this)]. + // rateLimitState is the 3rd declared mapping in RateLimitPolicy => base slot 2 (confirmed via forge inspect). + function _stateSlot(bytes32 id) internal view returns (bytes32) { + bytes32 inner = keccak256(abi.encode(id, uint256(2))); + return keccak256(abi.encode(address(this), inner)); + } + + /// @notice (A) INDUCTIVE INVARIANT: if the pre-state already respects the cap + /// (storedCount <= initialCount), then after checkUserOpPolicy the cap still holds, + /// for any symbolic block.timestamp. The reset branch writes exactly initialCount and + /// the no-reset branch only decrements, so neither branch can exceed the cap. + /// @dev Symbolic pre-state: after install we overwrite storedCount/resetDate with fresh symbolic + /// values (an ARBITRARY state, not just the freshly-installed one). The cap is the loop + /// invariant of every reachable trace: storedCount is only ever written to `initialCount` + /// (install/reset) then decremented, so `preStored <= initialCount` is the exact inductive + /// hypothesis — it is a precondition of every reachable pre-state, NOT a weakening. (A run + /// without it produces the expected counterexample of a fabricated storedCount > initialCount, + /// which is not a reachable state.) + function check_StoredCountNeverExceedsCap( + bytes32 id, + uint48 interval, + uint48 initialCount, + uint48 preStored, + uint48 preReset + ) external { + // install to make config Live, then plant an arbitrary state respecting the inductive hypothesis + _install(id, interval, initialCount); + vm.assume(preStored <= initialCount); // inductive hypothesis: cap held in the pre-state + vm.store(address(policy), _stateSlot(id), bytes32((uint256(preReset) << 48) | uint256(preStored))); + // sanity: the plant round-trips (guards against a slot-layout mistake making this vacuous) + require(_storedCount(id) == preStored); + + policy.checkUserOpPolicy(id, _emptyOp()); + + // Single load-bearing assertion: stored <= config cap (observable storage <= config field). + assertLe(uint256(_storedCount(id)), uint256(_initialCount(id))); + } + + // ---- Reachability / non-vacuity witnesses (must produce counterexamples) ---- + + /// @notice Witness (i) — BUDGET GATE is live (supports claim B): a same-window sequence that + /// exhausts the budget reverts RateLimited() on the exhausting call. With initialCount==1 + /// and no reset crossing, the first call is accepted and the second reverts. Proving the + /// second call NEVER reverts must fail, exposing the live reject path. + function check_BudgetGateReject_reachable(bytes32 id, uint48 interval) external { + vm.assume(block.timestamp <= type(uint48).max); + uint48 now48 = uint48(block.timestamp); + // stay inside one window on the second call: resetDate stays in the future. + vm.assume(uint256(now48) + uint256(interval) <= type(uint48).max); + + _install(id, interval, 1); // budget of exactly one, resetDate = now + interval + + policy.checkUserOpPolicy(id, _emptyOp()); // first: accepted, stored 1 -> 0 + + // second call: now < resetDate (same window) so no refill, stored==0 -> must revert + try policy.checkUserOpPolicy(id, _emptyOp()) returns (uint256) { + assertTrue(true); // non-reverting path + } catch { + assertTrue(false); // fails => a reverting model exists => gate is reachable + } + } + + /// @notice Witness (ii) — RESET LIVENESS is live (supports claim C): a call with now >= resetDate + /// refills storedCount to initialCount. Starting from a drained/expired state, the call + /// must refill. Proving stored != initialCount-1 after the refill+decrement must fail, + /// exposing the live reset path. + function check_ResetRefill_reachable(bytes32 id, uint48 interval, uint48 initialCount) external { + vm.assume(initialCount > 0); + vm.assume(block.timestamp <= type(uint48).max); + uint48 now48 = uint48(block.timestamp); + vm.assume(uint256(now48) + uint256(interval) <= type(uint48).max); // reset push no overflow + + _install(id, interval, initialCount); + // drain and expire: stored==0, resetDate==0 (<= now) => next call crosses the reset. + vm.store(address(policy), _stateSlot(id), bytes32(uint256(0))); + + policy.checkUserOpPolicy(id, _emptyOp()); // crosses reset: refill to initialCount, then -- + + // reset is live iff a model exists where the refill happened (stored == initialCount - 1); + // assert it never does to expose the reachable refill path. + assertNotEq(uint256(_storedCount(id)), uint256(initialCount - 1)); + } +} diff --git a/test/halmos/ThrottlePolicyHalmos.t.sol b/test/halmos/ThrottlePolicyHalmos.t.sol new file mode 100644 index 0000000..3651a77 --- /dev/null +++ b/test/halmos/ThrottlePolicyHalmos.t.sol @@ -0,0 +1,96 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import {Test} from "forge-std/Test.sol"; +import {SymTest} from "halmos-cheatcodes/SymTest.sol"; +import {PackedUserOperation} from "account-abstraction/interfaces/PackedUserOperation.sol"; +import {ThrottlePolicy} from "src/policies/ThrottlePolicy.sol"; +import {ValidAfter} from "src/types/Types.sol"; +import {SIG_VALIDATION_FAILED_UINT} from "src/types/Constants.sol"; + +/// @author taek +/// @notice Halmos proofs for ThrottlePolicy anchoring. +contract ThrottlePolicyHalmos is SymTest, Test { + ThrottlePolicy policy; + + function setUp() external { + // Deploy via etch of deployed bytecode: halmos 0.3.3 + foundry-nightly can route `new` + // through the unsupported deployCode(string) cheat, so avoid CREATE. ThrottlePolicy has no + // constructor state, so etching the runtime code is a faithful deployment. + policy = ThrottlePolicy(address(0xACE)); + vm.etch(address(policy), _throttleRuntime()); + } + + function _throttleRuntime() internal returns (bytes memory) { + // deployedBytecode of ThrottlePolicy (out/ThrottlePolicy.sol/ThrottlePolicy.json). + return type(ThrottlePolicy).runtimeCode; + } + + // Installs a Live config with symbolic interval/count/startAt for `id`, sender = this harness. + function _install(bytes32 id, uint48 interval, uint48 count, uint48 startAt) internal { + policy.onInstall(abi.encodePacked(id, interval, count, startAt)); + } + + function _emptyOp() internal pure returns (PackedUserOperation memory op) {} + + /// @notice ANCHOR (A): after an accepted checkUserOpPolicy the STORED next startAt equals + /// max(now, oldStartAt) + interval — an idle gap (now > oldStartAt) is NOT banked. + function check_AnchorNextSlotToNow(bytes32 id, uint48 interval, uint48 count, uint48 startAt) external { + vm.assume(count > 0); + // block.timestamp is symbolic; keep the uint48 cast faithful (no silent truncation). + vm.assume(block.timestamp <= type(uint48).max); + uint48 now48 = uint48(block.timestamp); + uint48 anchored = now48 > startAt ? now48 : startAt; + // interval chosen so anchored + interval does not overflow uint48 (dispatch precondition). + vm.assume(uint256(anchored) + uint256(interval) <= type(uint48).max); + + _install(id, interval, count, startAt); + + uint256 ret = policy.checkUserOpPolicy(id, _emptyOp()); + vm.assume(ret != SIG_VALIDATION_FAILED_UINT); // accepted op only + + (,, ValidAfter newStartAt) = policy.throttleConfigs(id, address(this)); + // Single load-bearing assertion: the stored slot is anchored to max(now, oldStartAt). + assertEq(ValidAfter.unwrap(newStartAt), anchored + interval); + } + + // ---- Reachability / non-vacuity witnesses (must produce counterexamples) ---- + + /// @notice Witness (i): the IDLE branch is live — a state where now > oldStartAt and the + /// stored slot becomes now + interval exists. Asserting false must fail. + function check_AnchorNextSlotToNow_reachable(bytes32 id, uint48 interval, uint48 count, uint48 startAt) external { + vm.assume(count > 0); + vm.assume(block.timestamp <= type(uint48).max); + uint48 now48 = uint48(block.timestamp); + vm.assume(now48 > startAt); // force the idle-gap branch specifically + vm.assume(uint256(now48) + uint256(interval) <= type(uint48).max); + + _install(id, interval, count, startAt); + uint256 ret = policy.checkUserOpPolicy(id, _emptyOp()); + vm.assume(ret != SIG_VALIDATION_FAILED_UINT); + + (,, ValidAfter newStartAt) = policy.throttleConfigs(id, address(this)); + // Path is live iff a model exists with newStartAt == now + interval: assert false to expose it. + assertNotEq(ValidAfter.unwrap(newStartAt), now48 + interval); + } + + /// @notice Witness (ii): the BUDGET gate is live — a config with count==1 exists whose next + /// call (count now 0) returns FAILED. Asserting the terminal reject never happens must fail. + function check_BudgetGateReject_reachable(bytes32 id, uint48 interval, uint48 startAt) external { + vm.assume(block.timestamp <= type(uint48).max); + uint48 now48 = uint48(block.timestamp); + uint48 anchored = now48 > startAt ? now48 : startAt; + vm.assume(uint256(anchored) + uint256(interval) <= type(uint48).max); + + _install(id, interval, 1, startAt); // budget of exactly one + + // first op accepted, decrements count 1 -> 0 + uint256 first = policy.checkUserOpPolicy(id, _emptyOp()); + vm.assume(first != SIG_VALIDATION_FAILED_UINT); + + // second op must hit the count==0 gate + uint256 second = policy.checkUserOpPolicy(id, _emptyOp()); + // Reject is live iff a model exists with second == FAILED: assert it never does to expose it. + assertNotEq(second, SIG_VALIDATION_FAILED_UINT); + } +} diff --git a/test/halmos/TimelockCancelAuthHalmos.t.sol b/test/halmos/TimelockCancelAuthHalmos.t.sol new file mode 100644 index 0000000..e185b23 --- /dev/null +++ b/test/halmos/TimelockCancelAuthHalmos.t.sol @@ -0,0 +1,154 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import {Test} from "forge-std/Test.sol"; +import {SymTest} from "halmos-cheatcodes/SymTest.sol"; +import {TimelockPolicy} from "src/policies/TimelockPolicy.sol"; + +/// @author taek +/// @notice Halmos proof: guardian is cancellation-only, per-account scoped. +/// @dev Property: cancelProposal's auth gate (TimelockPolicy.sol:152) passes IFF +/// msg.sender == account OR (guardian != 0 && msg.sender == guardian) +/// where guardian is read per (id, account) from timelockConfig[id][account].guardian (:151). +/// Any other caller reverts OnlyAccount. This is the observable revert-vs-pass of the auth +/// gate — asserted against the authorization predicate in BOTH directions (:154-167 is only +/// reachable when the gate passes; a Pending proposal is seeded so the pass path does not +/// immediately hit ProposalNotPending at :161). +contract TimelockCancelAuthHalmos is SymTest, Test { + TimelockPolicy policy; + + function setUp() external { + // Etch runtime code: halmos 0.3.3 cannot route `new` through deployCode. Empty ctor state. + policy = TimelockPolicy(address(0xACE)); + vm.etch(address(policy), type(TimelockPolicy).runtimeCode); + } + + // proposals slot = 2. base = keccak(account, keccak(id, keccak(userOpKey, 2))). + // Proposal packs {status(uint8), validAfter(uint48), validUntil(uint48)} into base slot; + // epoch(uint256) into base+1. Writing base = 1 => status = Pending, rest zero. + function _seedPending(bytes32 userOpKey, bytes32 id, address account) internal { + bytes32 s1 = keccak256(abi.encode(userOpKey, uint256(2))); + bytes32 s2 = keccak256(abi.encode(id, s1)); + bytes32 base = keccak256(abi.encode(account, s2)); + vm.store(address(policy), base, bytes32(uint256(1))); // ProposalStatus.Pending == 1 + } + + // Install config for `account` (sets initialized=true and guardian) by pranking as account. + function _install(bytes32 id, address account, address guardian) internal { + bytes memory data = abi.encodePacked(id, abi.encode(uint48(1), uint48(1), guardian)); + vm.prank(account); + policy.onInstall(data); + } + + // The authorization predicate exactly as coded at :152 (negated -> revert). + function _authorized(address caller, address account, address guardian) internal pure returns (bool) { + return caller == account || (guardian != address(0) && caller == guardian); + } + + /// @notice cancelProposal reverts OnlyAccount IFF the caller is not authorized, i.e. it succeeds + /// (proposal -> Cancelled) exactly when msg.sender==account OR (guardian!=0 && + /// msg.sender==guardian) for that per-account config. One boolean: revert-iff-unauthorized. + function check_CancelAuthGate( + bytes32 id, + address account, + address caller, + address guardian, + bytes calldata callData, + uint256 nonce + ) external { + // account must be able to install (guard at :101 needs a fresh, non-etch-address account is fine). + vm.assume(account != address(policy)); + _install(id, account, guardian); + + // Seed a Pending proposal for the exact key cancelProposal computes, so an authorized caller + // reaches the Cancelled write (:165) instead of ProposalNotPending (:161). + bytes32 userOpKey = keccak256(abi.encode(account, keccak256(callData), nonce)); + _seedPending(userOpKey, id, account); + + bool wantAuth = _authorized(caller, account, guardian); + + vm.prank(caller); + try policy.cancelProposal(id, account, callData, nonce) { + // Success path is reachable ONLY when the auth gate passed. + assertTrue(wantAuth); + } catch (bytes memory reason) { + // Must be OnlyAccount() and only when unauthorized. + assertEq(bytes4(reason), TimelockPolicy.OnlyAccount.selector); + assertFalse(wantAuth); + } + } + + // ---- Reachability / non-vacuity witnesses (each MUST produce a counterexample) ---- + + /// @notice Witness: the ACCOUNT-caller pass path is live (msg.sender==account -> Cancelled). + /// Assert it never succeeds to expose a live model. + function check_CancelAuthGate_reachable_account( + bytes32 id, + address account, + address guardian, + bytes calldata callData, + uint256 nonce + ) external { + vm.assume(account != address(policy)); + _install(id, account, guardian); + bytes32 userOpKey = keccak256(abi.encode(account, keccak256(callData), nonce)); + _seedPending(userOpKey, id, account); + + vm.prank(account); + policy.cancelProposal(id, account, callData, nonce); + // Live iff a model exists where account-caller cancels: getter shows Cancelled(3). + (TimelockPolicy.ProposalStatus status,,) = policy.getProposal(account, callData, nonce, id, account); + assertTrue(status != TimelockPolicy.ProposalStatus.Cancelled); + } + + /// @notice Witness: the GUARDIAN-caller pass path is live (guardian!=0, msg.sender==guardian, + /// guardian!=account -> Cancelled). Assert it never succeeds to expose a live model. + function check_CancelAuthGate_reachable_guardian( + bytes32 id, + address account, + address guardian, + bytes calldata callData, + uint256 nonce + ) external { + vm.assume(account != address(policy)); + vm.assume(guardian != address(0)); + vm.assume(guardian != account); + _install(id, account, guardian); + bytes32 userOpKey = keccak256(abi.encode(account, keccak256(callData), nonce)); + _seedPending(userOpKey, id, account); + + vm.prank(guardian); + policy.cancelProposal(id, account, callData, nonce); + (TimelockPolicy.ProposalStatus status,,) = policy.getProposal(account, callData, nonce, id, account); + assertTrue(status != TimelockPolicy.ProposalStatus.Cancelled); + } + + /// @notice Witness: the UNAUTHORIZED-revert path is live (caller != account, and either no + /// guardian or caller != guardian -> OnlyAccount). Assert cancel always succeeds to + /// expose the reverting model. + function check_CancelAuthGate_reachable_revert( + bytes32 id, + address account, + address caller, + address guardian, + bytes calldata callData, + uint256 nonce + ) external { + vm.assume(account != address(policy)); + vm.assume(caller != account); + vm.assume(guardian == address(0) || caller != guardian); + _install(id, account, guardian); + bytes32 userOpKey = keccak256(abi.encode(account, keccak256(callData), nonce)); + _seedPending(userOpKey, id, account); + + vm.prank(caller); + // Live iff a model exists that reaches the OnlyAccount revert: assert-false in the catch + // yields a counterexample, proving the unauthorized-revert path is reachable. + try policy.cancelProposal(id, account, callData, nonce) { + assertTrue(true); + } catch (bytes memory reason) { + assertEq(bytes4(reason), TimelockPolicy.OnlyAccount.selector); + assertFalse(true); + } + } +} diff --git a/test/halmos/TimelockExecWindowHalmos.t.sol b/test/halmos/TimelockExecWindowHalmos.t.sol new file mode 100644 index 0000000..09090bf --- /dev/null +++ b/test/halmos/TimelockExecWindowHalmos.t.sol @@ -0,0 +1,134 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import {Test} from "forge-std/Test.sol"; +import {SymTest} from "halmos-cheatcodes/SymTest.sol"; +import {TimelockPolicy} from "src/policies/TimelockPolicy.sol"; +import {PackedUserOperation} from "account-abstraction/interfaces/PackedUserOperation.sol"; + +/// @author taek +/// @notice Halmos proof: executing a Pending, current-epoch TimelockPolicy proposal returns an +/// ERC-4337 packed validation window whose high 48 bits == the STORED proposal.validAfter, +/// next 48 bits == the STORED proposal.validUntil, and low 160 bits (authorizer) == 0 (success). +/// @dev Property source: TimelockPolicy._handleProposalExecutionInternal returns +/// _packValidationData(proposal.validAfter, proposal.validUntil) (L263); layout at +/// _packValidationData (L342-344). The proposal is created through the REAL no-op creation +/// path so the stored validAfter/validUntil are genuine (creation stamps L214-215). +/// The assertion reads the STORED fields via the public getProposal getter (not a recompute +/// of block.timestamp+delay), then compares the extracted bitfields of the returned packed +/// value against them — the packing layout is the contract's public ABI to the EntryPoint. +/// DISCLOSED ASSUMPTION: no uint48 wrap at creation. The install-time guard (L108) +/// already enforces delay+expirationPeriod <= uint48.max - block.timestamp; that guard is the +/// only overflow check and it is NOT re-evaluated at execution — we keep it satisfiable at +/// creation, which is exactly that window. +contract TimelockExecWindowHalmos is SymTest, Test { + TimelockPolicy policy; + + // The (id, account) pair. account == address(this) is the caller of checkUserOpPolicy, + // which becomes both userOp.sender and the storage account key. + bytes32 constant ID = bytes32(uint256(0x7e10c0)); + + function setUp() external { + // Etch runtime code to avoid halmos-0.3.3 routing `new` through deployCode. No constructor state. + policy = TimelockPolicy(address(0xACE)); + vm.etch(address(policy), type(TimelockPolicy).runtimeCode); + } + + function _installData(uint48 delay, uint48 expirationPeriod, address guardian) + internal + pure + returns (bytes memory) + { + return abi.encodePacked(ID, abi.encode(delay, expirationPeriod, guardian)); + } + + // A UserOp with empty callData is a no-op => routes to proposal CREATION. + // The signature carries the proposal payload: [callDataLength(32)][callData][nonce(32)]. + function _creationUserOp(bytes memory execCallData, uint256 proposalNonce) + internal + view + returns (PackedUserOperation memory op) + { + op.sender = address(this); + op.nonce = 0; + op.callData = ""; // no-op => creation branch + op.signature = abi.encodePacked(uint256(execCallData.length), execCallData, proposalNonce); + } + + // A UserOp with real (non-no-op) callData + matching nonce => routes to EXECUTION of the + // proposal keyed by keccak(sender, keccak(callData), nonce). + function _executionUserOp(bytes memory execCallData, uint256 proposalNonce) + internal + view + returns (PackedUserOperation memory op) + { + op.sender = address(this); + op.nonce = proposalNonce; + op.callData = execCallData; + op.signature = ""; + } + + /// @notice The exact window the EntryPoint reads: executing a live Pending/current-epoch proposal + /// returns _packValidationData(storedValidAfter, storedValidUntil) with success authorizer==0. + /// Single load-bearing assertion: the three extracted bitfields all match the stored state. + function check_ExecReturnsStoredWindow(uint48 delay, uint48 expirationPeriod, uint256 proposalNonce) external { + // ---- Preconditions (genuine): install guard must be satisfiable so config is valid. ---- + vm.assume(delay > 0); + vm.assume(expirationPeriod > 0); + vm.assume(block.timestamp <= type(uint48).max); + // No-uint48-wrap-at-creation window (identical to the install guard, L108): + vm.assume(uint256(delay) + uint256(expirationPeriod) <= uint256(type(uint48).max) - block.timestamp); + + // A concrete, non-no-op execution calldata (a plain 4-byte selector is NOT a recognized no-op). + bytes memory execCallData = hex"11223344"; + + policy.onInstall(_installData(delay, expirationPeriod, address(0))); + + // Create the proposal (Pending, current epoch) via the real creation path. + policy.checkUserOpPolicy(ID, _creationUserOp(execCallData, proposalNonce)); + + // Read the STORED window (public getter) BEFORE execution mutates status. + (, uint256 storedValidAfter, uint256 storedValidUntil) = + policy.getProposal(address(this), execCallData, proposalNonce, ID, address(this)); + + // Execute the proposal. + uint256 packed = policy.checkUserOpPolicy(ID, _executionUserOp(execCallData, proposalNonce)); + + // Extract ERC-4337 bitfields. + uint256 retValidAfter = packed >> 208; // bits 208-255 + uint256 retValidUntil = (packed >> 160) & type(uint48).max; // bits 160-207 + uint256 authorizer = packed & ((uint256(1) << 160) - 1); // bits 0-159 + + // One property: returned window == stored window AND success (authorizer == 0). + assertTrue(retValidAfter == storedValidAfter && retValidUntil == storedValidUntil && authorizer == 0); + } + + // ---- Reachability / non-vacuity witness (MUST produce a counterexample) ---- + + /// @notice Witness: a real Pending/current-epoch proposal with validUntil > validAfter is created + /// and executed to a SUCCESS leaf (authorizer bits == 0). Asserting that never happens must + /// yield a counterexample — proving the executed-window path is live (non-vacuous). + function check_ExecReturnsStoredWindow_reachable(uint48 delay, uint48 expirationPeriod, uint256 proposalNonce) + external + { + vm.assume(delay > 0); + vm.assume(expirationPeriod > 0); + vm.assume(block.timestamp <= type(uint48).max); + vm.assume(uint256(delay) + uint256(expirationPeriod) <= uint256(type(uint48).max) - block.timestamp); + + bytes memory execCallData = hex"11223344"; + + policy.onInstall(_installData(delay, expirationPeriod, address(0))); + policy.checkUserOpPolicy(ID, _creationUserOp(execCallData, proposalNonce)); + + (, uint256 storedValidAfter, uint256 storedValidUntil) = + policy.getProposal(address(this), execCallData, proposalNonce, ID, address(this)); + + uint256 packed = policy.checkUserOpPolicy(ID, _executionUserOp(execCallData, proposalNonce)); + uint256 authorizer = packed & ((uint256(1) << 160) - 1); + + // Live iff a model exists where: proposal window is strictly ordered (validUntil > validAfter) + // AND execution succeeded (authorizer == 0). Assert the negation to expose the live path. + assertFalse(storedValidUntil > storedValidAfter && authorizer == 0); + } +} diff --git a/test/halmos/TimelockInitFlagHalmos.t.sol b/test/halmos/TimelockInitFlagHalmos.t.sol new file mode 100644 index 0000000..d6ffe54 --- /dev/null +++ b/test/halmos/TimelockInitFlagHalmos.t.sol @@ -0,0 +1,88 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import {Test} from "forge-std/Test.sol"; +import {SymTest} from "halmos-cheatcodes/SymTest.sol"; +import {TimelockPolicy} from "src/policies/TimelockPolicy.sol"; + +/// @author taek +/// @notice Halmos proof for TimelockPolicy install/uninstall init-flag round-trip (^req-20/^req-21). +/// @dev Target rebinding: the dispatch referenced a generic ERC-7579 module template +/// (`initialized[msg.sender]` at L79/L93, an `Initialized` emit). No such file exists here. +/// The concrete guard with the same error selectors (`IModule.AlreadyInitialized` / +/// `IModule.NotInitialized`) lives in TimelockPolicy._policyOninstall (L101) and +/// _policyOnUninstall (L125). The observable flag is `timelockConfig[id][account].initialized`; +/// the config-set path (the template's `Initialized` emit) is `TimelockConfigUpdated` at L118. +contract TimelockInitFlagHalmos is SymTest, Test { + TimelockPolicy policy; + + function setUp() external { + // Etch runtime code to avoid halmos-0.3.3 routing `new` through deployCode. No constructor state. + policy = TimelockPolicy(address(0xACE)); + vm.etch(address(policy), type(TimelockPolicy).runtimeCode); + } + + // onInstall entry: data = id(32) || abi.encode(delay, expirationPeriod, guardian) + function _installData(bytes32 id, uint48 delay, uint48 expirationPeriod, address guardian) + internal + pure + returns (bytes memory) + { + return abi.encodePacked(id, abi.encode(delay, expirationPeriod, guardian)); + } + + // onUninstall entry: data = id(32) || tail (tail unused by _policyOnUninstall) + function _uninstallData(bytes32 id) internal pure returns (bytes memory) { + return abi.encodePacked(id); + } + + function _initialized(bytes32 id) internal view returns (bool) { + (,,, bool init) = policy.timelockConfig(id, address(this)); + return init; + } + + // Precondition: keep the uint48 overflow guard (L108) satisfiable so onInstall can succeed. + function _validParams(uint48 delay, uint48 expirationPeriod) internal view { + vm.assume(delay > 0); + vm.assume(expirationPeriod > 0); + vm.assume(block.timestamp <= type(uint48).max); + vm.assume(uint256(delay) + uint256(expirationPeriod) <= uint256(type(uint48).max) - block.timestamp); + } + + /// @notice ROUND-TRIP IDEMPOTENCE (^req-20/^req-21): starting from an uninitialized (id, account), + /// onInstall sets the flag true and a following onUninstall restores it to false — the flag + /// returns to its pre-install value. Observable via the public timelockConfig getter, not a + /// recompute of the guard boolean. + function check_InitFlagRoundTrip(bytes32 id, uint48 delay, uint48 expirationPeriod, address guardian) external { + _validParams(delay, expirationPeriod); + // Precondition: (id, this) starts uninitialized (the fresh-install branch). + vm.assume(!_initialized(id)); + + policy.onInstall(_installData(id, delay, expirationPeriod, guardian)); + bool afterInstall = _initialized(id); + + policy.onUninstall(_uninstallData(id)); + bool afterUninstall = _initialized(id); + + // Single load-bearing assertion: install toggled true then uninstall toggled false. + // Encoded as one boolean so it is exactly one property (round-trip == install-set && uninstall-clear). + assertTrue(afterInstall && !afterUninstall); + } + + // ---- Reachability / non-vacuity witness (MUST produce a counterexample) ---- + + /// @notice Witness: the successful onInstall path (initialized false -> true, reaching the + /// TimelockConfigUpdated / config-set leaf) is LIVE. Asserting the post-install flag is + /// never true must fail — exposing a real model where install succeeds. + function check_InitFlagRoundTrip_reachable(bytes32 id, uint48 delay, uint48 expirationPeriod, address guardian) + external + { + _validParams(delay, expirationPeriod); + vm.assume(!_initialized(id)); + + policy.onInstall(_installData(id, delay, expirationPeriod, guardian)); + + // Live iff a model exists with the flag set post-install: assert it never is to expose it. + assertFalse(_initialized(id)); + } +} diff --git a/test/halmos/TimelockStaleEpochHalmos.t.sol b/test/halmos/TimelockStaleEpochHalmos.t.sol new file mode 100644 index 0000000..bd4d1bc --- /dev/null +++ b/test/halmos/TimelockStaleEpochHalmos.t.sol @@ -0,0 +1,121 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import {Test} from "forge-std/Test.sol"; +import {SymTest} from "halmos-cheatcodes/SymTest.sol"; +import {TimelockPolicy} from "src/policies/TimelockPolicy.sol"; +import {PackedUserOperation} from "account-abstraction/interfaces/PackedUserOperation.sol"; +import {SIG_VALIDATION_FAILED_UINT} from "src/types/Constants.sol"; + +/// @author taek +/// @notice Halmos proof (stale-proposal replay, epoch-mismatch leg): a proposal created under a +/// prior installation can NEVER validate for execution after reinstall. Concretely, +/// _handleProposalExecutionInternal (reached via checkUserOpPolicy with matching non-no-op +/// callData/nonce) returns SIG_VALIDATION_FAILED_UINT whenever proposal.epoch != +/// currentEpoch[id][account]. +/// @dev Property source: TimelockPolicy._policyOninstall bumps currentEpoch (L113 +/// `currentEpoch[id][msg.sender]++`); _handleProposalCreationInternal stamps proposal.epoch = +/// currentEpoch (L231); _handleProposalExecutionInternal rejects on mismatch (L256 +/// `if (proposal.epoch != currentEpoch[id][account]) return SIG_VALIDATION_FAILED_UINT`). +/// The stale cross-epoch state is produced through the REAL trace: install (epoch E) -> create +/// Pending proposal at epoch E -> uninstall -> reinstall (epoch E+1). The assertion checks the +/// OBSERVABLE return sentinel (== SIG_VALIDATION_FAILED_UINT), not a recompute of the epoch +/// counter. +/// DEPLOY: vm.etch of runtimeCode (empty ctor) — sound for halmos-0.3.3 which cannot route `new` +/// through deployCode. +contract TimelockStaleEpochHalmos is SymTest, Test { + TimelockPolicy policy; + + bytes32 constant ID = bytes32(uint256(0x7e10c0)); + + function setUp() external { + policy = TimelockPolicy(address(0xACE)); + vm.etch(address(policy), type(TimelockPolicy).runtimeCode); + } + + function _installData(uint48 delay, uint48 expirationPeriod, address guardian) + internal + pure + returns (bytes memory) + { + return abi.encodePacked(ID, abi.encode(delay, expirationPeriod, guardian)); + } + + // no-op callData => proposal CREATION; signature = [callDataLength(32)][callData][nonce(32)]. + function _creationUserOp(bytes memory execCallData, uint256 proposalNonce) + internal + view + returns (PackedUserOperation memory op) + { + op.sender = address(this); + op.nonce = 0; + op.callData = ""; + op.signature = abi.encodePacked(uint256(execCallData.length), execCallData, proposalNonce); + } + + // non-no-op callData + matching nonce => EXECUTION of proposal keyed by keccak(sender, keccak(callData), nonce). + function _executionUserOp(bytes memory execCallData, uint256 proposalNonce) + internal + view + returns (PackedUserOperation memory op) + { + op.sender = address(this); + op.nonce = proposalNonce; + op.callData = execCallData; + op.signature = ""; + } + + /// @notice A proposal created before a reinstall (epoch E) can never execute after reinstall + /// (epoch E+1): execution returns the failure sentinel. One load-bearing assertion. + function check_StaleEpochProposalRejected(uint48 delay, uint48 expirationPeriod, uint256 proposalNonce) external { + // Genuine preconditions: install guard satisfiable (else onInstall reverts, not a real state). + vm.assume(delay > 0); + vm.assume(expirationPeriod > 0); + vm.assume(block.timestamp <= type(uint48).max); + vm.assume(uint256(delay) + uint256(expirationPeriod) <= uint256(type(uint48).max) - block.timestamp); + + bytes memory execCallData = hex"11223344"; // non-no-op + + // Install #1 -> epoch E. Create Pending proposal stamped at epoch E. + policy.onInstall(_installData(delay, expirationPeriod, address(0))); + policy.checkUserOpPolicy(ID, _creationUserOp(execCallData, proposalNonce)); + + // Reinstall: uninstall (config deleted, currentEpoch persists) then install #2 -> epoch E+1. + policy.onUninstall(abi.encodePacked(ID, bytes(""))); + policy.onInstall(_installData(delay, expirationPeriod, address(0))); + + // Attempt to execute the stale (epoch E) proposal under the reinstalled config (epoch E+1). + uint256 result = policy.checkUserOpPolicy(ID, _executionUserOp(execCallData, proposalNonce)); + + // OBSERVABLE postcondition: the failure sentinel, never a success window. + assertEq(result, SIG_VALIDATION_FAILED_UINT); + } + + // ---- Reachability / non-vacuity witness (MUST produce a counterexample) ---- + + /// @notice Witness that the stale cross-epoch state is genuinely reachable AND that, absent the + /// reinstall, the SAME proposal WOULD execute to success — so the L256 epoch check is a + /// real discriminator, not because execution always fails. We assert false on the + /// SUCCESS leaf of the no-reinstall path; a counterexample proves that path is live. + function check_StaleEpochProposalRejected_reachable(uint48 delay, uint48 expirationPeriod, uint256 proposalNonce) + external + { + vm.assume(delay > 0); + vm.assume(expirationPeriod > 0); + vm.assume(block.timestamp <= type(uint48).max); + vm.assume(uint256(delay) + uint256(expirationPeriod) <= uint256(type(uint48).max) - block.timestamp); + + bytes memory execCallData = hex"11223344"; + + // Same install + create, but NO reinstall: proposal.epoch == currentEpoch. + policy.onInstall(_installData(delay, expirationPeriod, address(0))); + policy.checkUserOpPolicy(ID, _creationUserOp(execCallData, proposalNonce)); + + uint256 result = policy.checkUserOpPolicy(ID, _executionUserOp(execCallData, proposalNonce)); + + // Live iff a model exists where the matching-epoch proposal executes to a SUCCESS window + // (authorizer bits == 0). Assert the negation to expose the live success path. + uint256 authorizer = result & ((uint256(1) << 160) - 1); + assertFalse(authorizer == 0 && result != SIG_VALIDATION_FAILED_UINT); + } +} diff --git a/test/halmos/WebAuthnKeyLifecycleHalmos.t.sol b/test/halmos/WebAuthnKeyLifecycleHalmos.t.sol new file mode 100644 index 0000000..15a0f2b --- /dev/null +++ b/test/halmos/WebAuthnKeyLifecycleHalmos.t.sol @@ -0,0 +1,269 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import {SymTest} from "halmos-cheatcodes/SymTest.sol"; +import {PackedUserOperation} from "account-abstraction/interfaces/PackedUserOperation.sol"; +import {WebAuthnValidator, WebAuthnValidatorData} from "src/validators/WebAuthnValidator.sol"; +import {WebAuthnSigner, WebAuthnSignerData} from "src/signers/WebAuthnSigner.sol"; +import {SIG_VALIDATION_SUCCESS_UINT, SIG_VALIDATION_FAILED_UINT} from "src/types/Constants.sol"; + +// Minimal cheatcode surface. Inheriting forge-std `Test` pulls in a base constructor that calls +// vm.deployCode(string) (StdConfig), which Halmos 0.3.3 does not support and fails setUp(). +// Note: expectRevert(bytes4) is NOT supported by Halmos 0.3.3, so revert checks use low-level +// .call and inspect the returned revert selector directly. +interface Vm { + function assume(bool) external pure; + function prank(address) external; + function etch(address, bytes calldata) external; +} + +/// @author taek +/// @notice Halmos proof harness for WebAuthnValidator / WebAuthnSigner storage-key correctness +/// and install/uninstall lifecycle guards. The WebAuthn/P256 signature verification is +/// NOT proved here: Solady WebAuthn verification is an INTERNAL library that inlines Base64URL +/// encoding, sha256, JSON offset checks, and P256 verification over an unbounded +/// (bytes,string,...) abi.decode of the signature — intractable for Halmos and reported +/// OUT-OF-SCOPE (claims (a)/(b) SUCCESS-tracking). This harness proves the observable +/// lifecycle behaviour that does not decode the signature: +/// (c) onInstall rejects pubKeyX==0 || pubKeyY==0 (InvalidPublicKey), +/// reverts AlreadyInitialized on double-install; +/// onUninstall reverts NotInitialized when unset; +/// WebAuthnSigner increments/decrements usedIds without underflow; +/// per-key storage separation: a stored key lands under the correct (account) / +/// (id,account) key and is readable back, and unset keys read as zero. +contract WebAuthnKeyLifecycleHalmos is SymTest { + Vm internal constant vm = Vm(address(uint160(uint256(keccak256("hevm cheat code"))))); + + WebAuthnValidator internal validator; + WebAuthnSigner internal signer; + + // Fixed caller so the (account)/(id,account) storage slots are concrete-keyed (Halmos-friendly). + address internal constant CALLER = address(0xCA11); + address internal constant OTHER = address(0xB0B); + + // AlreadyInitialized(address) / NotInitialized(address) live on IERC7579Modules. + bytes4 internal constant ALREADY_INIT = bytes4(keccak256("AlreadyInitialized(address)")); + bytes4 internal constant NOT_INIT = bytes4(keccak256("NotInitialized(address)")); + bytes4 internal constant INVALID_PUBKEY = bytes4(keccak256("InvalidPublicKey()")); + + function setUp() external { + // Halmos 0.3.3 cannot execute the via_ir creation bytecode (routes to an unsupported + // deployCode(string) cheat). Neither contract has constructor logic (WebAuthnValidator has + // no constructor; WebAuthnSigner inherits SignerBase's empty ctor), so placing runtime code + // directly is state-equivalent. + validator = WebAuthnValidator(address(uint160(uint256(keccak256("WebAuthnValidator"))))); + vm.etch(address(validator), type(WebAuthnValidator).runtimeCode); + + signer = WebAuthnSigner(address(uint160(uint256(keccak256("WebAuthnSigner"))))); + vm.etch(address(signer), type(WebAuthnSigner).runtimeCode); + } + + // install payload for the validator: abi.encode(WebAuthnValidatorData, bytes32) + function _valData(uint256 x, uint256 y) internal pure returns (bytes memory) { + return abi.encode(WebAuthnValidatorData({pubKeyX: x, pubKeyY: y}), bytes32(0)); + } + + // install payload for the signer: id (32 bytes) || abi.encode(WebAuthnSignerData, bytes32) + function _sigData(bytes32 id, uint256 x, uint256 y) internal pure returns (bytes memory) { + return abi.encodePacked(id, abi.encode(WebAuthnSignerData({pubKeyX: x, pubKeyY: y}), bytes32(0))); + } + + // Extracts the leading 4-byte selector from returndata (0 if none). + function _selector(bytes memory ret) internal pure returns (bytes4 s) { + if (ret.length >= 4) { + assembly { + s := mload(add(ret, 0x20)) + } + } + } + + // ============================================================================================= + // (c) VALIDATOR LIFECYCLE + // ============================================================================================= + + /// @notice onInstall reverts InvalidPublicKey iff either coordinate is zero; otherwise it stores + /// the (x,y) under webAuthnValidatorStorage[msg.sender] and marks the account initialized. + /// Observable: revert-selector / stored-value, no signature decode. + function check_Validator_onInstall_pubkeyGuardAndStore(uint256 x, uint256 y) external { + vm.prank(CALLER); + (bool ok, bytes memory ret) = address(validator).call(abi.encodeCall(validator.onInstall, (_valData(x, y)))); + if (x == 0 || y == 0) { + assert(!ok && _selector(ret) == INVALID_PUBKEY); + } else { + assert(ok); + (uint256 sx, uint256 sy) = validator.webAuthnValidatorStorage(CALLER); + // stored under the CORRECT key, exactly the installed value. + assert(sx == x && sy == y); + assert(validator.isInitialized(CALLER)); + } + } + + /// @notice Double-install reverts AlreadyInitialized. + function check_Validator_onInstall_doubleReverts(uint256 x, uint256 y) external { + vm.assume(x != 0 && y != 0); + vm.prank(CALLER); + validator.onInstall(_valData(x, y)); + + vm.prank(CALLER); + (bool ok, bytes memory ret) = address(validator).call(abi.encodeCall(validator.onInstall, (_valData(x, y)))); + assert(!ok && _selector(ret) == ALREADY_INIT); + } + + /// @notice onUninstall reverts NotInitialized when the account was never installed. + function check_Validator_onUninstall_unsetReverts() external { + vm.prank(CALLER); + (bool ok, bytes memory ret) = address(validator).call(abi.encodeCall(validator.onUninstall, (""))); + assert(!ok && _selector(ret) == NOT_INIT); + } + + /// @notice After uninstall the key is cleared and the account reads as uninitialized. + function check_Validator_onUninstall_clears(uint256 x, uint256 y) external { + vm.assume(x != 0 && y != 0); + vm.prank(CALLER); + validator.onInstall(_valData(x, y)); + + vm.prank(CALLER); + validator.onUninstall(""); + + (uint256 sx, uint256 sy) = validator.webAuthnValidatorStorage(CALLER); + assert(sx == 0 && sy == 0); + assert(!validator.isInitialized(CALLER)); + } + + /// @notice Per-account key separation: installing for CALLER never populates OTHER's slot. + function check_Validator_keySeparation(uint256 x, uint256 y) external { + vm.assume(x != 0 && y != 0); + vm.prank(CALLER); + validator.onInstall(_valData(x, y)); + + (uint256 ox, uint256 oy) = validator.webAuthnValidatorStorage(OTHER); + assert(ox == 0 && oy == 0); + assert(!validator.isInitialized(OTHER)); + } + + // ============================================================================================= + // (c) SIGNER LIFECYCLE + // ============================================================================================= + + /// @notice _signerOninstall reverts InvalidPublicKey iff either coordinate is zero; otherwise it + /// stores under webAuthnSignerStorage[id][msg.sender] and increments usedIds[msg.sender]. + function check_Signer_onInstall_pubkeyGuardAndStore(bytes32 id, uint256 x, uint256 y) external { + vm.prank(CALLER); + (bool ok, bytes memory ret) = address(signer).call(abi.encodeCall(signer.onInstall, (_sigData(id, x, y)))); + if (x == 0 || y == 0) { + assert(!ok && _selector(ret) == INVALID_PUBKEY); + } else { + assert(ok); + (uint256 sx, uint256 sy) = signer.webAuthnSignerStorage(id, CALLER); + assert(sx == x && sy == y); + assert(signer.usedIds(CALLER) == 1); + } + } + + /// @notice Double-install of the same (id) reverts AlreadyInitialized. + function check_Signer_onInstall_doubleReverts(bytes32 id, uint256 x, uint256 y) external { + vm.assume(x != 0 && y != 0); + vm.prank(CALLER); + signer.onInstall(_sigData(id, x, y)); + + vm.prank(CALLER); + (bool ok, bytes memory ret) = address(signer).call(abi.encodeCall(signer.onInstall, (_sigData(id, x, y)))); + assert(!ok && _selector(ret) == ALREADY_INIT); + } + + /// @notice onUninstall reverts NotInitialized when (id, msg.sender) was never installed. + function check_Signer_onUninstall_unsetReverts(bytes32 id) external { + bytes memory data = abi.encodePacked(id, bytes("")); + vm.prank(CALLER); + (bool ok, bytes memory ret) = address(signer).call(abi.encodeCall(signer.onUninstall, (data))); + assert(!ok && _selector(ret) == NOT_INIT); + } + + /// @notice Uninstall clears the (id,account) key and decrements usedIds without underflow: + /// install then uninstall returns usedIds to 0 (no wrap to 2**256-1). + function check_Signer_onUninstall_clearsAndDecrements(bytes32 id, uint256 x, uint256 y) external { + vm.assume(x != 0 && y != 0); + vm.prank(CALLER); + signer.onInstall(_sigData(id, x, y)); + + vm.prank(CALLER); + signer.onUninstall(abi.encodePacked(id, bytes(""))); + + (uint256 sx, uint256 sy) = signer.webAuthnSignerStorage(id, CALLER); + assert(sx == 0 && sy == 0); + assert(signer.usedIds(CALLER) == 0); + } + + /// @notice Per-(id,account) key separation: installing (id, CALLER) never populates (id, OTHER) + /// nor a different id for CALLER. + function check_Signer_keySeparation(bytes32 id, bytes32 id2, uint256 x, uint256 y) external { + vm.assume(x != 0 && y != 0); + vm.assume(id != id2); + vm.prank(CALLER); + signer.onInstall(_sigData(id, x, y)); + + // different account, same id + (uint256 ox, uint256 oy) = signer.webAuthnSignerStorage(id, OTHER); + assert(ox == 0 && oy == 0); + // same account, different id + (uint256 dx, uint256 dy) = signer.webAuthnSignerStorage(id2, CALLER); + assert(dx == 0 && dy == 0); + } + + // ============================================================================================= + // REACHABILITY / NON-VACUITY WITNESSES + // ============================================================================================= + + /// @notice Witness: the validator install SUCCESS leaf is LIVE (non-zero key stores & inits). + function check_Validator_installReachable(uint256 x, uint256 y) external { + vm.assume(x != 0 && y != 0); + vm.prank(CALLER); + validator.onInstall(_valData(x, y)); + // path live => this fires with a counterexample. + assert(!validator.isInitialized(CALLER)); + } + + /// @notice Witness: the validator InvalidPublicKey revert leaf is LIVE. Low-level call so the + /// revert does not abort the test; assert the call SUCCEEDED => counterexample proves the + /// revert path is actually taken (non-vacuous). + function check_Validator_invalidPubkeyReachable(uint256 y) external { + vm.prank(CALLER); + (bool ok, bytes memory ret) = address(validator).call(abi.encodeCall(validator.onInstall, (_valData(0, y)))); + // If the revert path is live, ok==false with the InvalidPublicKey selector; asserting the + // opposite yields a counterexample proving reachability. + assert(ok || _selector(ret) != INVALID_PUBKEY); + } + + /// @notice Witness: the validator AlreadyInitialized revert leaf is LIVE. + function check_Validator_alreadyInitReachable(uint256 x, uint256 y) external { + vm.assume(x != 0 && y != 0); + vm.prank(CALLER); + validator.onInstall(_valData(x, y)); + vm.prank(CALLER); + (bool ok, bytes memory ret) = address(validator).call(abi.encodeCall(validator.onInstall, (_valData(x, y)))); + assert(ok || _selector(ret) != ALREADY_INIT); + } + + /// @notice Witness: the validator NotInitialized revert leaf is LIVE. + function check_Validator_notInitReachable() external { + vm.prank(CALLER); + (bool ok, bytes memory ret) = address(validator).call(abi.encodeCall(validator.onUninstall, (""))); + assert(ok || _selector(ret) != NOT_INIT); + } + + /// @notice Witness: the signer install SUCCESS leaf is LIVE (usedIds becomes 1). + function check_Signer_installReachable(bytes32 id, uint256 x, uint256 y) external { + vm.assume(x != 0 && y != 0); + vm.prank(CALLER); + signer.onInstall(_sigData(id, x, y)); + assert(signer.usedIds(CALLER) != 1); + } + + /// @notice Witness: the signer NotInitialized revert leaf is LIVE. + function check_Signer_notInitReachable(bytes32 id) external { + bytes memory data = abi.encodePacked(id, bytes("")); + vm.prank(CALLER); + (bool ok, bytes memory ret) = address(signer).call(abi.encodeCall(signer.onUninstall, (data))); + assert(ok || _selector(ret) != NOT_INIT); + } +} diff --git a/test/halmos/WebAuthnStatelessHalmos.t.sol b/test/halmos/WebAuthnStatelessHalmos.t.sol new file mode 100644 index 0000000..269e4bc --- /dev/null +++ b/test/halmos/WebAuthnStatelessHalmos.t.sol @@ -0,0 +1,276 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.20; + +import {SymTest} from "halmos-cheatcodes/SymTest.sol"; +import {WebAuthnValidator, WebAuthnValidatorData} from "src/validators/WebAuthnValidator.sol"; +import {WebAuthnSigner, WebAuthnSignerData} from "src/signers/WebAuthnSigner.sol"; +import {P256 as WebAuthnP256} from "solady/utils/P256.sol"; +import {SIG_VALIDATION_SUCCESS_UINT, SIG_VALIDATION_FAILED_UINT} from "src/types/Constants.sol"; + +interface Vm { + function assume(bool) external pure; + function prank(address) external; + function etch(address, bytes calldata) external; + function store(address, bytes32, bytes32) external; +} + +contract WebAuthnP256PrecompileHalmosStub { + fallback() external { + assembly ("memory-safe") { + mstore(0, sload(0)) + return(0, 0x20) + } + } +} + +/// @notice Exposes Solady's production P256 low-s gate without the surrounding module ABI. +contract WebAuthnPrimitiveHalmosHarness { + function verifyP256(bytes32 hash, uint256 r, uint256 s, uint256 x, uint256 y) external view returns (bool) { + return WebAuthnP256.verifySignature(hash, bytes32(r), bytes32(s), bytes32(x), bytes32(y)); + } +} + +/// @notice Production validator with only the cryptographic/parser boundary replaced by a +/// deterministic argument-checking oracle. The real stateless data-length, ABI-decode, +/// zero-key, and dispatch logic remains inherited byte-for-byte. +contract WebAuthnValidatorOracleHarness is WebAuthnValidator { + bytes32 internal constant ORACLE_ENABLED_SLOT = keccak256("WebAuthnHalmos.oracle.enabled"); + bytes32 internal constant ORACLE_HASH_SLOT = keccak256("WebAuthnHalmos.oracle.hash"); + bytes32 internal constant ORACLE_X_SLOT = keccak256("WebAuthnHalmos.oracle.x"); + bytes32 internal constant ORACLE_Y_SLOT = keccak256("WebAuthnHalmos.oracle.y"); + bytes32 internal constant ORACLE_SIGNATURE_LENGTH_SLOT = keccak256("WebAuthnHalmos.oracle.signatureLength"); + + function _verifySignature(bytes32 hash, bytes calldata signature, WebAuthnValidatorData memory data) + internal + view + override + returns (uint256) + { + bytes32 enabledSlot = ORACLE_ENABLED_SLOT; + bytes32 hashSlot = ORACLE_HASH_SLOT; + bytes32 xSlot = ORACLE_X_SLOT; + bytes32 ySlot = ORACLE_Y_SLOT; + bytes32 signatureLengthSlot = ORACLE_SIGNATURE_LENGTH_SLOT; + uint256 enabled; + bytes32 expectedHash; + uint256 expectedX; + uint256 expectedY; + uint256 expectedSignatureLength; + assembly ("memory-safe") { + enabled := sload(enabledSlot) + expectedHash := sload(hashSlot) + expectedX := sload(xSlot) + expectedY := sload(ySlot) + expectedSignatureLength := sload(signatureLengthSlot) + } + + bool matches = hash == expectedHash && data.pubKeyX == expectedX && data.pubKeyY == expectedY + && signature.length == expectedSignatureLength; + return enabled != 0 && matches ? SIG_VALIDATION_SUCCESS_UINT : SIG_VALIDATION_FAILED_UINT; + } +} + +/// @notice Production signer with the same deterministic argument-checking verification oracle. +contract WebAuthnSignerOracleHarness is WebAuthnSigner { + bytes32 internal constant ORACLE_ENABLED_SLOT = keccak256("WebAuthnHalmos.oracle.enabled"); + bytes32 internal constant ORACLE_HASH_SLOT = keccak256("WebAuthnHalmos.oracle.hash"); + bytes32 internal constant ORACLE_X_SLOT = keccak256("WebAuthnHalmos.oracle.x"); + bytes32 internal constant ORACLE_Y_SLOT = keccak256("WebAuthnHalmos.oracle.y"); + bytes32 internal constant ORACLE_SIGNATURE_LENGTH_SLOT = keccak256("WebAuthnHalmos.oracle.signatureLength"); + + function _verifySignature(bytes32 hash, bytes calldata signature, WebAuthnSignerData memory data) + internal + view + override + returns (uint256) + { + bytes32 enabledSlot = ORACLE_ENABLED_SLOT; + bytes32 hashSlot = ORACLE_HASH_SLOT; + bytes32 xSlot = ORACLE_X_SLOT; + bytes32 ySlot = ORACLE_Y_SLOT; + bytes32 signatureLengthSlot = ORACLE_SIGNATURE_LENGTH_SLOT; + uint256 enabled; + bytes32 expectedHash; + uint256 expectedX; + uint256 expectedY; + uint256 expectedSignatureLength; + assembly ("memory-safe") { + enabled := sload(enabledSlot) + expectedHash := sload(hashSlot) + expectedX := sload(xSlot) + expectedY := sload(ySlot) + expectedSignatureLength := sload(signatureLengthSlot) + } + + bool matches = hash == expectedHash && data.pubKeyX == expectedX && data.pubKeyY == expectedY + && signature.length == expectedSignatureLength; + return enabled != 0 && matches ? SIG_VALIDATION_SUCCESS_UINT : SIG_VALIDATION_FAILED_UINT; + } +} + +/// @author taek +/// @notice Halmos proofs for stateless WebAuthn module dispatch and Solady's locally decidable P256 +/// low-s gate. +/// +/// TCB / MODELING: the production stateless config gates and module dispatch execute from +/// inherited bytecode. `_verifySignature` is a deterministic oracle that also checks the +/// forwarded hash, public-key coordinates, and signature length. Solady's P256 low-s gate +/// is proven separately through WebAuthnPrimitiveHalmosHarness. +/// +/// COVERAGE GAP: Halmos 0.3.3 cannot execute the full Base64URL + multiple SHA-256 pipeline +/// with symbolic challenges (symbolic lookup indices and mixed-width SHA UFs). Challenge, +/// response-type, and authenticator-data integration remain covered by concrete Forge tests +/// and Solady's upstream suite; elliptic-curve soundness remains in the native verifier TCB. +contract WebAuthnStatelessHalmos is SymTest { + Vm internal constant vm = Vm(address(uint160(uint256(keccak256("hevm cheat code"))))); + + address internal constant PRECOMPILE = address(0x100); + address internal constant CALLER = address(0xCA11); + bytes32 internal constant ID = bytes32(uint256(0x1234)); + bytes32 internal constant ORACLE_ENABLED_SLOT = keccak256("WebAuthnHalmos.oracle.enabled"); + bytes32 internal constant ORACLE_HASH_SLOT = keccak256("WebAuthnHalmos.oracle.hash"); + bytes32 internal constant ORACLE_X_SLOT = keccak256("WebAuthnHalmos.oracle.x"); + bytes32 internal constant ORACLE_Y_SLOT = keccak256("WebAuthnHalmos.oracle.y"); + bytes32 internal constant ORACLE_SIGNATURE_LENGTH_SLOT = keccak256("WebAuthnHalmos.oracle.signatureLength"); + uint256 internal constant P256_N_DIV_2 = + 57896044605178124381348723474703786764998477612067880171211129530534256022184; + + WebAuthnValidatorOracleHarness internal validator; + WebAuthnSignerOracleHarness internal signer; + WebAuthnPrimitiveHalmosHarness internal primitives; + + function setUp() external { + WebAuthnP256PrecompileHalmosStub stub = + WebAuthnP256PrecompileHalmosStub(address(uint160(uint256(keccak256("WebAuthnP256PrecompileHalmosStub"))))); + vm.etch(address(stub), type(WebAuthnP256PrecompileHalmosStub).runtimeCode); + vm.etch(PRECOMPILE, address(stub).code); + + validator = + WebAuthnValidatorOracleHarness(address(uint160(uint256(keccak256("WebAuthnValidatorOracleHarness"))))); + vm.etch(address(validator), type(WebAuthnValidatorOracleHarness).runtimeCode); + + signer = WebAuthnSignerOracleHarness(address(uint160(uint256(keccak256("WebAuthnSignerOracleHarness"))))); + vm.etch(address(signer), type(WebAuthnSignerOracleHarness).runtimeCode); + + primitives = + WebAuthnPrimitiveHalmosHarness(address(uint160(uint256(keccak256("WebAuthnPrimitiveHalmosHarness"))))); + vm.etch(address(primitives), type(WebAuthnPrimitiveHalmosHarness).runtimeCode); + } + + function _data(uint256 x, uint256 y) internal pure returns (bytes memory) { + return abi.encode(WebAuthnValidatorData(x, y), bytes32(0)); + } + + function _signerInstallData(uint256 x, uint256 y) internal pure returns (bytes memory) { + return abi.encodePacked(ID, abi.encode(WebAuthnSignerData(x, y), bytes32(0))); + } + + function _armOracle(bytes32 hash, uint256 x, uint256 y, uint256 signatureLength, bool enabled) internal { + address[2] memory targets = [address(validator), address(signer)]; + for (uint256 i; i < targets.length; i++) { + vm.store(targets[i], ORACLE_ENABLED_SLOT, bytes32(uint256(enabled ? 1 : 0))); + vm.store(targets[i], ORACLE_HASH_SLOT, hash); + vm.store(targets[i], ORACLE_X_SLOT, bytes32(x)); + vm.store(targets[i], ORACLE_Y_SLOT, bytes32(y)); + vm.store(targets[i], ORACLE_SIGNATURE_LENGTH_SLOT, bytes32(signatureLength)); + } + } + + function _setP256Oracle(bool result) internal { + vm.store(PRECOMPILE, bytes32(0), bytes32(uint256(result ? 1 : 0))); + } + + // ============================================================================================= + // STATELESS CONFIG / DISPATCH + // ============================================================================================= + + function check_StatelessOraclePlumbing( + bytes32 hash, + uint256 x, + uint256 y, + bool oracleResult, + address requestingProtocol + ) external { + vm.assume(x != 0 && y != 0); + bytes memory signature = hex"010203"; + _armOracle(hash, x, y, signature.length, oracleResult); + + bool validatorDirect = validator.validateSignatureWithData(hash, signature, _data(x, y)); + bool validatorWithSender = + validator.validateSignatureWithDataWithSender(requestingProtocol, hash, signature, _data(x, y)); + bool signerDirect = signer.validateSignatureWithData(hash, signature, _data(x, y)); + bool signerWithSender = + signer.validateSignatureWithDataWithSender(requestingProtocol, hash, signature, _data(x, y)); + + assert(validatorDirect == oracleResult); + assert(validatorWithSender == oracleResult); + assert(signerDirect == oracleResult); + assert(signerWithSender == oracleResult); + } + + function check_StatelessConfigurationGuards(bytes32 hash) external { + _armOracle(hash, 1, 1, 0, true); + + assert(!validator.validateSignatureWithData(hash, hex"", hex"01")); + assert(!signer.validateSignatureWithData(hash, hex"", hex"01")); + assert(!validator.validateSignatureWithData(hash, hex"", _data(0, 1))); + assert(!signer.validateSignatureWithData(hash, hex"", _data(1, 0))); + } + + function check_StatelessIgnoresInstalledState(bytes32 hash, uint256 x, uint256 y, bool oracleResult) external { + vm.assume(x != 0 && y != 0); + bytes memory signature = hex"010203"; + _armOracle(hash, x, y, signature.length, oracleResult); + + bool validatorBefore = validator.validateSignatureWithData(hash, signature, _data(x, y)); + bool signerBefore = signer.validateSignatureWithData(hash, signature, _data(x, y)); + + vm.prank(CALLER); + validator.onInstall(_data(7, 11)); + vm.prank(CALLER); + signer.onInstall(_signerInstallData(7, 11)); + + bool validatorAfter = validator.validateSignatureWithData(hash, signature, _data(x, y)); + bool signerAfter = signer.validateSignatureWithData(hash, signature, _data(x, y)); + + assert(validatorBefore == validatorAfter); + assert(signerBefore == signerAfter); + assert(validatorAfter == signerAfter); + } + + // ============================================================================================= + // SOLADY P256 PRIMITIVE + // ============================================================================================= + + function check_P256LowSOracleExact(bytes32 hash, uint256 r, uint256 s, uint256 x, uint256 y, bool oracleResult) + external + { + vm.assume(s <= P256_N_DIV_2); + _setP256Oracle(oracleResult); + assert(primitives.verifyP256(hash, r, s, x, y) == oracleResult); + } + + function check_P256HighSAlwaysRejects(bytes32 hash, uint256 r, uint256 x, uint256 y, uint256 excess) external { + vm.assume(excess <= type(uint256).max - P256_N_DIV_2 - 1); + _setP256Oracle(true); + assert(!primitives.verifyP256(hash, r, P256_N_DIV_2 + 1 + excess, x, y)); + } + + // ============================================================================================= + // NON-VACUITY WITNESSES (counterexamples expected) + // ============================================================================================= + + function check_StatelessAcceptReachable(bytes32 hash) external { + bytes memory signature = hex"010203"; + _armOracle(hash, 1, 1, signature.length, true); + bool result = validator.validateSignatureWithData(hash, signature, _data(1, 1)); + assert(!result); + } + + function check_StatelessRejectReachable(bytes32 hash) external { + bytes memory signature = hex"010203"; + _armOracle(hash, 1, 1, signature.length, false); + bool result = signer.validateSignatureWithData(hash, signature, _data(1, 1)); + assert(result); + } +} diff --git a/test/halmos/WeightedECDSAAcceptSetHalmos.t.sol b/test/halmos/WeightedECDSAAcceptSetHalmos.t.sol new file mode 100644 index 0000000..6d6147c --- /dev/null +++ b/test/halmos/WeightedECDSAAcceptSetHalmos.t.sol @@ -0,0 +1,142 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +/// @author taek + +import {Test} from "forge-std/Test.sol"; +import {SymTest} from "halmos-cheatcodes/SymTest.sol"; + +/// @notice isValidSignatureWithSender returns ERC1271_MAGICVALUE only when the +/// summed weight of DISTINCT guardians reaches threshold; a duplicated single-guardian +/// signature must NOT reach threshold. +/// +/// MODELING (recover treated as an uninterpreted function — see TCB note): +/// ECDSA.recover is a precompile Halmos cannot solve symbolically, so this harness makes the +/// RECOVERED SIGNER the symbolic variable. The loop over data[i*65:(i+1)*65] is replaced by a +/// loop over N symbolic signer addresses s_0..s_{n-1}. Per-signer guardian weight is looked up +/// through a real mapping keyed by the symbolic address, so the SAME address always yields the +/// SAME symbolic weight (the constraint that makes the duplicate-signer case faithful). The body +/// replicates WeightedECDSAValidator.isValidSignatureWithSender lines 296-319 VERBATIM: +/// - line 305: prevSigner = address(uint160(type(uint160).max)) +/// - line 310: if (signer >= prevSigner) return ERC1271_INVALID; (strictly-descending guard) +/// - line 313: prevSigner = signer +/// - line 314: totalWeight += guardian[signer].weight (uint256 accumulation) +/// - line 315: if (totalWeight >= threshold) return ERC1271_MAGICVALUE; +contract WeightedECDSAAcceptSetHalmos is SymTest, Test { + bytes4 constant ERC1271_MAGICVALUE = 0x1626ba7e; + bytes4 constant ERC1271_INVALID = 0xffffffff; + + // Consistent per-address symbolic weight: identical signer address -> identical weight (uint24). + mapping(address => uint24) internal weightOf; + + uint256 constant N = 3; // bounded loop (sigCount): 3 covers duplicate-adjacency + non-adjacent cases + + /// @dev Faithful replica of the accept loop. `signers` are the (uninterpreted) recover results, + /// `count` is data.length/65, `threshold` is strg.threshold. Returns the bytes4 the real + /// function returns AND `counted` = number of signers processed toward totalWeight before + /// returning (== accepting index + 1 on MAGICVALUE; only these signers are "counted"). + function _run(address[N] memory signers, uint256 count, uint24 threshold) + internal + view + returns (bytes4 result, uint256 counted) + { + if (threshold == 0) return (ERC1271_INVALID, 0); // line 296-298 + if (count == 0) return (ERC1271_INVALID, 0); // line 300-303 + + uint256 totalWeight = 0; + address prevSigner = address(uint160(type(uint160).max)); // line 305 + for (uint256 i = 0; i < count; i++) { + address signer = signers[i]; // line 307: recover, uninterpreted + if (signer >= prevSigner) { + return (ERC1271_INVALID, i); // line 310-312 + } + prevSigner = signer; // line 313 + totalWeight += weightOf[signer]; // line 314 + if (totalWeight >= threshold) { + return (ERC1271_MAGICVALUE, i + 1); // line 315-317: signers[0..i] counted + } + } + return (ERC1271_INVALID, count); // line 319 + } + + /// @notice Any MAGICVALUE acceptance counts only pairwise-DISTINCT signers — a + /// duplicated address can never contribute weight twice. + function check_MagicValueImpliesDistinctSigners( + address s0, + address s1, + address s2, + uint256 count, + uint24 threshold, + uint24 w0, + uint24 w1, + uint24 w2 + ) external { + // sigCount = data.length/65 with N symbolic chunks modeled -> count in [1, N]. + vm.assume(count >= 1 && count <= N); + + weightOf[s0] = w0; + weightOf[s1] = w1; + weightOf[s2] = w2; + + address[N] memory signers = [s0, s1, s2]; + + (bytes4 result, uint256 counted) = _run(signers, count, threshold); + + // POSTCONDITION (observable): if accepted, every pair among the COUNTED signers (indices + // 0..counted-1) is distinct. Asserted only over the processed prefix, not the whole array, + // so signers past the accepting index (never guarded, never counted) are unconstrained. + // This does not recompute the running total; distinctness is the invariant the line-310 + // ordering guard establishes and is what blocks the duplicate-weight bug class. + if (result == ERC1271_MAGICVALUE) { + if (counted >= 2 && s0 == s1) assert(false); // s0,s1 both counted -> must differ + if (counted >= 3) { + assert(s0 != s2); + assert(s1 != s2); + } + } + } + + /// @notice VACUITY / REACHABILITY (i): the accept path is LIVE — a legitimate 2-distinct-guardian + /// input DOES return MAGICVALUE. Asserts false on that path; a counterexample proves the + /// MAGICVALUE branch of the main property is reachable (non-vacuous accept). + function check_MagicValueImpliesDistinctSigners_reachable( + address s0, + address s1, + uint256 count, + uint24 threshold, + uint24 w0, + uint24 w1 + ) external { + vm.assume(count >= 1 && count <= N); + weightOf[s0] = w0; + weightOf[s1] = w1; + weightOf[address(0)] = 0; // s2 slot unused in this witness + + address[N] memory signers = [s0, s1, address(0)]; + (bytes4 result,) = _run(signers, count, threshold); + + // If Halmos can drive this to MAGICVALUE, the accept path is reachable -> expect a CEX here. + assert(result != ERC1271_MAGICVALUE); + } + + /// @notice REACHABILITY (ii) — a bounded proof: with ONE guardian of weight w + /// where 2w >= threshold > w, a DUPLICATED signature (s0 == s1) can NEVER reach threshold; + /// the line-310 ordering guard rejects the second (equal) signer BEFORE it is counted, so + /// the result is always ERC1271_INVALID. This proves the guard discriminates duplicates. + function check_DuplicateSignerRejected(address s, uint24 w, uint24 threshold) external { + // Single-guardian weight-doubling preconditions (genuine impossibilities only): + vm.assume(threshold != 0); + vm.assume(w < threshold); // one signature alone is below threshold + vm.assume(uint256(w) * 2 >= threshold); // ...but counting it twice would reach it + + weightOf[s] = w; // the single guardian + // Duplicate the SAME signer across both slots (s0 == s1 == s); recover determinism guarantees + // identical calldata chunks recover to the identical address, which this models directly. + address[N] memory signers = [s, s, s]; + + (bytes4 result,) = _run(signers, 2, threshold); + + // The duplicate must be rejected: never MAGICVALUE. + assertEq(result, ERC1271_INVALID); + } +} diff --git a/test/halmos/WeightedECDSACrossConventionHalmos.t.sol b/test/halmos/WeightedECDSACrossConventionHalmos.t.sol new file mode 100644 index 0000000..bc4f48b --- /dev/null +++ b/test/halmos/WeightedECDSACrossConventionHalmos.t.sol @@ -0,0 +1,194 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +/// @author taek + +import {Test} from "forge-std/Test.sol"; +import {SymTest} from "halmos-cheatcodes/SymTest.sol"; + +/// @notice Cross-convention non-acceptance between WeightedECDSAValidator (ep0.7: the last UserOp +/// signature signs toEthSignedMessageHash(userOpHash)) and WeightedECDSAValidatorV09 (ep0.9: +/// the last signature signs the RAW userOpHash). The two contracts share `_verifyUserOp` +/// verbatim (src/base/WeightedThresholdBase.sol) — the ONLY behavioral difference is the +/// `finalHash` argument threaded from `_finalUserOpHash`. A signature set S that base ACCEPTS +/// (its final slice recovers, over hEth, to a weighted guardian g) must NOT be ACCEPTED by V09 +/// (which recovers that SAME final slice over hRaw to a DIFFERENT address), and the first N-1 +/// proposalHash aggregation prefix is bit-identical across the two (same message => same +/// recovered signers => same weight accumulation). +/// +/// MODELING (recover treated as an uninterpreted, deterministic, message-injective ghost): +/// ECDSA.tryRecoverCalldata(message, sigChunk) is a precompile Halmos cannot solve symbolically, so +/// the RECOVERED SIGNERS are the symbolic variables (same convention as WeightedECDSAAcceptSetHalmos). +/// For a fixed calldata slice, recovery over the proposalHash message yields the prefix signers +/// p0..p1 (SHARED by both variants — same message). Recovery of the FINAL slice differs by variant: +/// over hEth it yields g (base), over hRaw it yields v09Final (V09). Message-injectivity — distinct +/// messages recover the same slice to distinct addresses — is a faithful ECDSA fact and is encoded +/// as vm.assume(v09Final != g). Per-address weight is a real mapping keyed by the symbolic signer, +/// so the SAME address always has the SAME weight (preserves the de-dup / double-count invariant). +/// _verifyUserOp is replicated VERBATIM, parameterized by the final signer (g vs v09Final). N = 3. +contract WeightedECDSACrossConventionHalmos is SymTest, Test { + // Consistent per-address weight: identical signer address -> identical (symbolic) weight (uint24). + mapping(address => uint24) internal weightOf; + + uint256 constant N = 3; // bounded sigCount + + /// @dev VERBATIM replica of WeightedThresholdBase._verifyUserOp (lines 102-176), with the recovered + /// signers supplied directly: `prefix` are the proposalHash signers (indices 0..count-2, SHARED + /// across both variants), `finalSigner` is the recovery of the final slice under this variant's + /// convention. Reverts (SignersNotSorted / ZeroWeightSigner) are modeled as Solidity reverts. + function _verifyUserOp(address[N] memory prefix, address finalSigner, uint256 count, uint24 threshold) + internal + view + returns (bool ok) + { + if (threshold == 0) return false; // line 110-112 + // sig.length % 65 == 0 and count != 0 guaranteed by the model (line 114-121) + + uint256 totalWeight = 0; + address lastSigner = address(0); + uint256 prefixLen = count - 1; + + // First N-1 signatures sign proposalHash (identical recovered signers across both variants). + for (uint256 i = 0; i < prefixLen; i++) { + address signer = prefix[i]; // line 134: recover(proposalHash, i) + + if (signer <= lastSigner) { + revert("SignersNotSorted"); // line 137-139 + } + lastSigner = signer; // line 140 + + uint256 guardianWeight = weightOf[signer]; // line 143 + if (guardianWeight == 0) { + revert("ZeroWeightSigner"); // line 145-147 + } + totalWeight += guardianWeight; // line 148 + } + + // Last signature signs finalHash (finalSigner = recover(finalHash, count-1)). + uint256 lastWeight = weightOf[finalSigner]; // line 155 + if (lastWeight == 0) { + return false; // line 157-159 + } + + // De-dup: was the final signer already counted in the proposal prefix? (line 162-168) + bool alreadySigned = false; + for (uint256 i = 0; i < prefixLen; i++) { + if (prefix[i] == finalSigner) { + alreadySigned = true; + break; + } + } + + if (!alreadySigned) { + totalWeight += lastWeight; // line 171-173 + } + + return totalWeight >= threshold; // line 175 + } + + /// @notice CROSS-CONVENTION NON-ACCEPTANCE (observable, single-guardian decisive form): the guardian + /// set's only threshold-meeting member is g, the address the base variant recovers from the + /// final slice over hEth. V09 recovers that SAME final slice over hRaw to v09Final != g, an + /// UNAUTHORIZED (weight-0) address. The prefix signers are shared (same proposalHash) and the + /// prefix weight is held below threshold so base ACCEPT is DECISIVE on g's final signature. + /// The property: the SAME set S that base ACCEPTS is REJECTED by V09. + /// + /// NON-TAUTOLOGY: the assertion is the ACCEPT DECISION (v09Ok == false) — it drives the full + /// aggregation (ordering, de-dup, threshold, the zero-weight-last-signer return-false path). + /// It is NOT a restatement of hEth != hRaw: a bug where V09 credited g's base-convention + /// signature (e.g. hashing the wrong message, or a de-dup/threshold flaw) would make + /// v09Ok == true and FALSIFY the property. + function check_CrossConventionNonAcceptance( + uint256 sigCount, + uint24 threshold, + address g, + address v09Final, + address p0, + address p1, + uint24 wg, + uint24 wp0, + uint24 wp1 + ) external { + // Dispatch on CONCRETE count so loop bounds fold to constants. Union covers N = 1..3. + if (sigCount == 1) { + _scenario(1, threshold, g, v09Final, p0, p1, wg, wp0, wp1); + } else if (sigCount == 2) { + _scenario(2, threshold, g, v09Final, p0, p1, wg, wp0, wp1); + } else if (sigCount == 3) { + _scenario(3, threshold, g, v09Final, p0, p1, wg, wp0, wp1); + } + } + + /// @dev Concrete-count scenario. Builds the decisive single-guardian setup for exactly `count` + /// signatures, runs base (final signer g over hEth) and V09 (final signer v09Final over hRaw) + /// over the SAME signature set, and asserts non-acceptance. + function _scenario( + uint256 count, + uint24 threshold, + address g, + address v09Final, + address p0, + address p1, + uint24 wg, + uint24 wp0, + uint24 wp1 + ) internal { + vm.assume(threshold != 0); + // recover message-injectivity (ECDSA fidelity): V09's final signer over hRaw is NOT g. + vm.assume(v09Final != g); + // g meets threshold on its own; v09Final is an UNAUTHORIZED, weight-0 address (the replayed + // slice recovers to a non-guardian under V09). + vm.assume(wg >= threshold); + vm.assume(v09Final != p0 && v09Final != p1); // v09Final is not one of the prefix guardians + weightOf[g] = wg; + weightOf[v09Final] = 0; + + // Prefix signers sign proposalHash (SAME message in BOTH variants -> bit-identical prefix). + // Nonzero weights (no ZeroWeightSigner revert), distinct from g, and prefix sum < threshold so + // base ACCEPT is DECISIVE on the hEth final slice. + address[N] memory prefix = [address(0), address(0), address(0)]; + uint256 prefixWeight = 0; + if (count >= 2) { + vm.assume(p0 != g && p0 != v09Final); + vm.assume(p0 != address(0)); + weightOf[p0] = wp0; + vm.assume(wp0 != 0); + prefix[0] = p0; + prefixWeight += wp0; + } + if (count >= 3) { + vm.assume(p1 != g && p1 != v09Final); + vm.assume(p1 != p0); + vm.assume(p0 < p1); // strictly ascending (else _verifyUserOp reverts SignersNotSorted) + weightOf[p1] = wp1; + vm.assume(wp1 != 0); + prefix[1] = p1; + prefixWeight += wp1; + } + vm.assume(prefixWeight < threshold); // final slice is load-bearing for base + + bool baseOk = _verifyUserOp(prefix, g, count, threshold); + bool v09Ok = _verifyUserOp(prefix, v09Final, count, threshold); + + // OBSERVABLE POSTCONDITION: a set accepted by base is NOT accepted by V09. + // (Non-vacuity confirmed out-of-band: `assert(!baseOk)` yields a CEX for count = 1, 2 and 3, + // proving the `if (baseOk)` guard is live in every branch.) + if (baseOk) { + assert(!v09Ok); + } + } + + /// @notice VACUITY / REACHABILITY (i): the base ACCEPT branch is LIVE. A single-signature set + /// (count = 1, final slice only) with a guardian g meeting threshold DOES make base accept. + /// Asserts false on that path -> a counterexample proves the accept branch is reachable + /// (non-vacuous), so the main property's `if (baseOk)` guard is not dead. + function check_CrossConventionNonAcceptance_reachable(uint24 threshold, address g, uint24 wg) external { + vm.assume(threshold != 0); + vm.assume(wg >= threshold); + weightOf[g] = wg; + address[N] memory prefix = [address(0), address(0), address(0)]; + bool baseOk = _verifyUserOp(prefix, g, 1, threshold); + // Expect a CEX: g's weight meets threshold -> baseOk == true, negating the assert. + assert(!baseOk); + } +} diff --git a/test/halmos/WeightedECDSAInstallHalmos.t.sol b/test/halmos/WeightedECDSAInstallHalmos.t.sol new file mode 100644 index 0000000..afc8bfc --- /dev/null +++ b/test/halmos/WeightedECDSAInstallHalmos.t.sol @@ -0,0 +1,193 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +/// @author taek + +import {Test} from "forge-std/Test.sol"; +import {SymTest} from "halmos-cheatcodes/SymTest.sol"; + +/// @notice After a SUCCESSFUL WeightedECDSASigner._signerOninstall, the stored config is +/// self-consistent: threshold > 0 AND threshold <= totalWeight AND totalWeight == the sum +/// of the validated (non-zero, distinct, non-self, non-zero-address) input weights. Each +/// rejection input triggers its SPECIFIC revert selector. This complements the renew proof +/// covering WeightedECDSAValidator.renew — this harness covers this signer's FIRST-install +/// bounds and its mapping-based (not ordering-based) distinctness guard. +/// +/// MODELING (follows the repo WeightedECDSAAcceptSet/Renew Halmos convention — the SUT is not +/// deployed because its EIP712 constructor is unsupported by Halmos's CREATE handling; the source +/// lines are replicated VERBATIM in-harness). Source: src/signers/WeightedECDSASigner.sol +/// _signerOninstall :59-83, _isInitialized :102-104. Faithful notes: +/// - reinstall guard (:61) keys off _isInitialized == (totalWeight != 0). On a FRESH account +/// totalWeight is 0, so the guard passes; this harness models the fresh-install path (the +/// reinstall-revert branch is exercised by a dedicated reachability check that pre-seeds +/// totalWeight). +/// - DISTINCTNESS is enforced by guardian[g].weight == 0 (:74), NOT by ordering. Modeled with a +/// real mapping keyed by the symbolic guardian address, so an in-install duplicate (same g +/// twice) is caught because the first iteration wrote a non-zero weight. +/// - totalWeight (:78) is `+=` on uint24 under 0.8 checked arithmetic -> overflow reverts. +contract WeightedECDSAInstallHalmos is SymTest, Test { + error AlreadyInitialized(address); + error LengthMismatch(); + error EmptyGuardians(); + error ZeroThreshold(); + error GuardianCannotBeSelf(); + error ZeroAddressGuardian(); + error ZeroWeight(); + error GuardianAlreadyEnabled(); + error ThresholdExceedsTotalWeight(); + error TotalWeightOverflow(); + + // Models guardian[g][id][kernel].weight for a fixed (id, kernel): identical guardian address + // always yields identical stored weight, so the "already enabled" guard sees a consistent view. + mapping(address => uint24) internal enabledWeight; + + uint24 internal storedTotalWeight; // models weightedStorage[id][kernel].totalWeight + uint24 internal storedThreshold; // models weightedStorage[id][kernel].threshold + + uint256 constant N = 3; // bounded guardian-array length (1..3) for tractability + + address constant KERNEL = address(0xdead); // stand-in for msg.sender (the kernel) + + /// @dev Faithful replica of _signerOninstall :59-83 for a fixed (id, KERNEL). Returns success = + /// false with a revert selector on any require/overflow path (so the caller can assert the + /// SPECIFIC selector), and on success returns (totalWeight, threshold) plus the summed + /// weight of the validated inputs computed INDEPENDENTLY (uint256, no early-exit) for the + /// totalWeight==sum equivalence. + function _install(address[N] memory guardians, uint24[N] memory weights, uint256 len, uint24 _threshold) + internal + returns (bool success, bytes4 selector, uint24 totalWeight, uint24 threshold, uint256 independentSum) + { + // :61 reinstall guard + if (storedTotalWeight != 0) return (false, AlreadyInitialized.selector, 0, 0, 0); + // :65 length mismatch is modeled by the caller keeping guardians/weights the same length; + // an explicit mismatch branch is exercised in a dedicated reachability check. + if (len == 0) return (false, EmptyGuardians.selector, 0, 0, 0); // :66 + if (_threshold == 0) return (false, ZeroThreshold.selector, 0, 0, 0); // :67 + + totalWeight = 0; // fresh storage + independentSum = 0; + for (uint256 i = 0; i < len; i++) { + address g = guardians[i]; + uint24 w = weights[i]; + if (g == KERNEL) return (false, GuardianCannotBeSelf.selector, 0, 0, 0); // :71 + if (g == address(0)) return (false, ZeroAddressGuardian.selector, 0, 0, 0); // :72 + if (w == 0) return (false, ZeroWeight.selector, 0, 0, 0); // :73 + if (enabledWeight[g] != 0) return (false, GuardianAlreadyEnabled.selector, 0, 0, 0); // :74 + + enabledWeight[g] = w; // :75-76 write guardian storage (distinctness for next iters) + // :78 totalWeight += w on uint24 -> checked, reverts on overflow. + unchecked { + uint24 nt = totalWeight + w; + if (nt < totalWeight) return (false, TotalWeightOverflow.selector, 0, 0, 0); + totalWeight = nt; + } + // Independent accumulation in wide uint256 (cannot overflow for N<=3 uint24s): this is + // the intended "sum of validated weights", computed WITHOUT reusing the uint24 running + // total, so totalWeight == independentSum is a genuine equivalence, not a tautology. + independentSum += uint256(w); + } + + // :81 threshold <= totalWeight + if (_threshold > totalWeight) return (false, ThresholdExceedsTotalWeight.selector, 0, 0, 0); + threshold = _threshold; // :82 + + // commit to storage (models weightedStorage writes) + storedTotalWeight = totalWeight; + storedThreshold = threshold; + return (true, bytes4(0), totalWeight, threshold, independentSum); + } + + /// @notice OBSERVABLE: on any SUCCESSFUL install, the stored config satisfies + /// threshold > 0 AND threshold <= totalWeight AND totalWeight == sum(validated weights). + function check_InstallEstablishesConsistentThreshold( + address g0, + address g1, + address g2, + uint24 w0, + uint24 w1, + uint24 w2, + uint256 len, + uint24 _threshold + ) external { + vm.assume(len >= 1 && len <= N); + + address[N] memory guardians = [g0, g1, g2]; + uint24[N] memory weights = [w0, w1, w2]; + + (bool success,, uint24 totalWeight, uint24 threshold, uint256 independentSum) = + _install(guardians, weights, len, _threshold); + + if (success) { + // Single coherent claim about a successful install's stored state. + assert(storedThreshold > 0 && storedThreshold <= storedTotalWeight); + assert(threshold == storedThreshold && totalWeight == storedTotalWeight); + assert(uint256(totalWeight) == independentSum); + } + } + + /// @notice VACUITY / REACHABILITY: a valid config (>=1 guardian, threshold in (0, sum]) + /// SUCCEEDS with the invariant holding. Asserts false on that live success path — a + /// counterexample proves the success path is reachable (non-vacuous). NO counterexample + /// => preconditions unsatisfiable => VACUOUS. + function check_InstallEstablishesConsistentThreshold_reachable( + address g0, + address g1, + address g2, + uint24 w0, + uint24 w1, + uint24 w2, + uint256 len, + uint24 _threshold + ) external { + vm.assume(len >= 1 && len <= N); + + address[N] memory guardians = [g0, g1, g2]; + uint24[N] memory weights = [w0, w1, w2]; + + (bool success,, uint24 totalWeight, uint24 threshold,) = _install(guardians, weights, len, _threshold); + + require(success); + require(threshold > 0); + require(threshold <= totalWeight); + assert(false); // reachable success => Halmos must return a counterexample here + } + + /// @notice REACHABILITY of each rejection branch: for every specific revert selector, there + /// exists an input that triggers exactly it. Asserts false when a given selector is + /// produced; a counterexample per selector proves that revert branch is live (so the + /// "each rejection triggers its SPECIFIC selector" clause is not vacuous). One assert + /// per selector; Halmos reports a CEX for each reachable branch. + function check_RejectionBranchesReachable( + address g0, + address g1, + address g2, + uint24 w0, + uint24 w1, + uint24 w2, + uint256 len, + uint24 _threshold, + uint24 seedTotalWeight + ) external { + vm.assume(len >= 1 && len <= N); + + // Allow the reinstall-guard branch to be reachable by seeding stored totalWeight. + storedTotalWeight = seedTotalWeight; + + address[N] memory guardians = [g0, g1, g2]; + uint24[N] memory weights = [w0, w1, w2]; + + (bool success, bytes4 selector,,,) = _install(guardians, weights, len, _threshold); + + if (!success) { + // Each of these must be independently reachable -> a CEX for each proves liveness. + if (selector == AlreadyInitialized.selector) assert(false); + if (selector == EmptyGuardians.selector) assert(false); + if (selector == ZeroThreshold.selector) assert(false); + if (selector == GuardianCannotBeSelf.selector) assert(false); + if (selector == ZeroAddressGuardian.selector) assert(false); + if (selector == ZeroWeight.selector) assert(false); + if (selector == GuardianAlreadyEnabled.selector) assert(false); + if (selector == ThresholdExceedsTotalWeight.selector) assert(false); + } + } +} diff --git a/test/halmos/WeightedECDSARenewHalmos.t.sol b/test/halmos/WeightedECDSARenewHalmos.t.sol new file mode 100644 index 0000000..7b11451 --- /dev/null +++ b/test/halmos/WeightedECDSARenewHalmos.t.sol @@ -0,0 +1,5 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +// REMOVED: this harness proved WeightedECDSAValidator.renew(), which no longer exists after the +// dead-governance removal. Neutralized (agent cannot `rm`); lead should `git rm` this file. diff --git a/test/halmos/WeightedECDSAValidateSignatureHalmos.t.sol b/test/halmos/WeightedECDSAValidateSignatureHalmos.t.sol new file mode 100644 index 0000000..9fb4eab --- /dev/null +++ b/test/halmos/WeightedECDSAValidateSignatureHalmos.t.sol @@ -0,0 +1,151 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +/// @author taek + +import {Test} from "forge-std/Test.sol"; +import {SymTest} from "halmos-cheatcodes/SymTest.sol"; + +/// @notice Double-count and ordering properties for the ERC1271 (`_validateSignature`) and +/// stateless (`_validateStatelessSignature`) paths of WeightedECDSASigner. Distinct from +/// WeightedECDSAAcceptSetHalmos, which exercised the legacy strictly-DESCENDING +/// `isValidSignatureWithSender` aggregation. THESE two paths use the current +/// strictly-ASCENDING guard (`lastSigner = 0`; reject on `signer <= lastSigner`) plus an +/// in-loop early-accept AND a separate ordering-gated last-signature branch — uncovered code. +/// +/// MODELING (recover UNINTERPRETED — see TCB): +/// ECDSA.tryRecoverCalldata is a precompile Halmos cannot solve, so the RECOVERED SIGNER is the +/// symbolic variable: each 65-byte slice -> one symbolic address. sigCount = sig.length/65 is +/// modeled as a symbolic `count` in [1, N]. The loop body is a VERBATIM replica of +/// src/signers/WeightedECDSASigner.sol: +/// _validateSignature :285-321 (sorted gate :289, weight add :299, early-accept :300, last :306-317) +/// _validateStatelessSignature :344-379 (sorted :347, weight :357, early-accept :358, last :364-376) +/// Both replicas share the identical accept/ordering logic; the only difference is the weight +/// source (real mapping for the installed ERC1271 path vs. memory arrays for the stateless path). +/// The ZeroWeightSigner revert on a non-last zero-weight signer is preserved so the harness only +/// accepts along the exact leaves the source accepts. +contract WeightedECDSAValidateSignatureHalmos is SymTest, Test { + bytes4 constant ERC1271_MAGICVALUE = 0x1626ba7e; + bytes4 constant ERC1271_INVALID = 0xffffffff; + + // Consistent per-address symbolic weight (installed ERC1271 path): same signer -> same weight. + mapping(address => uint24) internal weightOf; + + uint256 constant N = 3; // bounded loop (sigCount): covers duplicate-adjacency + non-adjacent + + // --------------------------------------------------------------------------------------------- + // Verbatim replica of _validateSignature (ERC1271 / installed path), lines 285-321. + // Returns the bytes4 result AND `counted` = number of signers whose weight was added toward + // totalWeight before returning (the accepting prefix on MAGICVALUE). + // --------------------------------------------------------------------------------------------- + function _runInstalled(address[N] memory signers, uint256 count, uint24 threshold) + internal + view + returns (bytes4 result, uint256 counted) + { + if (threshold == 0) return (ERC1271_INVALID, 0); // :271-273 + if (count == 0) return (ERC1271_INVALID, 0); // :276-278 + + uint256 totalWeight = 0; + address lastSigner = address(0); // :282 + + // Process all signatures except the last one (:285-303). + // Loop unrolled over the concrete bound N with an explicit `i + 1 < count` guard so the + // array offset stays CONCRETE (Halmos cannot index memory at a symbolic offset). + for (uint256 i = 0; i < N; i++) { + if (i + 1 >= count) break; // process all but the last + address signer = signers[i]; // :286 recover, uninterpreted + if (signer <= lastSigner) return (ERC1271_INVALID, i); // :289-291 sorted gate BEFORE count + lastSigner = signer; // :292 + uint24 guardianWeight = weightOf[signer]; // :294 + if (guardianWeight == 0) revert(); // :296-298 ZeroWeightSigner + totalWeight += guardianWeight; // :299 + if (totalWeight >= threshold) return (ERC1271_MAGICVALUE, i + 1); // :300-302 + } + + // Last signature (:305-318). Concrete-offset dispatch on count in [1, N]. + address last = count == 1 ? signers[0] : (count == 2 ? signers[1] : signers[2]); // :306 + if (last <= lastSigner) return (ERC1271_INVALID, count - 1); // :307-309 sorted gate + uint24 lastWeight = weightOf[last]; // :310 + if (lastWeight == 0) return (ERC1271_INVALID, count - 1); // :311-314 (no revert on last) + totalWeight += lastWeight; // :315 + if (totalWeight >= threshold) return (ERC1271_MAGICVALUE, count); // :316-318 + return (ERC1271_INVALID, count); // :320 + } + + // NOTE on _validateStatelessSignature (:344-379): its accept/ordering logic is byte-for-byte + // identical to _validateSignature (ascending gate BEFORE count, in-loop early-accept, gated last + // branch); only the weight SOURCE differs (memory-array _memoryGuardianWeight vs. real mapping). + // Distinctness-of-the-counted-set is independent of the weight source, so the installed replica + // below is the canonical proof for both paths. (The certora leg of this RACE inherits the real + // contract and proves the stateless path directly with recover as a per-index ghost.) + + // ============================================================================================= + // PROPERTY (installed ERC1271 path): MAGICVALUE => the counted signers are pairwise DISTINCT. + // The ascending ordering gate (:289 / :307) runs BEFORE the weight is added (:299 / :315), so no + // duplicate address can have its weight counted twice. Asserted over the counted prefix only — + // NOT a re-run of the summation (tautology guard). + // ============================================================================================= + function check_MagicValueImpliesDistinctSigners_Installed( + address s0, + address s1, + address s2, + uint256 count, + uint24 threshold, + uint24 w0, + uint24 w1, + uint24 w2 + ) external { + vm.assume(count >= 1 && count <= N); + + weightOf[s0] = w0; + weightOf[s1] = w1; + weightOf[s2] = w2; + + address[N] memory signers = [s0, s1, s2]; + (bytes4 result, uint256 counted) = _runInstalled(signers, count, threshold); + + if (result == ERC1271_MAGICVALUE) { + if (counted >= 2 && s0 == s1) assert(false); + if (counted >= 3) { + assert(s0 != s2); + assert(s1 != s2); + } + } + } + + // VACUITY / REACHABILITY (installed accept path is LIVE): a 2-distinct-guardian input DOES accept. + function check_MagicValueImpliesDistinctSigners_Installed_reachable( + address s0, + address s1, + uint256 count, + uint24 threshold, + uint24 w0, + uint24 w1 + ) external { + vm.assume(count >= 1 && count <= N); + weightOf[s0] = w0; + weightOf[s1] = w1; + weightOf[address(0)] = 0; + + address[N] memory signers = [s0, s1, address(0)]; + (bytes4 result,) = _runInstalled(signers, count, threshold); + + assert(result != ERC1271_MAGICVALUE); // expect CEX -> accept path reachable (non-vacuous) + } + + // REACHABILITY (duplicate rejected, installed): one guardian weight w with 2w >= threshold > w; + // duplicating the signature (s0 == s1) can never reach threshold — the ascending gate rejects + // the equal second signer BEFORE its weight is counted. + function check_DuplicateSignerRejected_Installed(address s, uint24 w, uint24 threshold) external { + vm.assume(threshold != 0); + vm.assume(w < threshold); + vm.assume(uint256(w) * 2 >= threshold); + + weightOf[s] = w; + address[N] memory signers = [s, s, s]; + + (bytes4 result,) = _runInstalled(signers, 2, threshold); + assertEq(result, ERC1271_INVALID); + } +} diff --git a/test/halmos/WeightedECDSAValidatorInstallHalmos.t.sol b/test/halmos/WeightedECDSAValidatorInstallHalmos.t.sol new file mode 100644 index 0000000..599dacb --- /dev/null +++ b/test/halmos/WeightedECDSAValidatorInstallHalmos.t.sol @@ -0,0 +1,201 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +/// @author taek + +import {Test} from "forge-std/Test.sol"; +import {SymTest} from "halmos-cheatcodes/SymTest.sol"; + +/// @notice After a SUCCESSFUL WeightedECDSAValidator.onInstall, the stored config is self-consistent: +/// threshold > 0 AND threshold <= totalWeight AND totalWeight == the sum of the validated +/// (non-zero, distinct, non-self, non-zero-address) input weights. Each rejection input +/// triggers its SPECIFIC revert selector. This is the SM-01 analog for the VALIDATOR — the +/// existing WeightedECDSAInstallHalmos proof covered only the SIGNER (WeightedECDSASigner). +/// +/// MODELING (follows the repo WeightedECDSAInstall/Renew Halmos convention — the SUT is not deployed +/// because its EIP712 constructor is unsupported by Halmos's CREATE handling; the source lines are +/// replicated VERBATIM in-harness). Source: src/validators/WeightedECDSAValidator.sol onInstall +/// :89-114, _isInitialized :136-138. Faithful notes: +/// - reinstall guard (:90) keys off _isInitialized == (weightedStorage[kernel].totalWeight != 0). +/// On a FRESH account totalWeight is 0, so the guard passes; the reinstall-revert branch is +/// exercised by the rejection reachability check which pre-seeds totalWeight. +/// - LengthMismatch (:94) requires _guardians.length == _weights.length. Modeled with two +/// independent lengths (gLen/wLen) so the mismatch branch is genuinely reachable. +/// - DISTINCTNESS is enforced by guardian[g][kernel].weight == 0 (:105), NOT by ordering. Modeled +/// with a real mapping keyed by the symbolic guardian address, so an in-install duplicate (same +/// g twice) is caught because the first iteration wrote a non-zero weight. +/// - totalWeight (:109) is `+=` on uint24 under 0.8 checked arithmetic -> overflow reverts. +/// - single-config: no `id` dimension (unlike the signer); enabledWeight/storedTotalWeight/ +/// storedThreshold model weightedStorage[KERNEL] for a fixed kernel. +contract WeightedECDSAValidatorInstallHalmos is SymTest, Test { + error AlreadyInitialized(address); + error LengthMismatch(); + error EmptyGuardians(); + error ZeroThreshold(); + error GuardianCannotBeSelf(); + error ZeroAddressGuardian(); + error ZeroWeight(); + error GuardianAlreadyEnabled(); + error ThresholdExceedsTotalWeight(); + error TotalWeightOverflow(); + + // Models guardian[g][kernel].weight for a fixed kernel: identical guardian address always yields + // identical stored weight, so the "already enabled" guard sees a consistent view. + mapping(address => uint24) internal enabledWeight; + + uint24 internal storedTotalWeight; // models weightedStorage[kernel].totalWeight + uint24 internal storedThreshold; // models weightedStorage[kernel].threshold + + uint256 constant N = 3; // bounded guardian-array length (1..3) for tractability + + address constant KERNEL = address(0xdead); // stand-in for msg.sender (the kernel) + + /// @dev Faithful replica of onInstall :89-114 for a fixed KERNEL. Returns success = false with a + /// revert selector on any require/overflow path (so the caller can assert the SPECIFIC + /// selector), and on success returns (totalWeight, threshold) plus the summed weight of the + /// validated inputs computed INDEPENDENTLY (uint256, no early-exit) for the totalWeight==sum + /// equivalence. gLen/wLen are the two array lengths so :94 LengthMismatch is reachable. + function _install( + address[N] memory guardians, + uint24[N] memory weights, + uint256 gLen, + uint256 wLen, + uint24 _threshold + ) internal returns (bool success, bytes4 selector, uint24 totalWeight, uint24 threshold, uint256 independentSum) { + // :90 reinstall guard + if (storedTotalWeight != 0) return (false, AlreadyInitialized.selector, 0, 0, 0); + // :94 length mismatch + if (gLen != wLen) return (false, LengthMismatch.selector, 0, 0, 0); + if (gLen == 0) return (false, EmptyGuardians.selector, 0, 0, 0); // :95 + if (_threshold == 0) return (false, ZeroThreshold.selector, 0, 0, 0); // :96 + + totalWeight = 0; // fresh storage + independentSum = 0; + for (uint256 i = 0; i < gLen; i++) { + address g = guardians[i]; + uint24 w = weights[i]; + if (g == KERNEL) return (false, GuardianCannotBeSelf.selector, 0, 0, 0); // :102 + if (g == address(0)) return (false, ZeroAddressGuardian.selector, 0, 0, 0); // :103 + if (w == 0) return (false, ZeroWeight.selector, 0, 0, 0); // :104 + if (enabledWeight[g] != 0) return (false, GuardianAlreadyEnabled.selector, 0, 0, 0); // :105 + + enabledWeight[g] = w; // :106-107 write guardian storage (distinctness for next iters) + // :109 totalWeight += w on uint24 -> checked, reverts on overflow. + unchecked { + uint24 nt = totalWeight + w; + if (nt < totalWeight) return (false, TotalWeightOverflow.selector, 0, 0, 0); + totalWeight = nt; + } + // Independent accumulation in wide uint256 (cannot overflow for N<=3 uint24s): this is the + // intended "sum of validated weights", computed WITHOUT reusing the uint24 running total, + // so totalWeight == independentSum is a genuine equivalence, not a tautology. + independentSum += uint256(w); + } + + // :112 threshold <= totalWeight + if (_threshold > totalWeight) return (false, ThresholdExceedsTotalWeight.selector, 0, 0, 0); + threshold = _threshold; // :113 + + // commit to storage (models weightedStorage writes) + storedTotalWeight = totalWeight; + storedThreshold = threshold; + return (true, bytes4(0), totalWeight, threshold, independentSum); + } + + /// @notice OBSERVABLE: on any SUCCESSFUL install, the stored config satisfies + /// threshold > 0 AND threshold <= totalWeight AND totalWeight == sum(validated weights). + function check_InstallEstablishesConsistentThreshold( + address g0, + address g1, + address g2, + uint24 w0, + uint24 w1, + uint24 w2, + uint256 gLen, + uint24 _threshold + ) external { + vm.assume(gLen >= 1 && gLen <= N); + + address[N] memory guardians = [g0, g1, g2]; + uint24[N] memory weights = [w0, w1, w2]; + + // Success path requires equal lengths; on the observable claim we drive the matched case. + (bool success,, uint24 totalWeight, uint24 threshold, uint256 independentSum) = + _install(guardians, weights, gLen, gLen, _threshold); + + if (success) { + // Single coherent claim about a successful install's stored state. + assert(storedThreshold > 0 && storedThreshold <= storedTotalWeight); + assert(threshold == storedThreshold && totalWeight == storedTotalWeight); + assert(uint256(totalWeight) == independentSum); + } + } + + /// @notice VACUITY / REACHABILITY: a valid config (>=1 guardian, threshold in (0, sum]) SUCCEEDS + /// with the invariant holding. Asserts false on that live success path — a counterexample + /// proves the success path is reachable (non-vacuous). NO counterexample => preconditions + /// unsatisfiable => VACUOUS. + function check_InstallEstablishesConsistentThreshold_reachable( + address g0, + address g1, + address g2, + uint24 w0, + uint24 w1, + uint24 w2, + uint256 gLen, + uint24 _threshold + ) external { + vm.assume(gLen >= 1 && gLen <= N); + + address[N] memory guardians = [g0, g1, g2]; + uint24[N] memory weights = [w0, w1, w2]; + + (bool success,, uint24 totalWeight, uint24 threshold,) = _install(guardians, weights, gLen, gLen, _threshold); + + require(success); + require(threshold > 0); + require(threshold <= totalWeight); + assert(false); // reachable success => Halmos must return a counterexample here + } + + /// @notice REACHABILITY of each rejection branch: for every specific revert selector, there exists + /// an input that triggers exactly it. Asserts false when a given selector is produced; a + /// counterexample per selector proves that revert branch is live (so the "each rejection + /// triggers its SPECIFIC selector" clause is not vacuous). One assert per selector; Halmos + /// reports a CEX for each reachable branch. gLen/wLen independent so LengthMismatch fires. + function check_RejectionBranchesReachable( + address g0, + address g1, + address g2, + uint24 w0, + uint24 w1, + uint24 w2, + uint256 gLen, + uint256 wLen, + uint24 _threshold, + uint24 seedTotalWeight + ) external { + vm.assume(gLen <= N && wLen <= N); + + // Allow the reinstall-guard branch to be reachable by seeding stored totalWeight. + storedTotalWeight = seedTotalWeight; + + address[N] memory guardians = [g0, g1, g2]; + uint24[N] memory weights = [w0, w1, w2]; + + (bool success, bytes4 selector,,,) = _install(guardians, weights, gLen, wLen, _threshold); + + if (!success) { + // Each of these must be independently reachable -> a CEX for each proves liveness. + if (selector == AlreadyInitialized.selector) assert(false); + if (selector == LengthMismatch.selector) assert(false); + if (selector == EmptyGuardians.selector) assert(false); + if (selector == ZeroThreshold.selector) assert(false); + if (selector == GuardianCannotBeSelf.selector) assert(false); + if (selector == ZeroAddressGuardian.selector) assert(false); + if (selector == ZeroWeight.selector) assert(false); + if (selector == GuardianAlreadyEnabled.selector) assert(false); + if (selector == ThresholdExceedsTotalWeight.selector) assert(false); + } + } +} diff --git a/test/halmos/WeightedThresholdUserOpDedupHalmos.t.sol b/test/halmos/WeightedThresholdUserOpDedupHalmos.t.sol new file mode 100644 index 0000000..67175b6 --- /dev/null +++ b/test/halmos/WeightedThresholdUserOpDedupHalmos.t.sol @@ -0,0 +1,170 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +/// @author taek + +import {Test} from "forge-std/Test.sol"; +import {SymTest} from "halmos-cheatcodes/SymTest.sol"; + +/// @notice Dedup / double-count property for the SPLIT-SIG UserOp path of WeightedThresholdBase +/// (`_verifyUserOp`, src/base/WeightedThresholdBase.sol:102-176). NEW code — no existing +/// proof touches the split-sig path (WeightedECDSAValidateSignatureHalmos covers only the +/// single-hash `_validateSignature`/`_validateStatelessSignature` sorted paths). +/// +/// MODELING (recover UNINTERPRETED — see TCB): +/// ECDSA.tryRecoverCalldata is a precompile Halmos cannot solve, so the RECOVERED SIGNER is the +/// symbolic variable. CRITICAL: the N-1 proposal slices recover over `proposalHash` while the +/// FINAL slice recovers over `finalHash` (a DIFFERENT message) — so the final signer is an +/// INDEPENDENT symbolic address. The harness lets the adversary CHOOSE the final signer equal to +/// any proposal signer (that IS the double-count attack the dedup :161-173 defends against). +/// Weight is a real per-address mapping keyed by recovered address (same address -> same weight). +/// sigCount is modeled as symbolic `count` in [1, N]; the loop is unrolled over concrete N with an +/// `i + 1 < count` guard so array offsets stay concrete (Halmos can't index memory symbolically). +/// The ascending gate REVERTS (SignersNotSorted) and a non-last zero-weight proposal signer REVERTS +/// (ZeroWeightSigner) — preserved verbatim so the harness only accepts along source-accepting leaves. +/// +/// N = 3: up to 2 proposal signers + 1 final signer — the smallest bound that exhibits both a +/// multi-signer ascending proposal set AND the final==proposal double-count case. +contract WeightedThresholdUserOpDedupHalmos is SymTest, Test { + // Consistent per-address symbolic weight: same recovered signer -> same weight. + mapping(address => uint256) internal weightOf; + + uint256 constant N = 3; + + // --------------------------------------------------------------------------------------------- + // Verbatim replica of WeightedThresholdBase._verifyUserOp (:102-176). + // proposal[0..count-2] recover over proposalHash (independent symbolic addresses). + // `finalSigner` recovers over finalHash (independent, adversary-chosen). + // count == sigCount in [1, N]: count-1 proposal signers + 1 final signer. + // Reverts (via Solidity revert) mirror _revertSignersNotSorted / _revertZeroWeightSigner. + // --------------------------------------------------------------------------------------------- + function _runUserOp(address[N] memory proposal, address finalSigner, uint256 count, uint256 threshold) + internal + view + returns (bool ok) + { + if (threshold == 0) return false; // :110-112 + // sig.length % 65 == 0 and sigCount != 0 modeled by count in [1, N] (:114-121) + + uint256 totalWeight = 0; + address lastSigner = address(0); // :125 + + // proposalSigners[0..count-2] — the N-1 proposal set (:128). + address[N] memory proposalSigners; + uint256 proposalLen = count - 1; + + // Process all signatures except the last one — they sign proposalHash (:133-150). + // Unrolled over concrete N with an `i + 1 < count` guard to keep offsets concrete. + for (uint256 i = 0; i < N; i++) { + if (i + 1 >= count) break; // process all but the last (i < sigCount - 1) + address signer = proposal[i]; // :134 recover(proposalHash, ...), uninterpreted + if (signer <= lastSigner) revert(); // :137-139 SignersNotSorted REVERT (BEFORE count) + lastSigner = signer; // :140 + proposalSigners[i] = signer; // :141 + uint256 guardianWeight = weightOf[signer]; // :143 + if (guardianWeight == 0) revert(); // :145-147 ZeroWeightSigner REVERT + totalWeight += guardianWeight; // :148 NO early return :149 + } + + // Last signature signs finalHash (:153) — independent recovery. + address last = finalSigner; // :153 recover(finalHash, ...), uninterpreted & adversary-chosen + uint256 lastWeight = weightOf[last]; // :155 + if (lastWeight == 0) return false; // :157-159 (no revert on last) + + // Dedup: was the finalHash signer among the proposalHash signers? (:161-168) + bool alreadySigned = false; + for (uint256 i = 0; i < N; i++) { + if (i >= proposalLen) break; + if (proposalSigners[i] == last) { + alreadySigned = true; + break; + } + } + + if (!alreadySigned) { + totalWeight += lastWeight; // :171-173 add only if not already counted + } + + return totalWeight >= threshold; // :175 + } + + // ============================================================================================= + // DISPATCHED PROPERTY (observable, contrapositive double-count case): + // Final signer == the single proposal signer; one guardian weight w with w < threshold <= 2w. + // If the dedup :161-173 works, that lone guardian's weight is counted ONCE (not doubled) so the + // split sig MUST NOT accept. A broken dedup would double w to 2w >= threshold and return true. + // Asserted as an observable outcome (result must be false) — NOT a re-run of the dedup loop. + // ============================================================================================= + function check_FinalEqualsProposalNotDoubleCounted(address g, uint256 w, uint256 threshold) external { + vm.assume(threshold != 0); + vm.assume(w < threshold); // one copy is below threshold + vm.assume(w * 2 >= threshold); // two copies WOULD reach it — dedup is what prevents accept + vm.assume(w < type(uint128).max); // avoid overflow noise in the doubling arithmetic + + weightOf[g] = w; + + // count = 2: one proposal signer (g over proposalHash) + final signer (g over finalHash). + address[N] memory proposal = [g, address(0), address(0)]; + bool ok = _runUserOp(proposal, g, 2, threshold); + + assertEq(ok, false); // dedup fires -> weight counted once -> below threshold -> reject + } + + // --------------------------------------------------------------------------------------------- + // VACUITY / REACHABILITY (accept path is LIVE): a legitimate 2-DISTINCT-guardian split sig + // (one proposal signer + a DIFFERENT final signer, weights summing >= threshold) DOES accept. + // If this found no CEX the preconditions of the accept branch would be unsatisfiable (vacuous). + // --------------------------------------------------------------------------------------------- + function check_FinalEqualsProposalNotDoubleCounted_reachable( + address gp, + address gf, + uint256 wp, + uint256 wf, + uint256 threshold + ) external { + vm.assume(gp != gf); // two DISTINCT guardians + vm.assume(gp > address(0)); // proposal signer must beat lastSigner = 0 (ascending gate) + vm.assume(threshold != 0); + vm.assume(wp != 0 && wf != 0); + vm.assume(wp < type(uint128).max && wf < type(uint128).max); + vm.assume(wp + wf >= threshold); // combined weight reaches threshold + + weightOf[gp] = wp; + weightOf[gf] = wf; + + // count = 2: proposal signer gp + final signer gf (distinct). + address[N] memory proposal = [gp, address(0), address(0)]; + bool ok = _runUserOp(proposal, gf, 2, threshold); + + assert(!ok); // expect CEX -> accept path reachable (non-vacuous) + } + + // --------------------------------------------------------------------------------------------- + // DISCRIMINATION: proves the dedup is load-bearing. Same lone guardian, count = 3 (two proposal + // slices would BOTH be g — but the ascending gate REVERTS on the equal second proposal signer, + // so this input can never accept regardless of dedup). Confirms the ascending REVERT for the + // proposal set on the split path. (The dedup-specific discrimination is the dispatched property + // above: without dedup, count=2 final==proposal WOULD accept.) + // --------------------------------------------------------------------------------------------- + function check_DuplicateProposalSignersRevert(address g, uint256 w, uint256 threshold) external { + vm.assume(threshold != 0); + vm.assume(w != 0 && w < type(uint128).max); + weightOf[g] = w; + + address[N] memory proposal = [g, g, address(0)]; + // count = 3: proposal signers [g, g] + final. The equal second proposal signer trips the + // ascending gate -> revert. Halmos treats the revert as a non-accepting leaf; there is no + // path where this returns true. + (bool success,) = address(this).staticcall(abi.encodeCall(this.callRunUserOp, (proposal, g, 3, threshold))); + assertEq(success, false); // ascending gate reverts -> no accepting path + } + + /// @dev External wrapper so the discrimination check can observe the revert via staticcall. + function callRunUserOp(address[N] memory proposal, address finalSigner, uint256 count, uint256 threshold) + external + view + returns (bool) + { + return _runUserOp(proposal, finalSigner, count, threshold); + } +} diff --git a/test/halmos/WeightedValidatorVerifySortedHalmos.t.sol b/test/halmos/WeightedValidatorVerifySortedHalmos.t.sol new file mode 100644 index 0000000..2abdb42 --- /dev/null +++ b/test/halmos/WeightedValidatorVerifySortedHalmos.t.sol @@ -0,0 +1,157 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +/// @author taek + +import {Test} from "forge-std/Test.sol"; +import {SymTest} from "halmos-cheatcodes/SymTest.sol"; + +/// @notice ADAPTER-LEVEL proof for WeightedECDSAValidator.isValidSignatureWithSender, which +/// delegates to the SHARED WeightedThresholdBase._verifySorted on the VALIDATOR's storage +/// layout (single-config guardian set: threshold from weightedStorage[msg.sender].threshold, +/// weight from guardian[signer][msg.sender].weight, cfg = bytes32(0)). Establishes the shared +/// core is sound on the validator adapter, not just on WeightedECDSASigner — the core reason +/// for the refactor. Distinct from: +/// - WeightedECDSAValidateSignatureHalmos: proves the SIGNER's _validateSignature paths. +/// - WeightedECDSAAcceptSetHalmos: legacy strictly-DESCENDING variant (stale guard model). +/// +/// MODELING (recover UNINTERPRETED — see TCB): +/// ECDSA.tryRecoverCalldata is a precompile Halmos cannot solve, so the RECOVERED SIGNER is the +/// symbolic variable: each 65-byte slice -> one symbolic address, sigCount = sig.length/65 modeled +/// as a symbolic `count` in [1, N]. Per-signer weight is looked up through a real mapping keyed by +/// the symbolic address, so the SAME address always yields the SAME weight (the constraint that +/// makes the duplicate-signer case faithful — mirrors guardian[signer][account].weight). +/// The body is a VERBATIM replica of WeightedThresholdBase._verifySorted (src/base/WeightedThreshold- +/// Base.sol:38-93) as reached through the validator adapter (WeightedECDSAValidator.sol:171-178): +/// :43-45 threshold == 0 -> false +/// :47-50 sigCount == 0 -> false +/// :54 lastSigner = address(0) +/// :57-75 loop over first sigCount-1: :61 ascending gate `signer <= lastSigner` BEFORE count, +/// :66 weight via _guardianWeight, :68-70 non-last zero-weight REVERTS ZeroWeightSigner, +/// :71 add, :72 `>=` early-accept +/// :78-90 last sig: :79 ascending gate, :82 weight, :84-86 last zero-weight returns false (no +/// revert), :87 add, :88 `>=` accept +/// :92 fall-through false +contract WeightedValidatorVerifySortedHalmos is SymTest, Test { + bytes4 constant ERC1271_MAGICVALUE = 0x1626ba7e; + bytes4 constant ERC1271_INVALID = 0xffffffff; + + // Consistent per-address symbolic weight (validator single-config path): mirrors + // guardian[signer][msg.sender].weight — same signer -> same weight (uint24, the storage width). + mapping(address => uint24) internal weightOf; + + uint256 constant N = 3; // bounded loop (sigCount): covers duplicate-adjacency + non-adjacent + + // --------------------------------------------------------------------------------------------- + // Verbatim replica of WeightedThresholdBase._verifySorted as reached via the validator adapter. + // Returns the bytes4 that isValidSignatureWithSender returns AND `counted` = number of signers + // whose weight was added toward totalWeight before returning (the accepting prefix on MAGICVALUE). + // Loop is unrolled over the concrete bound N with an explicit `i + 1 < count` guard so the array + // offset stays CONCRETE (Halmos cannot index memory at a symbolic offset). + // --------------------------------------------------------------------------------------------- + function _verifySorted(address[N] memory signers, uint256 count, uint24 threshold) + internal + view + returns (bytes4 result, uint256 counted) + { + if (threshold == 0) return (ERC1271_INVALID, 0); // :43-45 + if (count == 0) return (ERC1271_INVALID, 0); // :47-50 + + uint256 totalWeight = 0; + address lastSigner = address(0); // :54 + + // Process all signatures except the last one (:57-75). + for (uint256 i = 0; i < N; i++) { + if (i + 1 >= count) break; // process all but the last + address signer = signers[i]; // :58 recover, uninterpreted + if (signer <= lastSigner) return (ERC1271_INVALID, i); // :61-63 ascending gate BEFORE count + lastSigner = signer; // :64 + uint24 guardianWeight = weightOf[signer]; // :66 _guardianWeight + if (guardianWeight == 0) revert(); // :68-70 _revertZeroWeightSigner (MUST revert) + totalWeight += guardianWeight; // :71 + if (totalWeight >= threshold) return (ERC1271_MAGICVALUE, i + 1); // :72-74 + } + + // Last signature (:78-90). Concrete-offset dispatch on count in [1, N]. + address last = count == 1 ? signers[0] : (count == 2 ? signers[1] : signers[2]); // :78 + if (last <= lastSigner) return (ERC1271_INVALID, count - 1); // :79-81 ascending gate + uint24 lastWeight = weightOf[last]; // :82 + if (lastWeight == 0) return (ERC1271_INVALID, count - 1); // :84-86 (no revert on last) + totalWeight += lastWeight; // :87 + if (totalWeight >= threshold) return (ERC1271_MAGICVALUE, count); // :88-90 + return (ERC1271_INVALID, count); // :92 + } + + // ============================================================================================= + // PROPERTY (validator adapter, ERC1271 path): MAGICVALUE => the counted signers are pairwise + // DISTINCT. The ascending ordering gate (:61 / :79) runs BEFORE weight is added (:71 / :87), so + // no duplicate address can have its weight counted twice. Asserted over the counted prefix only + // — NOT a re-run of the summation (tautology guard). + // ============================================================================================= + function check_MagicValueImpliesDistinctSigners_Validator( + address s0, + address s1, + address s2, + uint256 count, + uint24 threshold, + uint24 w0, + uint24 w1, + uint24 w2 + ) external { + vm.assume(count >= 1 && count <= N); + + weightOf[s0] = w0; + weightOf[s1] = w1; + weightOf[s2] = w2; + + address[N] memory signers = [s0, s1, s2]; + (bytes4 result, uint256 counted) = _verifySorted(signers, count, threshold); + + if (result == ERC1271_MAGICVALUE) { + if (counted >= 2 && s0 == s1) assert(false); // s0,s1 both counted -> must differ + if (counted >= 3) { + assert(s0 != s2); + assert(s1 != s2); + } + } + } + + // VACUITY / REACHABILITY (i): the validator accept path is LIVE — a 2-distinct-guardian input + // with weights summing >= threshold DOES return MAGICVALUE. Asserts false on that path; a CEX + // proves the MAGICVALUE branch of the main property is reachable (non-vacuous accept). + function check_MagicValueImpliesDistinctSigners_Validator_reachable( + address s0, + address s1, + uint256 count, + uint24 threshold, + uint24 w0, + uint24 w1 + ) external { + vm.assume(count >= 1 && count <= N); + weightOf[s0] = w0; + weightOf[s1] = w1; + weightOf[address(0)] = 0; // s2 slot unused in this witness + + address[N] memory signers = [s0, s1, address(0)]; + (bytes4 result,) = _verifySorted(signers, count, threshold); + + assert(result != ERC1271_MAGICVALUE); // expect CEX -> accept path reachable (non-vacuous) + } + + // REACHABILITY / DISCRIMINATION (ii): one validator guardian of weight w with 2w >= threshold > w; + // a DUPLICATED signature (s0 == s1 == s) can NEVER reach threshold — the ascending gate (:61) + // rejects the equal second signer BEFORE its weight is counted, so the result is ERC1271_INVALID. + // This is the duplicate-signer auth-bypass bug class, proved blocked on the validator's layout. + function check_DuplicateSignerRejected_Validator(address s, uint24 w, uint24 threshold) external { + vm.assume(threshold != 0); + vm.assume(w < threshold); // one signature alone is below threshold + vm.assume(uint256(w) * 2 >= threshold); // ...but counting it twice would reach it + + weightOf[s] = w; // the single guardian + address[N] memory signers = [s, s, s]; + + (bytes4 result,) = _verifySorted(signers, 2, threshold); + + assertEq(result, ERC1271_INVALID); // duplicate must be rejected + } +} diff --git a/test/kontrol/GasPolicyKontrol.t.sol b/test/kontrol/GasPolicyKontrol.t.sol new file mode 100644 index 0000000..584b52d --- /dev/null +++ b/test/kontrol/GasPolicyKontrol.t.sol @@ -0,0 +1,174 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.30; + +/// @author taek +/// +/// Kontrol (KEVM) proof: GasPolicy.checkUserOpPolicy cannot under-charge +/// the budget via uint128 truncation. KEVM confirms the EVM-level MUL + downcast +/// semantics on the exact 2^128 boundary — the value Kontrol adds over Halmos is +/// bytecode-level grounding of the truncation boundary. +/// +/// NOTE (dispatch blocker): this project has no Kontrol config (no kontrol.toml, +/// no kontrol-cheatcodes dependency, no KontrolTest base). Initializing Kontrol is +/// a structural change requiring team-lead approval, so this spec is authored but +/// NOT built/proven this dispatch. Once `kontrol init` + kontrol-cheatcodes are +/// added, run: +/// kontrol build +/// kontrol prove --match-test 'GasPolicyKontrol.prove_gasPolicy_noUnderCharge' +/// kontrol prove --match-test 'GasPolicyKontrol.prove_gasPolicy_boundaryRejected' +/// kontrol prove --match-test 'GasPolicyKontrol.prove_gasPolicy_successReachable' +/// kontrol prove --match-test 'GasPolicyKontrol.prove_gasPolicy_paymasterShortDataNoRevert' + +import {Test} from "forge-std/Test.sol"; +import {KontrolCheats} from "kontrol-cheatcodes/KontrolCheats.sol"; +import {PackedUserOperation} from "account-abstraction/interfaces/PackedUserOperation.sol"; +import {GasPolicy} from "src/policies/GasPolicy.sol"; + +contract GasPolicyKontrol is Test, KontrolCheats { + GasPolicy internal policy; + + uint256 constant SUCCESS = 0; // SIG_VALIDATION_SUCCESS_UINT + uint256 constant FAILED = 1; // SIG_VALIDATION_FAILED_UINT + + function setUp() public { + policy = new GasPolicy(); + } + + // -------------------------------------------------------------------------- + // Helper: build a PackedUserOperation with symbolic gas fields. + // verificationGasLimit / callGasLimit / maxFeePerGas are the uint128 slices of + // accountGasLimits (hi/lo) and gasFees (lo). preVerificationGas is full uint256 + // but bounded so the TRUE product is representable in uint256 (no ~2^320 wrap). + // -------------------------------------------------------------------------- + function _buildOp(uint256 preVG, uint128 vgl, uint128 cgl, uint128 mfpg) + internal + pure + returns (PackedUserOperation memory op) + { + op.accountGasLimits = bytes32((uint256(vgl) << 128) | uint256(cgl)); + op.preVerificationGas = preVG; + // gasFees = maxPriorityFeePerGas(hi) || maxFeePerGas(lo); only lo is read. + op.gasFees = bytes32(uint256(mfpg)); + // empty dynamic fields + } + + // Install a Live config with a symbolic allowed budget, no paymaster enforcement. + function _installLive(bytes32 id, uint128 allowed) internal { + vm.prank(address(this)); + bytes memory data = abi.encode(allowed, false, address(0)); + policy.onInstall(abi.encodePacked(id, data)); + } + + // ========================================================================== + // Main property: no under-charge. On SUCCESS the budget decreases by the TRUE + // (uint256-computed) cost; monotone non-increasing always. + // Reference trueCost is computed independently in uint256 here — NOT read back + // from the contract (that would be a tautological recompute of line 40). + // ========================================================================== + function prove_gasPolicy_noUnderCharge( + bytes32 id, + uint256 preVG, + uint128 vgl, + uint128 cgl, + uint128 mfpg, + uint128 allowedPre + ) public { + // Bound preVG so the sum fits well under uint256 and the product cannot wrap. + // sum <= 2^130, mfpg <= 2^128 => product <= 2^258 < 2^256? No — bound tighter: + // require sum * mfpg < 2^256 by bounding operands. + vm.assume(preVG <= type(uint96).max); // sum < 2^97 + // vgl, cgl are uint128 -> sum of three < 2^129; but with preVG<=2^96 sum<2^130. + // To guarantee product representable, bound mfpg so sum*mfpg < 2^256. + // sum < 2^130, so require mfpg < 2^126 => product < 2^256. + vm.assume(mfpg < (uint128(1) << 126)); + + _installLive(id, allowedPre); + PackedUserOperation memory op = _buildOp(preVG, vgl, cgl, mfpg); + + // Independent reference cost in full uint256 (does not touch the contract). + uint256 trueCost = (preVG + uint256(vgl) + uint256(cgl)) * uint256(mfpg); + + vm.prank(address(this)); + uint256 ret = policy.checkUserOpPolicy(id, op); + + (uint128 allowedPost,,) = policy.gasPolicyConfig(id, address(this)); + + if (ret == SUCCESS) { + // (a) true cost within budget AND budget decreased by exactly trueCost. + assert(trueCost <= uint256(allowedPre)); + assert(uint256(allowedPost) == uint256(allowedPre) - trueCost); + } + // (c) monotone non-increasing always. + assert(uint256(allowedPost) <= uint256(allowedPre)); + } + + // ========================================================================== + // Reachability witness for the truncation boundary: + // vgl = 2^80, mfpg = 2^48 => product == 2^128 exactly, low128 == 0. A uint128 + // truncation would pass this huge cost as 0; the contract MUST reject it + // whenever allowedPre < 2^128. KEVM checks the MUL + downcast at the exact bit. + // ========================================================================== + function prove_gasPolicy_boundaryRejected(bytes32 id, uint128 allowedPre) public { + vgl_boundary_helper(id, allowedPre); + } + + function vgl_boundary_helper(bytes32 id, uint128 allowedPre) internal { + // allowedPre is uint128 => strictly < 2^128 == trueCost, so must be rejected. + _installLive(id, allowedPre); + + uint128 vgl = uint128(1) << 80; // 2^80 + uint128 mfpg = uint128(1) << 48; // 2^48 + // trueCost = 2^80 * 2^48 = 2^128 (preVG=cgl=0) + PackedUserOperation memory op = _buildOp(0, vgl, 0, mfpg); + + uint256 trueCost = (uint256(vgl) + 0 + 0) * uint256(mfpg); + // trueCost == 2^128 > any uint128 allowedPre. + assert(trueCost > uint256(allowedPre)); + + vm.prank(address(this)); + uint256 ret = policy.checkUserOpPolicy(id, op); + + (uint128 allowedPost,,) = policy.gasPolicyConfig(id, address(this)); + + // (b) over-cap op MUST NOT return SUCCESS; budget untouched. + assert(ret == FAILED); + assert(allowedPost == allowedPre); + } + + // ========================================================================== + // Reachability witness that SUCCESS is reachable (non-vacuity): concrete + // assignment with trueCost <= allowed. If this reverts / is infeasible the + // main proof would be vacuous. + // ========================================================================== + function prove_gasPolicy_successReachable(bytes32 id) public { + _installLive(id, 1000); + PackedUserOperation memory op = _buildOp(10, 20, 30, 5); // cost = 60*5 = 300 + + vm.prank(address(this)); + uint256 ret = policy.checkUserOpPolicy(id, op); + (uint128 allowedPost,,) = policy.gasPolicyConfig(id, address(this)); + + assert(ret == SUCCESS); + assert(allowedPost == 700); // 1000 - 300 + } + + // ========================================================================== + // With enforcePaymaster=true, allowedPaymaster != 0, and + // paymasterAndData.length < 20, the function returns FAILED and does NOT + // revert on the [0:20] slice (line 46 guard short-circuits before the slice). + // ========================================================================== + function prove_gasPolicy_paymasterShortDataNoRevert(bytes32 id, address pm) public { + vm.assume(pm != address(0)); + + vm.prank(address(this)); + policy.onInstall(abi.encodePacked(id, abi.encode(uint128(type(uint128).max), true, pm))); + + PackedUserOperation memory op = _buildOp(1, 1, 1, 1); + op.paymasterAndData = hex"1122334455"; // length 5 < 20 + + vm.prank(address(this)); + uint256 ret = policy.checkUserOpPolicy(id, op); + + assert(ret == FAILED); + } +} diff --git a/test/kontrol/TimelockPolicyKontrol.t.sol b/test/kontrol/TimelockPolicyKontrol.t.sol new file mode 100644 index 0000000..b071596 --- /dev/null +++ b/test/kontrol/TimelockPolicyKontrol.t.sol @@ -0,0 +1,165 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.30; + +/// @author taek +/// +/// Kontrol (KEVM) proof: a proposal created under a prior installation +/// can NEVER validate for execution after reinstall. The epoch bump in +/// _policyOninstall (currentEpoch++) plus the epoch guard in +/// _handleProposalExecutionInternal (proposal.epoch != currentEpoch => FAILED) +/// together make any stale-epoch proposal un-executable. +/// +/// KEVM's value over Halmos/Certora here: the execution path runs the exact +/// compiled bytecode of checkUserOpPolicy -> _validateUserOpPolicy -> +/// _handleProposalExecutionInternal, including the SLOAD of the nested +/// proposals[keccak(...)] and currentEpoch mappings and the keccak of the +/// userOpKey — grounded at the opcode level, not at Solidity-source level. +/// +/// Run: +/// kontrol build +/// kontrol prove --match-test 'TimelockPolicyKontrol.prove_staleEpochProposalRejected' +/// kontrol prove --match-test 'TimelockPolicyKontrol.prove_matchingEpochSuccessReachable' +/// kontrol prove --match-test 'TimelockPolicyKontrol.prove_crossEpochStaleStateReachable' + +import {Test} from "forge-std/Test.sol"; +import {KontrolCheats} from "kontrol-cheatcodes/KontrolCheats.sol"; +import {PackedUserOperation} from "account-abstraction/interfaces/PackedUserOperation.sol"; +import {TimelockPolicy} from "src/policies/TimelockPolicy.sol"; + +contract TimelockPolicyKontrol is Test, KontrolCheats { + TimelockPolicy internal policy; + + uint256 constant SUCCESS_AUTHORIZER = 0; // low 160 bits == 0 on success + uint256 constant FAILED = 1; // SIG_VALIDATION_FAILED_UINT + + function setUp() public { + policy = new TimelockPolicy(); + } + + // A non-no-op callData: 4 bytes that are NOT executeUserOp/execute selectors and + // length < 100 so _isNoOpCalldata returns false and we hit the EXECUTION path. + function _execCallData() internal pure returns (bytes memory) { + return hex"deadbeef"; + } + + function _buildExecOp(uint256 nonce) internal pure returns (PackedUserOperation memory op) { + op.sender = address(0xA11CE); + op.nonce = nonce; + op.callData = _execCallData(); + } + + // Install a config (delay/expiration valid) so config.initialized == true and the + // execution path is reached rather than the not-initialized early return. + function _install(bytes32 id) internal { + uint48 delay = 1; + uint48 expiration = 1; + // guardian = 0 + bytes memory data = abi.encode(delay, expiration, address(0)); + vm.prank(address(0xA11CE)); + policy.onInstall(abi.encodePacked(id, data)); + } + + // Legitimately create a Pending proposal for (sender, callData, nonce) by sending a + // no-op UserOp whose signature carries the proposal (callData,nonce). This stamps + // proposal.epoch = currentEpoch at creation time. + function _createProposal(bytes32 id, bytes memory callData, uint256 nonce) internal { + PackedUserOperation memory op; + op.sender = address(0xA11CE); + op.nonce = 999; // the CURRENT op nonce is irrelevant; proposal keyed by sig data + op.callData = ""; // empty => no-op path => creation + + // sig format: [callDataLen(32)][callData][nonce(32)] + op.signature = abi.encodePacked(bytes32(callData.length), callData, bytes32(nonce)); + vm.prank(address(0xA11CE)); + policy.checkUserOpPolicy(id, op); + } + + // ========================================================================== + // MAIN discriminator (OBSERVABLE, non-tautological): a Pending proposal stamped + // at the pre-reinstall epoch, with currentEpoch advanced by a genuine reinstall, + // causes the execution path to return the FAILED sentinel. Inputs id and nonce + // are SYMBOLIC, so this covers every proposal key. Crucially we do NOT havoc + // storage (symbolicStorage produced out-of-range enum bytes -> spurious reverts); + // instead the mismatch is created through the contract's own transitions + // (create @ epoch 1, uninstall, reinstall -> epoch 2), which is both sound and + // keeps status/config bytes well-formed. We assert the observable return == + // FAILED, NOT a recomputation of the epoch counter. + // ========================================================================== + function prove_staleEpochProposalRejected(bytes32 id, uint256 nonce) public { + _install(id); // currentEpoch: 0 -> 1 + + bytes memory callData = _execCallData(); + _createProposal(id, callData, nonce); // proposal.epoch = 1, status = Pending + + // Advance currentEpoch via a real reinstall (simulating account reinstall). + vm.prank(address(0xA11CE)); + policy.onUninstall(abi.encodePacked(id, bytes(""))); + _install(id); // currentEpoch: 1 -> 2 => proposal.epoch (1) != currentEpoch (2) + + // Precondition witness (bound, not asserted-as-postcondition): the mismatch holds. + vm.assume(_readProposalEpoch(id, callData, nonce) != policy.currentEpoch(id, address(0xA11CE))); + + PackedUserOperation memory op = _buildExecOp(nonce); + vm.prank(address(0xA11CE)); + uint256 ret = policy.checkUserOpPolicy(id, op); + + // OBSERVABLE postcondition: mismatch => FAILED sentinel, never a success window. + assert(ret == FAILED); + } + + // ========================================================================== + // REACHABILITY witness #1 (non-vacuity): the SUCCESS path is reachable. Matching + // epoch, Pending, initialized => execution returns a success validationData whose + // low-160 authorizer bits are 0 (i.e. NOT the FAILED sentinel). If this were + // infeasible the main proof's FAILED would not be a real discriminator. + // ========================================================================== + function prove_matchingEpochSuccessReachable(bytes32 id, uint256 nonce) public { + _install(id); + bytes memory callData = _execCallData(); + _createProposal(id, callData, nonce); // epoch == currentEpoch, Pending + + PackedUserOperation memory op = _buildExecOp(nonce); + vm.prank(address(0xA11CE)); + uint256 ret = policy.checkUserOpPolicy(id, op); + + // Success: low 160 bits (authorizer) are 0, and it is NOT the FAILED sentinel. + assert(ret != FAILED); + assert((ret & ((uint256(1) << 160) - 1)) == SUCCESS_AUTHORIZER); + } + + // ========================================================================== + // REACHABILITY witness #2 (genuine cross-epoch stale state is reachable): drive + // the actual multi-step trace install -> create -> uninstall -> reinstall (bumps + // currentEpoch) and confirm the resulting proposal.epoch != currentEpoch AND that + // execution then returns FAILED. This proves the stale state is not merely a + // symbolic artifact but attainable through the contract's own transitions. + // ========================================================================== + function prove_crossEpochStaleStateReachable(bytes32 id) public { + uint256 nonce = 7; + bytes memory callData = _execCallData(); + + _install(id); // currentEpoch: 0 -> 1 + _createProposal(id, callData, nonce); // proposal.epoch = 1, Pending + + // Uninstall then reinstall to bump the epoch (simulating account reinstall). + vm.prank(address(0xA11CE)); + policy.onUninstall(abi.encodePacked(id, bytes(""))); + _install(id); // currentEpoch: 1 -> 2 + + uint256 cur = policy.currentEpoch(id, address(0xA11CE)); + uint256 propEpoch = _readProposalEpoch(id, callData, nonce); + assert(propEpoch != cur); // genuine stale state reached (1 != 2) + + PackedUserOperation memory op = _buildExecOp(nonce); + vm.prank(address(0xA11CE)); + uint256 ret = policy.checkUserOpPolicy(id, op); + assert(ret == FAILED); + } + + // Read proposal.epoch via the public `proposals` mapping getter. + function _readProposalEpoch(bytes32 id, bytes memory callData, uint256 nonce) internal view returns (uint256) { + bytes32 userOpKey = keccak256(abi.encode(address(0xA11CE), keccak256(callData), nonce)); + (,,, uint256 epoch) = policy.proposals(userOpKey, id, address(0xA11CE)); + return epoch; + } +} diff --git a/test/mocks/MockValidator.sol b/test/mocks/MockValidator.sol new file mode 100644 index 0000000..6b9ab72 --- /dev/null +++ b/test/mocks/MockValidator.sol @@ -0,0 +1,41 @@ +pragma solidity ^0.8.0; + +import {IValidator} from "src/interfaces/IERC7579Modules.sol"; +import {PackedUserOperation} from "account-abstraction/interfaces/PackedUserOperation.sol"; + +/// @notice Minimal IValidator mock that records onInstall/onUninstall calls for assertions. +contract MockValidator is IValidator { + uint256 public onInstallCallCount; + uint256 public onUninstallCallCount; + bytes public lastOnInstallData; + bytes public lastOnUninstallData; + + // Records call order so tests can assert onUninstall happens strictly before onInstall. + uint256 public onUninstallCallOrder; + uint256 public onInstallCallOrder; + uint256 internal callCounter; + + function onInstall(bytes calldata data) external payable override { + onInstallCallCount++; + lastOnInstallData = data; + onInstallCallOrder = ++callCounter; + } + + function onUninstall(bytes calldata data) external payable override { + onUninstallCallCount++; + lastOnUninstallData = data; + onUninstallCallOrder = ++callCounter; + } + + function isModuleType(uint256) external pure override returns (bool) { + return true; + } + + function validateUserOp(PackedUserOperation calldata, bytes32) external payable override returns (uint256) { + return 0; + } + + function isValidSignatureWithSender(address, bytes32, bytes calldata) external pure override returns (bytes4) { + return 0x1626ba7e; + } +}