Release v5.2 audit fixes (#5330)
Signed-off-by: Hadrien Croubois <hadrien.croubois@gmail.com> Co-authored-by: Sam Bugs <101145325+0xsambugs@users.noreply.github.com> Co-authored-by: Ernesto García <ernestognw@gmail.com> Co-authored-by: Arr00 <13561405+arr00@users.noreply.github.com> Co-authored-by: wizard <112275929+famouswizard@users.noreply.github.com> Co-authored-by: leopardracer <136604165+leopardracer@users.noreply.github.com> Co-authored-by: cairo <cairoeth@protonmail.com>
This commit is contained in:
@ -86,7 +86,7 @@ function shouldBehaveLikeNoncesKeyed() {
|
||||
|
||||
await expect(this.mock.$_useNonce(sender, ethers.Typed.uint192(0n)))
|
||||
.to.emit(this.mock, 'return$_useNonce_address_uint192')
|
||||
.withArgs(1n);
|
||||
.withArgs(keyOffset(0n) + 1n);
|
||||
|
||||
expect(this.mock.nonces(sender, ethers.Typed.uint192(0n))).to.eventually.equal(keyOffset(0n) + 2n);
|
||||
expect(this.mock.nonces(sender, ethers.Typed.uint192(17n))).to.eventually.equal(keyOffset(17n) + 0n);
|
||||
@ -98,18 +98,18 @@ function shouldBehaveLikeNoncesKeyed() {
|
||||
|
||||
await expect(this.mock.$_useNonce(sender, ethers.Typed.uint192(17n)))
|
||||
.to.emit(this.mock, 'return$_useNonce_address_uint192')
|
||||
.withArgs(0n);
|
||||
.withArgs(keyOffset(17n) + 0n);
|
||||
|
||||
await expect(this.mock.$_useNonce(sender, ethers.Typed.uint192(17n)))
|
||||
.to.emit(this.mock, 'return$_useNonce_address_uint192')
|
||||
.withArgs(1n);
|
||||
.withArgs(keyOffset(17n) + 1n);
|
||||
|
||||
expect(this.mock.nonces(sender, ethers.Typed.uint192(0n))).to.eventually.equal(keyOffset(0n) + 0n);
|
||||
expect(this.mock.nonces(sender, ethers.Typed.uint192(17n))).to.eventually.equal(keyOffset(17n) + 2n);
|
||||
});
|
||||
});
|
||||
|
||||
describe('_useCheckedNonce', function () {
|
||||
describe('_useCheckedNonce(address, uint256)', function () {
|
||||
it('default variant uses key 0', async function () {
|
||||
const currentNonce = await this.mock.nonces(sender, ethers.Typed.uint192(0n));
|
||||
|
||||
@ -135,12 +135,49 @@ function shouldBehaveLikeNoncesKeyed() {
|
||||
// reuse same nonce
|
||||
await expect(this.mock.$_useCheckedNonce(sender, currentNonce))
|
||||
.to.be.revertedWithCustomError(this.mock, 'InvalidAccountNonce')
|
||||
.withArgs(sender, 1);
|
||||
.withArgs(sender, currentNonce + 1n);
|
||||
|
||||
// use "future" nonce too early
|
||||
await expect(this.mock.$_useCheckedNonce(sender, currentNonce + 10n))
|
||||
.to.be.revertedWithCustomError(this.mock, 'InvalidAccountNonce')
|
||||
.withArgs(sender, 1);
|
||||
.withArgs(sender, currentNonce + 1n);
|
||||
});
|
||||
});
|
||||
|
||||
describe('_useCheckedNonce(address, uint192, uint64)', function () {
|
||||
const MASK = 0xffffffffffffffffn;
|
||||
|
||||
it('default variant uses key 0', async function () {
|
||||
const currentNonce = await this.mock.nonces(sender, ethers.Typed.uint192(0n));
|
||||
|
||||
await this.mock.$_useCheckedNonce(sender, ethers.Typed.uint192(0n), currentNonce);
|
||||
|
||||
expect(this.mock.nonces(sender, ethers.Typed.uint192(0n))).to.eventually.equal(currentNonce + 1n);
|
||||
});
|
||||
|
||||
it('use nonce at another key', async function () {
|
||||
const currentNonce = await this.mock.nonces(sender, ethers.Typed.uint192(17n));
|
||||
|
||||
await this.mock.$_useCheckedNonce(sender, ethers.Typed.uint192(17n), currentNonce & MASK);
|
||||
|
||||
expect(this.mock.nonces(sender, ethers.Typed.uint192(17n))).to.eventually.equal(currentNonce + 1n);
|
||||
});
|
||||
|
||||
it('reverts when nonce is not the expected', async function () {
|
||||
const currentNonce = await this.mock.nonces(sender, ethers.Typed.uint192(42n));
|
||||
|
||||
// use and increment
|
||||
await this.mock.$_useCheckedNonce(sender, ethers.Typed.uint192(42n), currentNonce & MASK);
|
||||
|
||||
// reuse same nonce
|
||||
await expect(this.mock.$_useCheckedNonce(sender, ethers.Typed.uint192(42n), currentNonce & MASK))
|
||||
.to.be.revertedWithCustomError(this.mock, 'InvalidAccountNonce')
|
||||
.withArgs(sender, currentNonce + 1n);
|
||||
|
||||
// use "future" nonce too early
|
||||
await expect(this.mock.$_useCheckedNonce(sender, ethers.Typed.uint192(42n), (currentNonce & MASK) + 10n))
|
||||
.to.be.revertedWithCustomError(this.mock, 'InvalidAccountNonce')
|
||||
.withArgs(sender, currentNonce + 1n);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@ -24,4 +24,27 @@ contract StringsTest is Test {
|
||||
function testParseChecksumHex(address value) external {
|
||||
assertEq(value, value.toChecksumHexString().parseAddress());
|
||||
}
|
||||
|
||||
function testTryParseHexUintExtendedEnd(string memory random) external pure {
|
||||
uint256 length = bytes(random).length;
|
||||
assembly ("memory-safe") {
|
||||
mstore(add(add(random, 0x20), length), 0x3030303030303030303030303030303030303030303030303030303030303030)
|
||||
}
|
||||
|
||||
(bool success, ) = random.tryParseHexUint(1, length + 1);
|
||||
assertFalse(success);
|
||||
}
|
||||
|
||||
function testTryParseAddressExtendedEnd(address random, uint256 begin) external pure {
|
||||
begin = bound(begin, 3, 43);
|
||||
string memory input = random.toHexString();
|
||||
uint256 length = bytes(input).length;
|
||||
|
||||
assembly ("memory-safe") {
|
||||
mstore(add(add(input, 0x20), length), 0x3030303030303030303030303030303030303030303030303030303030303030)
|
||||
}
|
||||
|
||||
(bool success, ) = input.tryParseAddress(begin, begin + 40);
|
||||
assertFalse(success);
|
||||
}
|
||||
}
|
||||
|
||||
@ -240,6 +240,11 @@ describe('Strings', function () {
|
||||
expect(await this.mock.$tryParseUint('1 000')).deep.equal([false, 0n]);
|
||||
});
|
||||
|
||||
it('parseUint invalid range', async function () {
|
||||
expect(this.mock.$parseUint('12', 3, 2)).to.be.revertedWithCustomError(this.mock, 'StringsInvalidChar');
|
||||
expect(await this.mock.$tryParseUint('12', 3, 2)).to.deep.equal([false, 0n]);
|
||||
});
|
||||
|
||||
it('parseInt overflow', async function () {
|
||||
await expect(this.mock.$parseInt((ethers.MaxUint256 + 1n).toString(10))).to.be.revertedWithPanic(
|
||||
PANIC_CODES.ARITHMETIC_OVERFLOW,
|
||||
@ -276,6 +281,11 @@ describe('Strings', function () {
|
||||
expect(await this.mock.$tryParseInt('1 000')).to.deep.equal([false, 0n]);
|
||||
});
|
||||
|
||||
it('parseInt invalid range', async function () {
|
||||
expect(this.mock.$parseInt('-12', 3, 2)).to.be.revertedWithCustomError(this.mock, 'StringsInvalidChar');
|
||||
expect(await this.mock.$tryParseInt('-12', 3, 2)).to.deep.equal([false, 0n]);
|
||||
});
|
||||
|
||||
it('parseHexUint overflow', async function () {
|
||||
await expect(this.mock.$parseHexUint((ethers.MaxUint256 + 1n).toString(16))).to.be.revertedWithPanic(
|
||||
PANIC_CODES.ARITHMETIC_OVERFLOW,
|
||||
@ -303,6 +313,11 @@ describe('Strings', function () {
|
||||
expect(await this.mock.$tryParseHexUint('1 000')).to.deep.equal([false, 0n]);
|
||||
});
|
||||
|
||||
it('parseHexUint invalid begin and end', async function () {
|
||||
expect(this.mock.$parseHexUint('0x', 3, 2)).to.be.revertedWithCustomError(this.mock, 'StringsInvalidChar');
|
||||
expect(await this.mock.$tryParseHexUint('0x', 3, 2)).to.deep.equal([false, 0n]);
|
||||
});
|
||||
|
||||
it('parseAddress invalid format', async function () {
|
||||
for (const addr of [
|
||||
'0x736a507fB2881d6bB62dcA54673CF5295dC07833', // valid
|
||||
|
||||
Reference in New Issue
Block a user