From 285da3145493d77622585d22e39939facf2330d1 Mon Sep 17 00:00:00 2001 From: Hadrien Croubois Date: Thu, 9 Jan 2025 11:47:33 +0100 Subject: [PATCH 1/4] Add a Calldata library to host otherwise duplicated emptyCalldataBytes and emptyCalldataString. --- .../account/utils/draft-ERC4337Utils.sol | 13 +++------- contracts/utils/Calldata.sol | 24 +++++++++++++++++++ 2 files changed, 27 insertions(+), 10 deletions(-) create mode 100644 contracts/utils/Calldata.sol diff --git a/contracts/account/utils/draft-ERC4337Utils.sol b/contracts/account/utils/draft-ERC4337Utils.sol index 355b0720b41..4221ca0308d 100644 --- a/contracts/account/utils/draft-ERC4337Utils.sol +++ b/contracts/account/utils/draft-ERC4337Utils.sol @@ -4,6 +4,7 @@ pragma solidity ^0.8.20; import {PackedUserOperation} from "../../interfaces/draft-IERC4337.sol"; import {Math} from "../../utils/math/Math.sol"; +import {Calldata} from "../../utils/Calldata.sol"; import {Packing} from "../../utils/Packing.sol"; /** @@ -106,7 +107,7 @@ library ERC4337Utils { /// @dev Returns `factoryData` from the {PackedUserOperation}, or empty bytes if the initCode is empty or not properly formatted. function factoryData(PackedUserOperation calldata self) internal pure returns (bytes calldata) { - return self.initCode.length < 20 ? _emptyCalldataBytes() : self.initCode[20:]; + return self.initCode.length < 20 ? Calldata.emptyBytes() : self.initCode[20:]; } /// @dev Returns `verificationGasLimit` from the {PackedUserOperation}. @@ -156,14 +157,6 @@ library ERC4337Utils { /// @dev Returns the fourth section of `paymasterAndData` from the {PackedUserOperation}. function paymasterData(PackedUserOperation calldata self) internal pure returns (bytes calldata) { - return self.paymasterAndData.length < 52 ? _emptyCalldataBytes() : self.paymasterAndData[52:]; - } - - // slither-disable-next-line write-after-write - function _emptyCalldataBytes() private pure returns (bytes calldata result) { - assembly ("memory-safe") { - result.offset := 0 - result.length := 0 - } + return self.paymasterAndData.length < 52 ? Calldata.emptyBytes() : self.paymasterAndData[52:]; } } diff --git a/contracts/utils/Calldata.sol b/contracts/utils/Calldata.sol new file mode 100644 index 00000000000..46b8387bace --- /dev/null +++ b/contracts/utils/Calldata.sol @@ -0,0 +1,24 @@ +// SPDX-License-Identifier: MIT + +pragma solidity ^0.8.24; + +/** + * @dev Helper library for manipulating objects in calldata. + */ +library Calldata { + // slither-disable-next-line write-after-write + function emptyBytes() internal pure returns (bytes calldata result) { + assembly ("memory-safe") { + result.offset := 0 + result.length := 0 + } + } + + // slither-disable-next-line write-after-write + function emptyString() internal pure returns (string calldata result) { + assembly ("memory-safe") { + result.offset := 0 + result.length := 0 + } + } +} From 5a415fc4635a6c9a70e5492772f1b00c5bc80393 Mon Sep 17 00:00:00 2001 From: Hadrien Croubois Date: Thu, 9 Jan 2025 17:20:09 +0100 Subject: [PATCH 2/4] fix pragma & add tests --- contracts/utils/Calldata.sol | 2 +- test/utils/Calldata.test.js | 22 ++++++++++++++++++++++ 2 files changed, 23 insertions(+), 1 deletion(-) create mode 100644 test/utils/Calldata.test.js diff --git a/contracts/utils/Calldata.sol b/contracts/utils/Calldata.sol index 46b8387bace..60e0b08b015 100644 --- a/contracts/utils/Calldata.sol +++ b/contracts/utils/Calldata.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: MIT -pragma solidity ^0.8.24; +pragma solidity ^0.8.20; /** * @dev Helper library for manipulating objects in calldata. diff --git a/test/utils/Calldata.test.js b/test/utils/Calldata.test.js new file mode 100644 index 00000000000..7e9d3d47813 --- /dev/null +++ b/test/utils/Calldata.test.js @@ -0,0 +1,22 @@ +const { ethers } = require('hardhat'); +const { expect } = require('chai'); +const { loadFixture } = require('@nomicfoundation/hardhat-network-helpers'); + +async function fixture() { + const mock = await ethers.deployContract('$Calldata'); + return { mock }; +} + +describe('Calldata utilities', function () { + beforeEach(async function () { + Object.assign(this, await loadFixture(fixture)); + }); + + it('emptyBytes', async function () { + await expect(this.mock.$emptyBytes()).to.eventually.equal('0x'); + }); + + it('emptyString', async function () { + await expect(this.mock.$emptyString()).to.eventually.equal(''); + }); +}); From 55ffd0c3bf3050ef86602f5dabc01ebb454bc998 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ernesto=20Garc=C3=ADa?= Date: Thu, 9 Jan 2025 19:46:27 -0600 Subject: [PATCH 3/4] Create good-cameras-serve.md --- .changeset/good-cameras-serve.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/good-cameras-serve.md diff --git a/.changeset/good-cameras-serve.md b/.changeset/good-cameras-serve.md new file mode 100644 index 00000000000..f0040d35c8f --- /dev/null +++ b/.changeset/good-cameras-serve.md @@ -0,0 +1,5 @@ +--- +"openzeppelin-solidity": minor +--- + +`Calldata`: Library with `emptyCalldataBytes` and `emptyCalldataString` functions to generate empty `bytes` and `string` calldata types. From abd1097e9468442f755305028df59768a34cd597 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ernesto=20Garc=C3=ADa?= Date: Thu, 9 Jan 2025 19:47:27 -0600 Subject: [PATCH 4/4] Update .changeset/good-cameras-serve.md --- .changeset/good-cameras-serve.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.changeset/good-cameras-serve.md b/.changeset/good-cameras-serve.md index f0040d35c8f..1f1895504dd 100644 --- a/.changeset/good-cameras-serve.md +++ b/.changeset/good-cameras-serve.md @@ -2,4 +2,4 @@ "openzeppelin-solidity": minor --- -`Calldata`: Library with `emptyCalldataBytes` and `emptyCalldataString` functions to generate empty `bytes` and `string` calldata types. +`Calldata`: Library with `emptyBytes` and `emptyString` functions to generate empty `bytes` and `string` calldata types.