aboutsummaryrefslogtreecommitdiffstats
path: root/packages
diff options
context:
space:
mode:
authorGreg Hysen <greg.hysen@gmail.com>2018-08-30 02:39:52 +0800
committerGreg Hysen <greg.hysen@gmail.com>2018-08-30 02:39:52 +0800
commit1c3b2b7141138f8da82197dfbdbdbfd76e7780b7 (patch)
tree729805d651424b1fc9ff8c8f7effc01d58efdcdf /packages
parentf44644ad9029148c43f69d666356ed9fb18de4e2 (diff)
downloaddexon-0x-contracts-1c3b2b7141138f8da82197dfbdbdbfd76e7780b7.tar
dexon-0x-contracts-1c3b2b7141138f8da82197dfbdbdbfd76e7780b7.tar.gz
dexon-0x-contracts-1c3b2b7141138f8da82197dfbdbdbfd76e7780b7.tar.bz2
dexon-0x-contracts-1c3b2b7141138f8da82197dfbdbdbfd76e7780b7.tar.lz
dexon-0x-contracts-1c3b2b7141138f8da82197dfbdbdbfd76e7780b7.tar.xz
dexon-0x-contracts-1c3b2b7141138f8da82197dfbdbdbfd76e7780b7.tar.zst
dexon-0x-contracts-1c3b2b7141138f8da82197dfbdbdbfd76e7780b7.zip
Updated readBytes4 to match spec + added unit tests. These are 3.5/3.6 from audit
Diffstat (limited to 'packages')
-rw-r--r--packages/contracts/src/2.0.0/protocol/AssetProxyOwner/AssetProxyOwner.sol13
-rw-r--r--packages/contracts/src/2.0.0/utils/LibBytes/LibBytes.sol7
-rw-r--r--packages/contracts/test/libraries/lib_bytes.ts26
3 files changed, 42 insertions, 4 deletions
diff --git a/packages/contracts/src/2.0.0/protocol/AssetProxyOwner/AssetProxyOwner.sol b/packages/contracts/src/2.0.0/protocol/AssetProxyOwner/AssetProxyOwner.sol
index 8b7333646..e661f2427 100644
--- a/packages/contracts/src/2.0.0/protocol/AssetProxyOwner/AssetProxyOwner.sol
+++ b/packages/contracts/src/2.0.0/protocol/AssetProxyOwner/AssetProxyOwner.sol
@@ -105,11 +105,20 @@ contract AssetProxyOwner is
uint256 index
)
internal
+ pure
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 {
- result := mload(add(b, 32))
+ result := mload(add(b, index))
// Solidity does not require us to clean the trailing bytes.
// We do it anyway
result := and(result, 0xFFFFFFFF00000000000000000000000000000000000000000000000000000000)
diff --git a/packages/contracts/src/2.0.0/utils/LibBytes/LibBytes.sol b/packages/contracts/src/2.0.0/utils/LibBytes/LibBytes.sol
index 504e950a8..93873cbcc 100644
--- a/packages/contracts/src/2.0.0/utils/LibBytes/LibBytes.sol
+++ b/packages/contracts/src/2.0.0/utils/LibBytes/LibBytes.sol
@@ -467,8 +467,13 @@ library LibBytes {
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 {
- result := mload(add(b, 32))
+ result := mload(add(b, index))
// Solidity does not require us to clean the trailing bytes.
// We do it anyway
result := and(result, 0xFFFFFFFF00000000000000000000000000000000000000000000000000000000)
diff --git a/packages/contracts/test/libraries/lib_bytes.ts b/packages/contracts/test/libraries/lib_bytes.ts
index 1c497a226..6fda9dc97 100644
--- a/packages/contracts/test/libraries/lib_bytes.ts
+++ b/packages/contracts/test/libraries/lib_bytes.ts
@@ -41,6 +41,8 @@ describe('LibBytes', () => {
const testBytes32B = '0x534877abd8443578526845cdfef020047528759477fedef87346527659aced32';
const testUint256 = new BigNumber(testBytes32, 16);
const testUint256B = new BigNumber(testBytes32B, 16);
+ const testBytes4 = '0xabcdef12';
+ const testBytes4B = new BigNumber(testBytes4, 16);
let shortData: string;
let shortTestBytes: string;
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'
it('should revert if byte array has a length < 4', async () => {
const byteArrayLessThan4Bytes = '0x010101';
+ const offset = new BigNumber(0);
return expectContractCallFailed(
- libBytes.publicReadBytes4.callAsync(byteArrayLessThan4Bytes, new BigNumber(0)),
+ libBytes.publicReadBytes4.callAsync(byteArrayLessThan4Bytes, offset),
RevertReason.LibBytesGreaterOrEqualTo4LengthRequired,
);
});
@@ -472,6 +475,27 @@ describe('LibBytes', () => {
const expectedFirst4Bytes = byteArrayLongerThan32Bytes.slice(0, 10);
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', () => {