Added unit tests for ReentrancyGuard

This commit is contained in:
Alex Towle 2019-07-26 15:42:12 -07:00
parent f4f922acb5
commit 6efb7027b5
8 changed files with 100 additions and 64 deletions

View File

@ -30,13 +30,13 @@
"src/LibEIP712.sol",
"src/Ownable.sol",
"src/ReentrancyGuard.sol",
"src/RichErrors.sol",
"src/SafeMath.sol",
"src/interfaces/IOwnable.sol",
"test/TestConstants.sol",
"test/TestLibAddressArray.sol",
"test/TestLibBytes.sol",
"test/TestOwnable.sol",
"test/TestReentrancyGuard.sol",
"test/TestSafeMath.sol"
]
}

View File

@ -1,58 +0,0 @@
/*
Copyright 2019 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.5.9;
contract RichErrors {
// bytes4(keccak256("Error(string)"))
bytes4 internal constant STANDARD_ERROR_SELECTOR =
0x08c379a0;
// solhint-disable func-name-mixedcase
/// @dev ABI encode a standard, string revert error payload.
/// This is the same payload that would be included by a `revert(string)`
/// solidity statement. It has the function signature `Error(string)`.
/// @param message The error string.
/// @return The ABI encoded error.
function StandardError(
string memory message
)
internal
pure
returns (bytes memory)
{
return abi.encodeWithSelector(
STANDARD_ERROR_SELECTOR,
bytes(message)
);
}
// solhint-enable func-name-mixedcase
/// @dev Reverts an encoded rich revert reason `errorData`.
/// @param errorData ABI encoded error data.
function _rrevert(bytes memory errorData)
internal
pure
{
assembly {
revert(add(errorData, 0x20), mload(errorData))
}
}
}

View File

@ -0,0 +1,54 @@
/*
Copyright 2019 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.5.9;
import "../src/ReentrancyGuard.sol";
contract TestReentrancyGuard is
ReentrancyGuard
{
uint256 internal counter = 2;
function guarded(bool shouldBeAttacked)
external
nonReentrant
{
if (shouldBeAttacked) {
this.exploitive();
} else {
this.nonExploitive();
}
}
function exploitive()
external
{
if (counter > 0) {
counter--;
this.guarded(true);
} else {
counter = 2;
}
}
function nonExploitive()
external
{} // solhint-disable-line no-empty-blocks
}

View File

@ -34,7 +34,7 @@
"lint-contracts": "solhint -c ../.solhint.json contracts/**/**/**/**/*.sol"
},
"config": {
"abis": "./generated-artifacts/@(IOwnable|LibAddress|LibBytes|LibEIP1271|LibEIP712|Ownable|ReentrancyGuard|RichErrors|SafeMath|TestConstants|TestLibAddressArray|TestLibBytes|TestOwnable|TestSafeMath).json",
"abis": "./generated-artifacts/@(IOwnable|LibAddress|LibBytes|LibEIP1271|LibEIP712|Ownable|ReentrancyGuard|SafeMath|TestConstants|TestLibAddressArray|TestLibBytes|TestOwnable|TestReentrancyGuard|TestSafeMath).json",
"abis:comment": "This list is auto-generated by contracts-gen. Don't edit manually."
},
"repository": {

View File

@ -12,12 +12,12 @@ import * as LibEIP1271 from '../generated-artifacts/LibEIP1271.json';
import * as LibEIP712 from '../generated-artifacts/LibEIP712.json';
import * as Ownable from '../generated-artifacts/Ownable.json';
import * as ReentrancyGuard from '../generated-artifacts/ReentrancyGuard.json';
import * as RichErrors from '../generated-artifacts/RichErrors.json';
import * as SafeMath from '../generated-artifacts/SafeMath.json';
import * as TestConstants from '../generated-artifacts/TestConstants.json';
import * as TestLibAddressArray from '../generated-artifacts/TestLibAddressArray.json';
import * as TestLibBytes from '../generated-artifacts/TestLibBytes.json';
import * as TestOwnable from '../generated-artifacts/TestOwnable.json';
import * as TestReentrancyGuard from '../generated-artifacts/TestReentrancyGuard.json';
import * as TestSafeMath from '../generated-artifacts/TestSafeMath.json';
export const artifacts = {
LibAddress: LibAddress as ContractArtifact,
@ -26,12 +26,12 @@ export const artifacts = {
LibEIP712: LibEIP712 as ContractArtifact,
Ownable: Ownable as ContractArtifact,
ReentrancyGuard: ReentrancyGuard as ContractArtifact,
RichErrors: RichErrors as ContractArtifact,
SafeMath: SafeMath as ContractArtifact,
IOwnable: IOwnable as ContractArtifact,
TestConstants: TestConstants as ContractArtifact,
TestLibAddressArray: TestLibAddressArray as ContractArtifact,
TestLibBytes: TestLibBytes as ContractArtifact,
TestOwnable: TestOwnable as ContractArtifact,
TestReentrancyGuard: TestReentrancyGuard as ContractArtifact,
TestSafeMath: TestSafeMath as ContractArtifact,
};

View File

@ -10,10 +10,10 @@ export * from '../generated-wrappers/lib_e_i_p1271';
export * from '../generated-wrappers/lib_e_i_p712';
export * from '../generated-wrappers/ownable';
export * from '../generated-wrappers/reentrancy_guard';
export * from '../generated-wrappers/rich_errors';
export * from '../generated-wrappers/safe_math';
export * from '../generated-wrappers/test_constants';
export * from '../generated-wrappers/test_lib_address_array';
export * from '../generated-wrappers/test_lib_bytes';
export * from '../generated-wrappers/test_ownable';
export * from '../generated-wrappers/test_reentrancy_guard';
export * from '../generated-wrappers/test_safe_math';

View File

@ -0,0 +1,40 @@
import { chaiSetup, provider, txDefaults, web3Wrapper } from '@0x/contracts-test-utils';
import { BlockchainLifecycle } from '@0x/dev-utils';
import { ReentrancyGuardRevertErrors } from '@0x/utils';
import * as chai from 'chai';
import * as _ from 'lodash';
import { artifacts, TestReentrancyGuardContract } from '../src';
chaiSetup.configure();
const expect = chai.expect;
const blockchainLifecycle = new BlockchainLifecycle(web3Wrapper);
describe('ReentrancyGuard', () => {
let guard: TestReentrancyGuardContract;
before(async () => {
await blockchainLifecycle.startAsync();
// Deploy TestReentrancyGuard
guard = await TestReentrancyGuardContract.deployFrom0xArtifactAsync(
artifacts.TestReentrancyGuard,
provider,
txDefaults,
);
});
after(async () => {
await blockchainLifecycle.revertAsync();
});
describe('nonReentrant', () => {
it('should throw if reentrancy occurs', async () => {
const expectedError = new ReentrancyGuardRevertErrors.IllegalReentrancyError();
return expect(guard.guarded.sendTransactionAsync(true)).to.revertWith(expectedError);
});
it('should succeed if reentrancy does not occur', async () => {
expect(guard.guarded.sendTransactionAsync(false)).to.be.fulfilled; // tslint:disable-line:no-unused-expression
});
});
});

View File

@ -10,12 +10,12 @@
"generated-artifacts/LibEIP712.json",
"generated-artifacts/Ownable.json",
"generated-artifacts/ReentrancyGuard.json",
"generated-artifacts/RichErrors.json",
"generated-artifacts/SafeMath.json",
"generated-artifacts/TestConstants.json",
"generated-artifacts/TestLibAddressArray.json",
"generated-artifacts/TestLibBytes.json",
"generated-artifacts/TestOwnable.json",
"generated-artifacts/TestReentrancyGuard.json",
"generated-artifacts/TestSafeMath.json"
],
"exclude": ["./deploy/solc/solc_bin"]