Updated readBytes4 to match spec + added unit tests. These are 3.5/3.6 from audit
This commit is contained in:
parent
f44644ad90
commit
1c3b2b7141
@ -105,11 +105,20 @@ contract AssetProxyOwner is
|
|||||||
uint256 index
|
uint256 index
|
||||||
)
|
)
|
||||||
internal
|
internal
|
||||||
|
pure
|
||||||
returns (bytes4 result)
|
returns (bytes4 result)
|
||||||
{
|
{
|
||||||
require(b.length >= index + 4);
|
require(
|
||||||
|
b.length >= index + 4,
|
||||||
|
"GREATER_OR_EQUAL_TO_4_LENGTH_REQUIRED"
|
||||||
|
);
|
||||||
|
|
||||||
|
// Arrays are prefixed by a 32 byte length field
|
||||||
|
index += 32;
|
||||||
|
|
||||||
|
// Read the bytes4 from array memory
|
||||||
assembly {
|
assembly {
|
||||||
result := mload(add(b, 32))
|
result := mload(add(b, index))
|
||||||
// Solidity does not require us to clean the trailing bytes.
|
// Solidity does not require us to clean the trailing bytes.
|
||||||
// We do it anyway
|
// We do it anyway
|
||||||
result := and(result, 0xFFFFFFFF00000000000000000000000000000000000000000000000000000000)
|
result := and(result, 0xFFFFFFFF00000000000000000000000000000000000000000000000000000000)
|
||||||
|
@ -467,8 +467,13 @@ library LibBytes {
|
|||||||
b.length >= index + 4,
|
b.length >= index + 4,
|
||||||
"GREATER_OR_EQUAL_TO_4_LENGTH_REQUIRED"
|
"GREATER_OR_EQUAL_TO_4_LENGTH_REQUIRED"
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// Arrays are prefixed by a 32 byte length field
|
||||||
|
index += 32;
|
||||||
|
|
||||||
|
// Read the bytes4 from array memory
|
||||||
assembly {
|
assembly {
|
||||||
result := mload(add(b, 32))
|
result := mload(add(b, index))
|
||||||
// Solidity does not require us to clean the trailing bytes.
|
// Solidity does not require us to clean the trailing bytes.
|
||||||
// We do it anyway
|
// We do it anyway
|
||||||
result := and(result, 0xFFFFFFFF00000000000000000000000000000000000000000000000000000000)
|
result := and(result, 0xFFFFFFFF00000000000000000000000000000000000000000000000000000000)
|
||||||
|
@ -41,6 +41,8 @@ describe('LibBytes', () => {
|
|||||||
const testBytes32B = '0x534877abd8443578526845cdfef020047528759477fedef87346527659aced32';
|
const testBytes32B = '0x534877abd8443578526845cdfef020047528759477fedef87346527659aced32';
|
||||||
const testUint256 = new BigNumber(testBytes32, 16);
|
const testUint256 = new BigNumber(testBytes32, 16);
|
||||||
const testUint256B = new BigNumber(testBytes32B, 16);
|
const testUint256B = new BigNumber(testBytes32B, 16);
|
||||||
|
const testBytes4 = '0xabcdef12';
|
||||||
|
const testBytes4B = new BigNumber(testBytes4, 16);
|
||||||
let shortData: string;
|
let shortData: string;
|
||||||
let shortTestBytes: string;
|
let shortTestBytes: string;
|
||||||
let shortTestBytesAsBuffer: Buffer;
|
let shortTestBytesAsBuffer: Buffer;
|
||||||
@ -462,8 +464,9 @@ describe('LibBytes', () => {
|
|||||||
// AssertionError: expected promise to be rejected with an error including 'revert' but it was fulfilled with '0x08c379a0'
|
// AssertionError: expected promise to be rejected with an error including 'revert' but it was fulfilled with '0x08c379a0'
|
||||||
it('should revert if byte array has a length < 4', async () => {
|
it('should revert if byte array has a length < 4', async () => {
|
||||||
const byteArrayLessThan4Bytes = '0x010101';
|
const byteArrayLessThan4Bytes = '0x010101';
|
||||||
|
const offset = new BigNumber(0);
|
||||||
return expectContractCallFailed(
|
return expectContractCallFailed(
|
||||||
libBytes.publicReadBytes4.callAsync(byteArrayLessThan4Bytes, new BigNumber(0)),
|
libBytes.publicReadBytes4.callAsync(byteArrayLessThan4Bytes, offset),
|
||||||
RevertReason.LibBytesGreaterOrEqualTo4LengthRequired,
|
RevertReason.LibBytesGreaterOrEqualTo4LengthRequired,
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
@ -472,6 +475,27 @@ describe('LibBytes', () => {
|
|||||||
const expectedFirst4Bytes = byteArrayLongerThan32Bytes.slice(0, 10);
|
const expectedFirst4Bytes = byteArrayLongerThan32Bytes.slice(0, 10);
|
||||||
expect(first4Bytes).to.equal(expectedFirst4Bytes);
|
expect(first4Bytes).to.equal(expectedFirst4Bytes);
|
||||||
});
|
});
|
||||||
|
it('should successfully read bytes4 when the bytes4 takes up the whole array', async () => {
|
||||||
|
const testBytes4Offset = new BigNumber(0);
|
||||||
|
const bytes4 = await libBytes.publicReadBytes4.callAsync(testBytes4, testBytes4Offset);
|
||||||
|
return expect(bytes4).to.be.equal(testBytes4);
|
||||||
|
});
|
||||||
|
it('should successfully read bytes4 when it is offset in the array)', async () => {
|
||||||
|
const bytes4ByteArrayBuffer = ethUtil.toBuffer(testBytes4);
|
||||||
|
const prefixByteArrayBuffer = ethUtil.toBuffer('0xabcdef');
|
||||||
|
const combinedByteArrayBuffer = Buffer.concat([prefixByteArrayBuffer, bytes4ByteArrayBuffer]);
|
||||||
|
const combinedByteArray = ethUtil.bufferToHex(combinedByteArrayBuffer);
|
||||||
|
const testBytes4Offset = new BigNumber(prefixByteArrayBuffer.byteLength);
|
||||||
|
const bytes4 = await libBytes.publicReadBytes4.callAsync(combinedByteArray, testBytes4Offset);
|
||||||
|
return expect(bytes4).to.be.equal(testBytes4);
|
||||||
|
});
|
||||||
|
it('should fail if the length between the offset and end of the byte array is too short to hold a bytes4', async () => {
|
||||||
|
const badOffset = new BigNumber(ethUtil.toBuffer(testBytes4).byteLength);
|
||||||
|
return expectContractCallFailed(
|
||||||
|
libBytes.publicReadBytes4.callAsync(testBytes4, badOffset),
|
||||||
|
RevertReason.LibBytesGreaterOrEqualTo4LengthRequired,
|
||||||
|
);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('readBytesWithLength', () => {
|
describe('readBytesWithLength', () => {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user