Add a Calldata library with `emptyBytes` and `emptyString` functions (#5422)

Co-authored-by: Ernesto García <ernestognw@gmail.com>
pull/5427/head
Hadrien Croubois 3 weeks ago committed by GitHub
parent 7b74442c5e
commit 352ab13687
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 5
      .changeset/good-cameras-serve.md
  2. 13
      contracts/account/utils/draft-ERC4337Utils.sol
  3. 24
      contracts/utils/Calldata.sol
  4. 22
      test/utils/Calldata.test.js

@ -0,0 +1,5 @@
---
"openzeppelin-solidity": minor
---
`Calldata`: Library with `emptyBytes` and `emptyString` functions to generate empty `bytes` and `string` calldata types.

@ -5,6 +5,7 @@ pragma solidity ^0.8.20;
import {PackedUserOperation} from "../../interfaces/draft-IERC4337.sol"; import {PackedUserOperation} from "../../interfaces/draft-IERC4337.sol";
import {Math} from "../../utils/math/Math.sol"; import {Math} from "../../utils/math/Math.sol";
import {Calldata} from "../../utils/Calldata.sol";
import {Packing} from "../../utils/Packing.sol"; import {Packing} from "../../utils/Packing.sol";
/** /**
@ -107,7 +108,7 @@ library ERC4337Utils {
/// @dev Returns `factoryData` from the {PackedUserOperation}, or empty bytes if the initCode is empty or not properly formatted. /// @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) { 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}. /// @dev Returns `verificationGasLimit` from the {PackedUserOperation}.
@ -157,14 +158,6 @@ library ERC4337Utils {
/// @dev Returns the fourth section of `paymasterAndData` from the {PackedUserOperation}. /// @dev Returns the fourth section of `paymasterAndData` from the {PackedUserOperation}.
function paymasterData(PackedUserOperation calldata self) internal pure returns (bytes calldata) { function paymasterData(PackedUserOperation calldata self) internal pure returns (bytes calldata) {
return self.paymasterAndData.length < 52 ? _emptyCalldataBytes() : self.paymasterAndData[52:]; return self.paymasterAndData.length < 52 ? Calldata.emptyBytes() : 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
}
} }
} }

@ -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
}
}
}

@ -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('');
});
});
Loading…
Cancel
Save