Skip to content

Commit

Permalink
Add a Calldata library with emptyBytes and emptyString functions (#…
Browse files Browse the repository at this point in the history
…5422)

Co-authored-by: Ernesto García <[email protected]>
  • Loading branch information
Amxx and ernestognw authored Jan 10, 2025
1 parent 7b74442 commit 352ab13
Show file tree
Hide file tree
Showing 4 changed files with 54 additions and 10 deletions.
5 changes: 5 additions & 0 deletions .changeset/good-cameras-serve.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"openzeppelin-solidity": minor
---

`Calldata`: Library with `emptyBytes` and `emptyString` functions to generate empty `bytes` and `string` calldata types.
13 changes: 3 additions & 10 deletions contracts/account/utils/draft-ERC4337Utils.sol
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,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";

/**
Expand Down Expand Up @@ -107,7 +108,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}.
Expand Down Expand Up @@ -157,14 +158,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:];
}
}
24 changes: 24 additions & 0 deletions contracts/utils/Calldata.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.20;

/**
* @dev Helper library for manipulating objects in calldata.
*/
library Calldata {
// slither-disable-next-line write-after-write
function emptyBytes() internal pure returns (bytes calldata result) {
assembly ("memory-safe") {
result.offset := 0
result.length := 0
}
}

// slither-disable-next-line write-after-write
function emptyString() internal pure returns (string calldata result) {
assembly ("memory-safe") {
result.offset := 0
result.length := 0
}
}
}
22 changes: 22 additions & 0 deletions test/utils/Calldata.test.js
Original file line number Diff line number Diff line change
@@ -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('');
});
});

0 comments on commit 352ab13

Please sign in to comment.