diff options
5 files changed, 180 insertions, 33 deletions
diff --git a/packages/contracts/package.json b/packages/contracts/package.json index 540846731..48019fe8c 100644 --- a/packages/contracts/package.json +++ b/packages/contracts/package.json @@ -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", diff --git a/packages/contracts/src/contracts/current/test/TestLibBytes/TestLibBytes.sol b/packages/contracts/src/contracts/current/test/TestLibBytes/TestLibBytes.sol new file mode 100644 index 000000000..1597ff8d5 --- /dev/null +++ b/packages/contracts/src/contracts/current/test/TestLibBytes/TestLibBytes.sol @@ -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; + } +} diff --git a/packages/contracts/src/contracts/current/utils/LibBytes/LibBytes.sol b/packages/contracts/src/contracts/current/utils/LibBytes/LibBytes.sol index cff780ba4..3eba0708f 100644 --- a/packages/contracts/src/contracts/current/utils/LibBytes/LibBytes.sol +++ b/packages/contracts/src/contracts/current/utils/LibBytes/LibBytes.sol @@ -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)); } diff --git a/packages/contracts/src/utils/types.ts b/packages/contracts/src/utils/types.ts index 6f9aeda94..2200e09f3 100644 --- a/packages/contracts/src/utils/types.ts +++ b/packages/contracts/src/utils/types.ts @@ -99,7 +99,7 @@ export enum ContractName { ERC20Proxy = 'ERC20Proxy', ERC721Proxy = 'ERC721Proxy', DummyERC721Token = 'DummyERC721Token', - LibBytes = 'LibBytes', + TestLibBytes = 'TestLibBytes', Authorizable = 'Authorizable', } diff --git a/packages/contracts/test/libraries/lib_bytes.ts b/packages/contracts/test/libraries/lib_bytes.ts index b96fb84b0..1270a617f 100644 --- a/packages/contracts/test/libraries/lib_bytes.ts +++ b/packages/contracts/test/libraries/lib_bytes.ts @@ -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, + ); }); }); |