Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add sanity checks #32

Merged
merged 18 commits into from
Oct 30, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -275,6 +275,7 @@ GitHub.sublime-settings
__pycache__/
*.py[cod]
*$py.class
.pytest_cache/

# C extensions
*.so
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,9 @@ contract ProxyAttacker {
receiver.transfer(address(this).balance);
}

function benign() public {
}

function() public payable {}

}
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@

//added pragma version
pragma solidity ^0.4.22;
import "hardhat/console.sol";

contract FibonacciBalance {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ contract Reentrancy_bonus{

function getFirstWithdrawalBonus(address recipient) public {
require(!claimedBonus[recipient]); // Each recipient should only be able to claim the bonus once

rewardsForA[recipient] += 100;
// <yes> <report> REENTRANCY
withdrawReward(recipient); // At this point, the caller will be able to execute getFirstWithdrawalBonus again.
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
pragma solidity ^0.4.24;

import "../dataset/reentrancy/modifier_reentrancy.sol";

contract BankBenign {
ModifierEntrancy modifierEntrancyInstance;

constructor(address _victimAddress) public {
modifierEntrancyInstance = ModifierEntrancy(_victimAddress);
}

function supportsToken() external pure returns(bytes32){
return(keccak256(abi.encodePacked("Nu Token")));
}

function airDrop() public {
modifierEntrancyInstance.airDrop();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,25 @@ contract PandaCaller {
}
}

contract PandaCallerSuccess {
PandaCore public pandaCore;

function PandaCallerSuccess(address _pandaCore) public {
pandaCore = PandaCore(_pandaCore);
}

function call(uint256 _matronId, uint256[2] _childGenes, uint256[2] _factors) public {
uint babyId = pandaCore.giveBirth(_matronId, _childGenes, _factors);
}

function withdraw() public {
pandaCore.withdrawBalance();
}

function() external payable {
}
}

contract GeneScience {
/// @dev simply a boolean to indicate this is the contract we expect to be
function isGeneScience() public pure returns (bool) {
Expand Down Expand Up @@ -93,4 +112,41 @@ contract MyERC721 {
revert("I always revert!");
}

}

contract MyERC721Success {

/// @notice Name and symbol of the non fungible token, as defined in ERC721.
string public constant name = "NFT";
string public constant symbol = "NFT";

bytes4 constant InterfaceSignature_ERC165 =
bytes4(keccak256('supportsInterface(bytes4)'));

bytes4 constant InterfaceSignature_ERC721 =
bytes4(keccak256('name()')) ^
bytes4(keccak256('symbol()')) ^
bytes4(keccak256('totalSupply()')) ^
bytes4(keccak256('balanceOf(address)')) ^
bytes4(keccak256('ownerOf(uint256)')) ^
bytes4(keccak256('approve(address,uint256)')) ^
bytes4(keccak256('transfer(address,uint256)')) ^
bytes4(keccak256('transferFrom(address,address,uint256)')) ^
bytes4(keccak256('tokensOfOwner(address)')) ^
bytes4(keccak256('tokenMetadata(uint256,string)'));

/// @notice Introspection interface as per ERC-165 (https://github.com/ethereum/EIPs/issues/165).
/// Returns true for any standardized interfaces implemented by this contract. We implement
/// ERC-165 (obviously!) and ERC-721.
function supportsInterface(bytes4 _interfaceID) external view returns (bool)
{
// DEBUG ONLY
//require((InterfaceSignature_ERC165 == 0x01ffc9a7) && (InterfaceSignature_ERC721 == 0x9a20483d));

return ((_interfaceID == InterfaceSignature_ERC165) || (_interfaceID == InterfaceSignature_ERC721));
}

function() external payable {
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
pragma solidity ^0.4.9;

import "../dataset/unchecked_low_level_calls/0x89c1b3807d4c67df034fffb62f3509561218d30b.sol";
contract TownCrierCaller {
TownCrier public TC_CONTRACT;
bytes4 constant TC_CALLBACK_FID = bytes4(sha3("response(uint64,uint64,bytes32)"));
int requestId;
bytes32 public hash;

event LogResponse(uint64 responseType, uint64 errors, bytes32 data);
event Received(address sender, uint value);

function TownCrierCaller(address _townCrier) {
TC_CONTRACT = TownCrier(_townCrier);
}

function request(uint8 requestType, bytes32[] requestData) public payable {

requestId = TC_CONTRACT.request.value(msg.value)(requestType, this, TC_CALLBACK_FID, 0, requestData);
hash = sha3(requestType, requestData);
}

function cancel() public {
TC_CONTRACT.cancel(uint64(requestId));
}

function response(uint64 responseType, uint64 errors, bytes32 data) public {
emit LogResponse(responseType, errors, data);
}

function() payable {
emit Received(msg.sender, msg.value);
}

}
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
pragma solidity 0.4.25;

import "hardhat/console.sol";

contract RevertContract {

// Fallback function that will fail on purpose
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
pragma solidity 0.4.25;

contract SuccessContract {
mapping(address => uint256) public balanceOf;

constructor() public {
balanceOf[msg.sender] = 10 ether;
}

function transferFrom(address from, address to, uint256 amount) public {
require(balanceOf[from] >= amount);
balanceOf[from] -= amount;
balanceOf[to] += amount;
}

function transfer(address to, uint256 amount) public {
require(balanceOf[msg.sender] >= amount);
balanceOf[msg.sender] -= amount;
balanceOf[to] += amount;
}

function sendEther(address _to) public payable {
(bool success, ) = _to.call.value(msg.value)("");
require(success, "Ether transfer failed");
}

function withdrawEther(address _from) public {
bytes4 data = bytes4(keccak256("withdraw()"));
(bool success, ) = _from.call(data);
require(success, "Ether transfer failed");
}

// it should accept any call without reverting
function() external payable {
}
}
8 changes: 6 additions & 2 deletions smartbugs-curated/0.4.x/hardhat.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ const fs = require('fs');
// }

// const patches = getPatches(validPatchesPath);
// // remove empyt string from the list
// // remove empty string from the list
// const index = patches.indexOf("");
// if (index > -1) {
// patches.splice(index, 1);
Expand All @@ -31,8 +31,12 @@ const fs = require('fs');

// let filtered = [];
// filtered.push(path.join(config.paths.sources, "unchecked_low_level_calls/revert_contract.sol"));
// filtered.push(path.join(config.paths.sources, "unchecked_low_level_calls/success_contract.sol"));
// filtered.push(path.join(config.paths.sources, "unchecked_low_level_calls/TokenEBU.sol"));
// for (let i = 0; i < patches.length; i++) {
// if (patches[i] === "patch,main contract") {
// continue;
// }
// filename = path.join(patches[i].split("/")[1], patches[i].split("/")[2]);
// filename = filename.replace(".sol", "_attack.sol");
// filePath = path.join(config.paths.sources, filename);
Expand Down Expand Up @@ -94,7 +98,7 @@ module.exports = {
mocha: {
reporter: './scripts/CustomReporter.js',
reporterOptions: {
json: false, // Export test results to JSON
json: true, // Export test results to JSON
}
},
};
70 changes: 44 additions & 26 deletions smartbugs-curated/0.4.x/scripts/CustomReporter.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,12 @@ class CustomReporter extends Spec {
let currentFile = null;
let allTestsPassed = true;
let allFiles = 0;
const testResults = [];

let failedSanity = 0;
const failedSanityTests = [];
let passedSanity = 0;
const passedResults = [];
const failedResults = [];

const exportOptions = options.reporterOptions || {};
const exportToJson = exportOptions.json || false;

Expand All @@ -40,34 +44,42 @@ class CustomReporter extends Spec {
// Mark the current test file as having failed tests
allTestsPassed = false;
const fileName = currentFile.split('/test/')[1];
const contractFile = fileName.replace('_test.js', suffix+ '.sol');
testResults.push({
const contractFile = fileName.replace('_test.js', suffix+ '.sol');
const result ={
title: test.title,
file: fileName,
contractFile: contractFile,
state: test.state,
error: err.message,
stack: err.stack,
}
if (test.title.includes('sanity check')) {
failedSanity += 1;
failedSanityTests.push(result);
}
else {
failedResults.push(result);
}
});

// If any test passes
runner.on('pass', (test) => {
const fileName = currentFile.split('/test/')[1];
const contractFile = fileName.replace('_test.js', suffix + '.sol');
const result = {
title: test.title,
file: fileName,
contractFile: contractFile,
state: 'failed',
error: err.message, // Capture the error message
stack: err.stack, // Capture the stack trace
});
state: test.state,
};
if (test.title.includes('sanity check')) {
passedSanity += 1;
}
else {
passedResults.push(result);
}
});

// When a test ends, store its result
runner.on('test end', (test) => {
// only get the string after 'test' in the title
// filename = currentFile.split('/');
const fileName = currentFile.split('/test/')[1];
const contractFile = fileName.replace('_test.js', suffix + '.sol');
// console.log(contract_file);
if (test.state === 'passed') {
testResults.push({
title: test.title,
file: fileName,
contractFile: contractFile,
state: test.state,
});
}
});

// When the suite (test file) ends
runner.on('suite end', (suite) => {
if (suite.file && currentFile === suite.file && allTestsPassed) {
Expand All @@ -83,9 +95,11 @@ class CustomReporter extends Spec {

const formattedMessage = Base.color('green', `Total passing test files: ${passingFiles}/${allFiles}`);
const formattedMessage2 = Base.color('fail', `Total failed files: ${failedFiles}/${allFiles}`);
const formattedMessage3 = Base.color('fail', `Total failed sanity tests: ${failedSanity}/${allFiles}`);
// // Log the formatted message
console.log(`${formattedMessage}`);
console.log(`${formattedMessage2}`);
console.log(`${formattedMessage3}`);

if (exportToJson) {
// Prepare the data to be exported to JSON
Expand All @@ -96,7 +110,11 @@ class CustomReporter extends Spec {
totalFiles: allFiles,
passingFiles: passingFiles,
failingFiles: failedFiles,
testResults: testResults,
failedSanity: failedSanity,
passedSanity: passedSanity,
failedSanityTests: failedSanityTests,
passedResults: passedResults,
failedResults: failedResults,
};

// Write to JSON file
Expand Down
Loading
Loading