Skip to content

Commit 352ab13

Browse files
Amxxernestognw
andauthored
Add a Calldata library with emptyBytes and emptyString functions (#5422)
Co-authored-by: Ernesto García <ernestognw@gmail.com>
1 parent 7b74442 commit 352ab13

File tree

4 files changed

+54
-10
lines changed

4 files changed

+54
-10
lines changed

.changeset/good-cameras-serve.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"openzeppelin-solidity": minor
3+
---
4+
5+
`Calldata`: Library with `emptyBytes` and `emptyString` functions to generate empty `bytes` and `string` calldata types.

contracts/account/utils/draft-ERC4337Utils.sol

Lines changed: 3 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ pragma solidity ^0.8.20;
55

66
import {PackedUserOperation} from "../../interfaces/draft-IERC4337.sol";
77
import {Math} from "../../utils/math/Math.sol";
8+
import {Calldata} from "../../utils/Calldata.sol";
89
import {Packing} from "../../utils/Packing.sol";
910

1011
/**
@@ -107,7 +108,7 @@ library ERC4337Utils {
107108

108109
/// @dev Returns `factoryData` from the {PackedUserOperation}, or empty bytes if the initCode is empty or not properly formatted.
109110
function factoryData(PackedUserOperation calldata self) internal pure returns (bytes calldata) {
110-
return self.initCode.length < 20 ? _emptyCalldataBytes() : self.initCode[20:];
111+
return self.initCode.length < 20 ? Calldata.emptyBytes() : self.initCode[20:];
111112
}
112113

113114
/// @dev Returns `verificationGasLimit` from the {PackedUserOperation}.
@@ -157,14 +158,6 @@ library ERC4337Utils {
157158

158159
/// @dev Returns the fourth section of `paymasterAndData` from the {PackedUserOperation}.
159160
function paymasterData(PackedUserOperation calldata self) internal pure returns (bytes calldata) {
160-
return self.paymasterAndData.length < 52 ? _emptyCalldataBytes() : self.paymasterAndData[52:];
161-
}
162-
163-
// slither-disable-next-line write-after-write
164-
function _emptyCalldataBytes() private pure returns (bytes calldata result) {
165-
assembly ("memory-safe") {
166-
result.offset := 0
167-
result.length := 0
168-
}
161+
return self.paymasterAndData.length < 52 ? Calldata.emptyBytes() : self.paymasterAndData[52:];
169162
}
170163
}

contracts/utils/Calldata.sol

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
// SPDX-License-Identifier: MIT
2+
3+
pragma solidity ^0.8.20;
4+
5+
/**
6+
* @dev Helper library for manipulating objects in calldata.
7+
*/
8+
library Calldata {
9+
// slither-disable-next-line write-after-write
10+
function emptyBytes() internal pure returns (bytes calldata result) {
11+
assembly ("memory-safe") {
12+
result.offset := 0
13+
result.length := 0
14+
}
15+
}
16+
17+
// slither-disable-next-line write-after-write
18+
function emptyString() internal pure returns (string calldata result) {
19+
assembly ("memory-safe") {
20+
result.offset := 0
21+
result.length := 0
22+
}
23+
}
24+
}

test/utils/Calldata.test.js

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
const { ethers } = require('hardhat');
2+
const { expect } = require('chai');
3+
const { loadFixture } = require('@nomicfoundation/hardhat-network-helpers');
4+
5+
async function fixture() {
6+
const mock = await ethers.deployContract('$Calldata');
7+
return { mock };
8+
}
9+
10+
describe('Calldata utilities', function () {
11+
beforeEach(async function () {
12+
Object.assign(this, await loadFixture(fixture));
13+
});
14+
15+
it('emptyBytes', async function () {
16+
await expect(this.mock.$emptyBytes()).to.eventually.equal('0x');
17+
});
18+
19+
it('emptyString', async function () {
20+
await expect(this.mock.$emptyString()).to.eventually.equal('');
21+
});
22+
});

0 commit comments

Comments
 (0)