Make LibBytes methods internal, add TestLibBytes

This commit is contained in:
Amir Bandeali
2018-05-04 17:00:24 -07:00
parent c84be8ddb3
commit bbf088d903
5 changed files with 180 additions and 33 deletions

View File

@@ -30,9 +30,9 @@
},
"config": {
"abis":
"../migrations/src/artifacts/@(DummyERC20Token|Exchange|TokenRegistry|MultiSigWallet|MultiSigWalletWithTimeLock|MultiSigWalletWithTimeLockExceptRemoveAuthorizedAddress|TokenRegistry|ZRXToken|TestAssetProxyDispatcher|TestLibs|TestSignatureValidator|ERC20Proxy|ERC721Proxy|DummyERC721Token|LibBytes|Authorizable).json",
"../migrations/src/artifacts/@(DummyERC20Token|Exchange|TokenRegistry|MultiSigWallet|MultiSigWalletWithTimeLock|MultiSigWalletWithTimeLockExceptRemoveAuthorizedAddress|TokenRegistry|ZRXToken|TestAssetProxyDispatcher|TestLibs|TestSignatureValidator|ERC20Proxy|ERC721Proxy|DummyERC721Token|TestLibBytes|Authorizable).json",
"contracts":
"Exchange,DummyERC20Token,ZRXToken,WETH9,MultiSigWallet,MultiSigWalletWithTimeLock,MultiSigWalletWithTimeLockExceptRemoveAuthorizedAddress,TokenRegistry,TestAssetProxyDispatcher,TestLibs,TestSignatureValidator,ERC20Proxy,ERC721Proxy,DummyERC721Token,LibBytes,Authorizable"
"Exchange,DummyERC20Token,ZRXToken,WETH9,MultiSigWallet,MultiSigWalletWithTimeLock,MultiSigWalletWithTimeLockExceptRemoveAuthorizedAddress,TokenRegistry,TestAssetProxyDispatcher,TestLibs,TestSignatureValidator,ERC20Proxy,ERC721Proxy,DummyERC721Token,TestLibBytes,Authorizable"
},
"repository": {
"type": "git",

View File

@@ -0,0 +1,133 @@
/*
Copyright 2018 ZeroEx Intl.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
pragma solidity ^0.4.23;
pragma experimental ABIEncoderV2;
import "../../utils/LibBytes/LibBytes.sol";
contract TestLibBytes is
LibBytes
{
/// @dev Tests equality of two byte arrays.
/// @param lhs First byte array to compare.
/// @param rhs Second byte array to compare.
/// @return True if arrays are the same. False otherwise.
function publicAreBytesEqual(bytes memory lhs, bytes memory rhs)
public
pure
returns (bool equal)
{
equal = areBytesEqual(lhs, rhs);
return equal;
}
/// @dev Reads an address from a position in a byte array.
/// @param b Byte array containing an address.
/// @param index Index in byte array of address.
/// @return address from byte array.
function publicReadAddress(
bytes memory b,
uint256 index)
public
pure
returns (address result)
{
result = readAddress(b, index);
return result;
}
/// @dev Writes an address into a specific position in a byte array.
/// @param b Byte array to insert address into.
/// @param index Index in byte array of address.
/// @param input Address to put into byte array.
function publicWriteAddress(
bytes memory b,
uint256 index,
address input)
public
pure
returns (bytes memory)
{
writeAddress(b, index, input);
return b;
}
/// @dev Reads a bytes32 value from a position in a byte array.
/// @param b Byte array containing a bytes32 value.
/// @param index Index in byte array of bytes32 value.
/// @return bytes32 value from byte array.
function publicReadBytes32(
bytes memory b,
uint256 index)
public
pure
returns (bytes32 result)
{
result = readBytes32(b, index);
return result;
}
/// @dev Writes a bytes32 into a specific position in a byte array.
/// @param b Byte array to insert <input> into.
/// @param index Index in byte array of <input>.
/// @param input bytes32 to put into byte array.
function publicWriteBytes32(
bytes memory b,
uint256 index,
bytes32 input)
public
pure
returns (bytes memory)
{
writeBytes32(b, index, input);
return b;
}
/// @dev Reads a uint256 value from a position in a byte array.
/// @param b Byte array containing a uint256 value.
/// @param index Index in byte array of uint256 value.
/// @return uint256 value from byte array.
function publicReadUint256(
bytes memory b,
uint256 index)
public
pure
returns (uint256 result)
{
result = readUint256(b, index);
return result;
}
/// @dev Writes a uint256 into a specific position in a byte array.
/// @param b Byte array to insert <input> into.
/// @param index Index in byte array of <input>.
/// @param input uint256 to put into byte array.
function publicWriteUint256(
bytes memory b,
uint256 index,
uint256 input)
public
pure
returns (bytes memory)
{
writeUint256(b, index, input);
return b;
}
}

View File

@@ -17,7 +17,6 @@
*/
pragma solidity ^0.4.23;
pragma experimental ABIEncoderV2;
contract LibBytes {
@@ -26,7 +25,8 @@ contract LibBytes {
/// @param rhs Second byte array to compare.
/// @return True if arrays are the same. False otherwise.
function areBytesEqual(bytes memory lhs, bytes memory rhs)
public pure
internal
pure
returns (bool equal)
{
assembly {
@@ -59,7 +59,8 @@ contract LibBytes {
function readAddress(
bytes memory b,
uint256 index)
public pure
internal
pure
returns (address result)
{
require(
@@ -90,7 +91,8 @@ contract LibBytes {
bytes memory b,
uint256 index,
address input)
public pure
internal
pure
{
require(
b.length >= index + 20, // 20 is length of address
@@ -126,7 +128,8 @@ contract LibBytes {
function readBytes32(
bytes memory b,
uint256 index)
public pure
internal
pure
returns (bytes32 result)
{
require(
@@ -152,7 +155,8 @@ contract LibBytes {
bytes memory b,
uint256 index,
bytes32 input)
public pure
internal
pure
{
require(
b.length >= index + 32,
@@ -175,7 +179,8 @@ contract LibBytes {
function readUint256(
bytes memory b,
uint256 index)
public pure
internal
pure
returns (uint256 result)
{
return uint256(readBytes32(b, index));
@@ -189,7 +194,8 @@ contract LibBytes {
bytes memory b,
uint256 index,
uint256 input)
public pure
internal
pure
{
writeBytes32(b, index, bytes32(input));
}

View File

@@ -99,7 +99,7 @@ export enum ContractName {
ERC20Proxy = 'ERC20Proxy',
ERC721Proxy = 'ERC721Proxy',
DummyERC721Token = 'DummyERC721Token',
LibBytes = 'LibBytes',
TestLibBytes = 'TestLibBytes',
Authorizable = 'Authorizable',
}

View File

@@ -7,7 +7,7 @@ import * as chai from 'chai';
import ethUtil = require('ethereumjs-util');
import * as Web3 from 'web3';
import { LibBytesContract } from '../../src/contract_wrappers/generated/lib_bytes';
import { TestLibBytesContract } from '../../src/contract_wrappers/generated/test_lib_bytes';
import { constants } from '../../src/utils/constants';
import { AssetProxyId, ContractName } from '../../src/utils/types';
import { chaiSetup } from '../utils/chai_setup';
@@ -20,7 +20,7 @@ const blockchainLifecycle = new BlockchainLifecycle(web3Wrapper);
describe('LibBytes', () => {
let owner: string;
let libBytes: LibBytesContract;
let libBytes: TestLibBytesContract;
const byteArrayShorterThan32Bytes = '0x012345';
const byteArrayLongerThan32Bytes =
'0x0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef';
@@ -38,8 +38,8 @@ describe('LibBytes', () => {
owner = accounts[0];
testAddress = accounts[1];
// Deploy LibBytes
const libBytesInstance = await deployer.deployAsync(ContractName.LibBytes);
libBytes = new LibBytesContract(libBytesInstance.abi, libBytesInstance.address, provider);
const libBytesInstance = await deployer.deployAsync(ContractName.TestLibBytes);
libBytes = new TestLibBytesContract(libBytesInstance.abi, libBytesInstance.address, provider);
// Verify lengths of test data
const byteArrayShorterThan32BytesLength = ethUtil.toBuffer(byteArrayShorterThan32Bytes).byteLength;
expect(byteArrayShorterThan32BytesLength).to.be.lessThan(32);
@@ -57,7 +57,7 @@ describe('LibBytes', () => {
describe('areBytesEqual', () => {
it('should return true if byte arrays are equal (both arrays < 32 bytes)', async () => {
const areBytesEqual = await libBytes.areBytesEqual.callAsync(
const areBytesEqual = await libBytes.publicAreBytesEqual.callAsync(
byteArrayShorterThan32Bytes,
byteArrayShorterThan32Bytes,
);
@@ -65,7 +65,7 @@ describe('LibBytes', () => {
});
it('should return true if byte arrays are equal (both arrays > 32 bytes)', async () => {
const areBytesEqual = await libBytes.areBytesEqual.callAsync(
const areBytesEqual = await libBytes.publicAreBytesEqual.callAsync(
byteArrayLongerThan32Bytes,
byteArrayLongerThan32Bytes,
);
@@ -73,7 +73,7 @@ describe('LibBytes', () => {
});
it('should return false if byte arrays are not equal (first array < 32 bytes, second array > 32 bytes)', async () => {
const areBytesEqual = await libBytes.areBytesEqual.callAsync(
const areBytesEqual = await libBytes.publicAreBytesEqual.callAsync(
byteArrayShorterThan32Bytes,
byteArrayLongerThan32Bytes,
);
@@ -81,7 +81,7 @@ describe('LibBytes', () => {
});
it('should return false if byte arrays are not equal (first array > 32 bytes, second array < 32 bytes)', async () => {
const areBytesEqual = await libBytes.areBytesEqual.callAsync(
const areBytesEqual = await libBytes.publicAreBytesEqual.callAsync(
byteArrayLongerThan32Bytes,
byteArrayShorterThan32Bytes,
);
@@ -89,7 +89,7 @@ describe('LibBytes', () => {
});
it('should return false if byte arrays are not equal (same length, but a byte in first word differs)', async () => {
const areBytesEqual = await libBytes.areBytesEqual.callAsync(
const areBytesEqual = await libBytes.publicAreBytesEqual.callAsync(
byteArrayLongerThan32BytesFirstBytesSwapped,
byteArrayLongerThan32Bytes,
);
@@ -97,7 +97,7 @@ describe('LibBytes', () => {
});
it('should return false if byte arrays are not equal (same length, but a byte in last word differs)', async () => {
const areBytesEqual = await libBytes.areBytesEqual.callAsync(
const areBytesEqual = await libBytes.publicAreBytesEqual.callAsync(
byteArrayLongerThan32BytesLastBytesSwapped,
byteArrayLongerThan32Bytes,
);
@@ -109,7 +109,7 @@ describe('LibBytes', () => {
it('should successfully read address when the address takes up the whole array)', async () => {
const byteArray = ethUtil.addHexPrefix(testAddress);
const testAddressOffset = new BigNumber(0);
const address = await libBytes.readAddress.callAsync(byteArray, testAddressOffset);
const address = await libBytes.publicReadAddress.callAsync(byteArray, testAddressOffset);
return expect(address).to.be.equal(testAddress);
});
@@ -119,20 +119,24 @@ describe('LibBytes', () => {
const combinedByteArrayBuffer = Buffer.concat([prefixByteArrayBuffer, addressByteArrayBuffer]);
const combinedByteArray = ethUtil.bufferToHex(combinedByteArrayBuffer);
const testAddressOffset = new BigNumber(prefixByteArrayBuffer.byteLength);
const address = await libBytes.readAddress.callAsync(combinedByteArray, testAddressOffset);
const address = await libBytes.publicReadAddress.callAsync(combinedByteArray, testAddressOffset);
return expect(address).to.be.equal(testAddress);
});
it('should fail if the byte array is too short to hold an address)', async () => {
const shortByteArray = '0xabcdef';
const offset = new BigNumber(0);
return expect(libBytes.readAddress.callAsync(shortByteArray, offset)).to.be.rejectedWith(constants.REVERT);
return expect(libBytes.publicReadAddress.callAsync(shortByteArray, offset)).to.be.rejectedWith(
constants.REVERT,
);
});
it('should fail if the length between the offset and end of the byte array is too short to hold an address)', async () => {
const byteArray = ethUtil.addHexPrefix(testAddress);
const badOffset = new BigNumber(ethUtil.toBuffer(byteArray).byteLength);
return expect(libBytes.readAddress.callAsync(byteArray, badOffset)).to.be.rejectedWith(constants.REVERT);
return expect(libBytes.publicReadAddress.callAsync(byteArray, badOffset)).to.be.rejectedWith(
constants.REVERT,
);
});
});
@@ -150,7 +154,7 @@ describe('LibBytes', () => {
describe('readBytes32', () => {
it('should successfully read bytes32 when the bytes32 takes up the whole array)', async () => {
const testBytes32Offset = new BigNumber(0);
const bytes32 = await libBytes.readBytes32.callAsync(testBytes32, testBytes32Offset);
const bytes32 = await libBytes.publicReadBytes32.callAsync(testBytes32, testBytes32Offset);
return expect(bytes32).to.be.equal(testBytes32);
});
@@ -160,20 +164,22 @@ describe('LibBytes', () => {
const combinedByteArrayBuffer = Buffer.concat([prefixByteArrayBuffer, bytes32ByteArrayBuffer]);
const combinedByteArray = ethUtil.bufferToHex(combinedByteArrayBuffer);
const testAddressOffset = new BigNumber(prefixByteArrayBuffer.byteLength);
const bytes32 = await libBytes.readBytes32.callAsync(combinedByteArray, testAddressOffset);
const bytes32 = await libBytes.publicReadBytes32.callAsync(combinedByteArray, testAddressOffset);
return expect(bytes32).to.be.equal(testBytes32);
});
it('should fail if the byte array is too short to hold a bytes32)', async () => {
const offset = new BigNumber(0);
return expect(libBytes.readBytes32.callAsync(byteArrayShorterThan32Bytes, offset)).to.be.rejectedWith(
return expect(libBytes.publicReadBytes32.callAsync(byteArrayShorterThan32Bytes, offset)).to.be.rejectedWith(
constants.REVERT,
);
});
it('should fail if the length between the offset and end of the byte array is too short to hold a bytes32)', async () => {
const badOffset = new BigNumber(ethUtil.toBuffer(testBytes32).byteLength);
return expect(libBytes.readBytes32.callAsync(testBytes32, badOffset)).to.be.rejectedWith(constants.REVERT);
return expect(libBytes.publicReadBytes32.callAsync(testBytes32, badOffset)).to.be.rejectedWith(
constants.REVERT,
);
});
});
@@ -194,7 +200,7 @@ describe('LibBytes', () => {
const testUint256AsBuffer = ethUtil.toBuffer(formattedTestUint256);
const byteArray = ethUtil.bufferToHex(testUint256AsBuffer);
const testUint256Offset = new BigNumber(0);
const uint256 = await libBytes.readUint256.callAsync(byteArray, testUint256Offset);
const uint256 = await libBytes.publicReadUint256.callAsync(byteArray, testUint256Offset);
return expect(uint256).to.bignumber.equal(testUint256);
});
@@ -205,13 +211,13 @@ describe('LibBytes', () => {
const combinedByteArrayBuffer = Buffer.concat([prefixByteArrayBuffer, testUint256AsBuffer]);
const combinedByteArray = ethUtil.bufferToHex(combinedByteArrayBuffer);
const testUint256Offset = new BigNumber(prefixByteArrayBuffer.byteLength);
const uint256 = await libBytes.readUint256.callAsync(combinedByteArray, testUint256Offset);
const uint256 = await libBytes.publicReadUint256.callAsync(combinedByteArray, testUint256Offset);
return expect(uint256).to.bignumber.equal(testUint256);
});
it('should fail if the byte array is too short to hold a uint256)', async () => {
const offset = new BigNumber(0);
return expect(libBytes.readUint256.callAsync(byteArrayShorterThan32Bytes, offset)).to.be.rejectedWith(
return expect(libBytes.publicReadUint256.callAsync(byteArrayShorterThan32Bytes, offset)).to.be.rejectedWith(
constants.REVERT,
);
});
@@ -221,7 +227,9 @@ describe('LibBytes', () => {
const testUint256AsBuffer = ethUtil.toBuffer(formattedTestUint256);
const byteArray = ethUtil.bufferToHex(testUint256AsBuffer);
const badOffset = new BigNumber(testUint256AsBuffer.byteLength);
return expect(libBytes.readUint256.callAsync(byteArray, badOffset)).to.be.rejectedWith(constants.REVERT);
return expect(libBytes.publicReadUint256.callAsync(byteArray, badOffset)).to.be.rejectedWith(
constants.REVERT,
);
});
});