mirror of https://github.com/crytic/echidna
parent
0f135d18c1
commit
2f613c0e96
@ -0,0 +1,348 @@ |
||||
pragma solidity 0.4.24; |
||||
|
||||
library AddressArrayUtils { |
||||
|
||||
/** |
||||
* Finds the index of the first occurrence of the given element. |
||||
* @param A The input array to search |
||||
* @param a The value to find |
||||
* @return Returns (index and isIn) for the first occurrence starting from index 0 |
||||
*/ |
||||
function indexOf(address[] memory A, address a) internal pure returns (uint256, bool) { |
||||
uint256 length = A.length; |
||||
for (uint256 i = 0; i < length; i++) { |
||||
if (A[i] == a) { |
||||
return (i, true); |
||||
} |
||||
} |
||||
return (0, false); |
||||
} |
||||
|
||||
/** |
||||
* Returns true if the value is present in the list. Uses indexOf internally. |
||||
* @param A The input array to search |
||||
* @param a The value to find |
||||
* @return Returns isIn for the first occurrence starting from index 0 |
||||
*/ |
||||
function contains(address[] memory A, address a) internal pure returns (bool) { |
||||
(, bool isIn) = indexOf(A, a); |
||||
return isIn; |
||||
} |
||||
|
||||
/// @return Returns index and isIn for the first occurrence starting from |
||||
/// end |
||||
function indexOfFromEnd(address[] A, address a) internal pure returns (uint256, bool) { |
||||
uint256 length = A.length; |
||||
for (uint256 i = length; i > 0; i--) { |
||||
if (A[i - 1] == a) { |
||||
return (i, true); |
||||
} |
||||
} |
||||
return (0, false); |
||||
} |
||||
|
||||
/** |
||||
* Returns the combination of the two arrays |
||||
* @param A The first array |
||||
* @param B The second array |
||||
* @return Returns A extended by B |
||||
*/ |
||||
function extend(address[] memory A, address[] memory B) internal pure returns (address[] memory) { |
||||
uint256 aLength = A.length; |
||||
uint256 bLength = B.length; |
||||
address[] memory newAddresses = new address[](aLength + bLength); |
||||
for (uint256 i = 0; i < aLength; i++) { |
||||
newAddresses[i] = A[i]; |
||||
} |
||||
for (i = 0; i < bLength; i++) { |
||||
newAddresses[aLength + i] = B[i]; |
||||
} |
||||
return newAddresses; |
||||
} |
||||
|
||||
/** |
||||
* Returns the array with a appended to A. |
||||
* @param A The first array |
||||
* @param a The value to append |
||||
* @return Returns A appended by a |
||||
*/ |
||||
function append(address[] memory A, address a) internal pure returns (address[] memory) { |
||||
address[] memory newAddresses = new address[](A.length + 1); |
||||
for (uint256 i = 0; i < A.length; i++) { |
||||
newAddresses[i] = A[i]; |
||||
} |
||||
newAddresses[A.length] = a; |
||||
return newAddresses; |
||||
} |
||||
|
||||
/** |
||||
* Returns the combination of two storage arrays. |
||||
* @param A The first array |
||||
* @param B The second array |
||||
* @return Returns A appended by a |
||||
*/ |
||||
function sExtend(address[] storage A, address[] storage B) internal { |
||||
uint256 length = B.length; |
||||
for (uint256 i = 0; i < length; i++) { |
||||
A.push(B[i]); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Returns the intersection of two arrays. Arrays are treated as collections, so duplicates are kept. |
||||
* @param A The first array |
||||
* @param B The second array |
||||
* @return The intersection of the two arrays |
||||
*/ |
||||
function intersect(address[] memory A, address[] memory B) internal pure returns (address[] memory) { |
||||
uint256 length = A.length; |
||||
bool[] memory includeMap = new bool[](length); |
||||
uint256 newLength = 0; |
||||
for (uint256 i = 0; i < length; i++) { |
||||
if (contains(B, A[i])) { |
||||
includeMap[i] = true; |
||||
newLength++; |
||||
} |
||||
} |
||||
address[] memory newAddresses = new address[](newLength); |
||||
uint256 j = 0; |
||||
for (i = 0; i < length; i++) { |
||||
if (includeMap[i]) { |
||||
newAddresses[j] = A[i]; |
||||
j++; |
||||
} |
||||
} |
||||
return newAddresses; |
||||
} |
||||
|
||||
/** |
||||
* Returns the union of the two arrays. Order is not guaranteed. |
||||
* @param A The first array |
||||
* @param B The second array |
||||
* @return The union of the two arrays |
||||
*/ |
||||
function union(address[] memory A, address[] memory B) internal pure returns (address[] memory) { |
||||
address[] memory leftDifference = difference(A, B); |
||||
address[] memory rightDifference = difference(B, A); |
||||
address[] memory intersection = intersect(A, B); |
||||
return extend(leftDifference, extend(intersection, rightDifference)); |
||||
} |
||||
|
||||
/** |
||||
* Alternate implementation |
||||
* Assumes there are no duplicates |
||||
*/ |
||||
function unionB(address[] memory A, address[] memory B) internal pure returns (address[] memory) { |
||||
bool[] memory includeMap = new bool[](A.length + B.length); |
||||
uint256 i = 0; |
||||
uint256 count = 0; |
||||
for (i = 0; i < A.length; i++) { |
||||
includeMap[i] = true; |
||||
count++; |
||||
} |
||||
for (i = 0; i < B.length; i++) { |
||||
if (!contains(A, B[i])) { |
||||
includeMap[A.length + i] = true; |
||||
count++; |
||||
} |
||||
} |
||||
address[] memory newAddresses = new address[](count); |
||||
uint256 j = 0; |
||||
for (i = 0; i < A.length; i++) { |
||||
if (includeMap[i]) { |
||||
newAddresses[j] = A[i]; |
||||
j++; |
||||
} |
||||
} |
||||
for (i = 0; i < B.length; i++) { |
||||
if (includeMap[A.length + i]) { |
||||
newAddresses[j] = B[i]; |
||||
j++; |
||||
} |
||||
} |
||||
return newAddresses; |
||||
} |
||||
|
||||
/** |
||||
* Computes the difference of two arrays. Assumes there are no duplicates. |
||||
* @param A The first array |
||||
* @param B The second array |
||||
* @return The difference of the two arrays |
||||
*/ |
||||
function difference(address[] memory A, address[] memory B) internal pure returns (address[] memory) { |
||||
uint256 length = A.length; |
||||
bool[] memory includeMap = new bool[](length); |
||||
uint256 count = 0; |
||||
// First count the new length because can't push for in-memory arrays |
||||
for (uint256 i = 0; i < length; i++) { |
||||
address e = A[i]; |
||||
if (!contains(B, e)) { |
||||
includeMap[i] = true; |
||||
count++; |
||||
} |
||||
} |
||||
address[] memory newAddresses = new address[](count); |
||||
uint256 j = 0; |
||||
for (i = 0; i < length; i++) { |
||||
if (includeMap[i]) { |
||||
newAddresses[j] = A[i]; |
||||
j++; |
||||
} |
||||
} |
||||
return newAddresses; |
||||
} |
||||
|
||||
/** |
||||
* @dev Reverses storage array in place |
||||
*/ |
||||
function sReverse(address[] storage A) internal { |
||||
address t; |
||||
uint256 length = A.length; |
||||
for (uint256 i = 0; i < length / 2; i++) { |
||||
t = A[i]; |
||||
A[i] = A[A.length - i - 1]; |
||||
A[A.length - i - 1] = t; |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Removes specified index from array |
||||
* Resulting ordering is not guaranteed |
||||
* @return Returns the new array and the removed entry |
||||
*/ |
||||
function pop(address[] memory A, uint256 index) |
||||
internal |
||||
pure |
||||
returns (address[] memory, address) |
||||
{ |
||||
uint256 length = A.length; |
||||
address[] memory newAddresses = new address[](length - 1); |
||||
for (uint256 i = 0; i < index; i++) { |
||||
newAddresses[i] = A[i]; |
||||
} |
||||
for (i = index + 1; i < length; i++) { |
||||
newAddresses[i - 1] = A[i]; |
||||
} |
||||
return (newAddresses, A[index]); |
||||
} |
||||
|
||||
/** |
||||
* @return Returns the new array |
||||
*/ |
||||
function remove(address[] memory A, address a) |
||||
internal |
||||
pure |
||||
returns (address[] memory) |
||||
{ |
||||
(uint256 index, bool isIn) = indexOf(A, a); |
||||
if (!isIn) { |
||||
revert(); |
||||
} else { |
||||
(address[] memory _A,) = pop(A, index); |
||||
return _A; |
||||
} |
||||
} |
||||
|
||||
function sPop(address[] storage A, uint256 index) internal returns (address) { |
||||
uint256 length = A.length; |
||||
if (index >= length) { |
||||
revert("Error: index out of bounds"); |
||||
} |
||||
address entry = A[index]; |
||||
for (uint256 i = index; i < length - 1; i++) { |
||||
A[i] = A[i + 1]; |
||||
} |
||||
A.length--; |
||||
return entry; |
||||
} |
||||
|
||||
/** |
||||
* Deletes address at index and fills the spot with the last address. |
||||
* Order is not preserved. |
||||
* @return Returns the removed entry |
||||
*/ |
||||
function sPopCheap(address[] storage A, uint256 index) internal returns (address) { |
||||
uint256 length = A.length; |
||||
if (index >= length) { |
||||
revert("Error: index out of bounds"); |
||||
} |
||||
address entry = A[index]; |
||||
if (index != length - 1) { |
||||
A[index] = A[length - 1]; |
||||
delete A[length - 1]; |
||||
} |
||||
A.length--; |
||||
return entry; |
||||
} |
||||
|
||||
/** |
||||
* Deletes address at index. Works by swapping it with the last address, then deleting. |
||||
* Order is not preserved |
||||
* @param A Storage array to remove from |
||||
*/ |
||||
function sRemoveCheap(address[] storage A, address a) internal { |
||||
(uint256 index, bool isIn) = indexOf(A, a); |
||||
if (!isIn) { |
||||
revert("Error: entry not found"); |
||||
} else { |
||||
sPopCheap(A, index); |
||||
return; |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Returns whether or not there's a duplicate. Runs in O(n^2). |
||||
* @param A Array to search |
||||
* @return Returns true if duplicate, false otherwise |
||||
*/ |
||||
function hasDuplicate(address[] memory A) internal pure returns (bool) { |
||||
//if (A.length == 0) { |
||||
// return false; |
||||
//} |
||||
for (uint256 i = 0; i < A.length - 1; i++) { |
||||
for (uint256 j = i + 1; j < A.length; j++) { |
||||
if (A[i] == A[j]) { |
||||
return true; |
||||
} |
||||
} |
||||
} |
||||
return false; |
||||
} |
||||
|
||||
/** |
||||
* Returns whether the two arrays are equal. |
||||
* @param A The first array |
||||
* @param B The second array |
||||
* @return True is the arrays are equal, false if not. |
||||
*/ |
||||
function isEqual(address[] memory A, address[] memory B) internal pure returns (bool) { |
||||
if (A.length != B.length) { |
||||
return false; |
||||
} |
||||
for (uint256 i = 0; i < A.length; i++) { |
||||
if (A[i] != B[i]) { |
||||
return false; |
||||
} |
||||
} |
||||
return true; |
||||
} |
||||
|
||||
/** |
||||
* Returns the elements indexed at indexArray. |
||||
* @param A The array to index |
||||
* @param indexArray The array to use to index |
||||
* @return Returns array containing elements indexed at indexArray |
||||
*/ |
||||
function argGet(address[] memory A, uint256[] memory indexArray) |
||||
internal |
||||
pure |
||||
returns (address[] memory) |
||||
{ |
||||
address[] memory array = new address[](indexArray.length); |
||||
for (uint256 i = 0; i < indexArray.length; i++) { |
||||
array[i] = A[indexArray[i]]; |
||||
} |
||||
return array; |
||||
} |
||||
|
||||
} |
@ -0,0 +1,54 @@ |
||||
pragma solidity 0.4.24; |
||||
|
||||
import "AddressArrayUtils_withHasDuplicateBug.sol"; |
||||
|
||||
contract TEST { |
||||
|
||||
address [] addrs1; |
||||
address [] addrs2; |
||||
address a; |
||||
|
||||
bool everSet = false; |
||||
|
||||
function push_it_1() public { |
||||
if (everSet) { |
||||
addrs1.push(a); |
||||
} |
||||
} |
||||
|
||||
function push_it_2() public { |
||||
if (everSet) { |
||||
addrs2.push(a); |
||||
} |
||||
} |
||||
|
||||
function push_it_both() public { |
||||
if (everSet) { |
||||
addrs1.push(a); |
||||
addrs2.push(1); |
||||
} |
||||
} |
||||
|
||||
function set_addr(address newa) public { |
||||
everSet = true; |
||||
a = newa; |
||||
} |
||||
|
||||
function echidna_hasDuplicate() public view returns (bool) { |
||||
if (!everSet) { |
||||
return true; |
||||
} |
||||
bool hasDup = false; |
||||
uint i1; |
||||
uint i2; |
||||
bool b; |
||||
for (uint i = 0; i < addrs1.length; i++) { |
||||
(i1, b) = AddressArrayUtils.indexOf(addrs1, addrs1[i]); |
||||
(i2, b) = AddressArrayUtils.indexOfFromEnd(addrs1, addrs1[i]); |
||||
if (i1 != (i2-1)) { |
||||
hasDup = true; |
||||
} |
||||
} |
||||
return hasDup == AddressArrayUtils.hasDuplicate(addrs1); |
||||
} |
||||
} |
@ -0,0 +1,590 @@ |
||||
pragma solidity 0.4.24; |
||||
|
||||
import "AddressArrayUtils.sol"; |
||||
|
||||
contract TEST { |
||||
|
||||
address [] addrs1; |
||||
address [] addrs2; |
||||
address a; |
||||
|
||||
bool everSet = false; |
||||
|
||||
function push_it_1() public { |
||||
if (everSet) { |
||||
addrs1.push(a); |
||||
} |
||||
} |
||||
|
||||
function push_it_2() public { |
||||
if (everSet) { |
||||
addrs2.push(a); |
||||
} |
||||
} |
||||
|
||||
function push_it_both() public { |
||||
if (everSet) { |
||||
addrs1.push(a); |
||||
addrs2.push(1); |
||||
} |
||||
} |
||||
|
||||
function set_addr(address newa) public { |
||||
everSet = true; |
||||
a = newa; |
||||
} |
||||
|
||||
function echidna_find() public view returns (bool) { |
||||
if (!everSet) { |
||||
return true; |
||||
} |
||||
uint256 i; |
||||
uint256 j; |
||||
bool b; |
||||
(i, b) = AddressArrayUtils.indexOf(addrs1, a); |
||||
if (b) { |
||||
if (addrs1[i] != a) { |
||||
return false; |
||||
} |
||||
for (j = 0; j < i; j++) { |
||||
if (addrs1[j] == a) { |
||||
return false; |
||||
} |
||||
} |
||||
if (!AddressArrayUtils.contains(addrs1, a)) { |
||||
return false; |
||||
} |
||||
(i, b) = AddressArrayUtils.indexOfFromEnd(addrs1, a); |
||||
if (!b) { |
||||
return false; |
||||
} |
||||
if (addrs1[i-1] != a) { |
||||
return false; |
||||
} |
||||
for (j = (addrs1.length-1); j >= i; j--) { |
||||
if (addrs1[j] == a) { |
||||
return false; |
||||
} |
||||
} |
||||
} else { |
||||
for (j = 0; j < addrs1.length; j++) { |
||||
if (addrs1[j] == a) { |
||||
return false; |
||||
} |
||||
} |
||||
if (AddressArrayUtils.contains(addrs1, a)) { |
||||
return false; |
||||
} |
||||
(i, b) = AddressArrayUtils.indexOfFromEnd(addrs1, a); |
||||
if (b) { |
||||
return false; |
||||
} |
||||
} |
||||
return true; |
||||
} |
||||
|
||||
function echidna_append() public view returns (bool) { |
||||
if (!everSet) { |
||||
return true; |
||||
} |
||||
address [] memory addrs1PlusA = AddressArrayUtils.append(addrs1, a); |
||||
uint256 i; |
||||
uint256 j; |
||||
bool b1; |
||||
bool b2; |
||||
if (AddressArrayUtils.isEqual(addrs1, addrs1PlusA)) { |
||||
return false; |
||||
} |
||||
(i, b1) = AddressArrayUtils.indexOfFromEnd(addrs1PlusA, a); |
||||
if (!b1) { |
||||
return false; |
||||
} |
||||
if (i != (addrs1PlusA.length)) { |
||||
return false; |
||||
} |
||||
if (addrs1PlusA[i-1] != a) { |
||||
return false; |
||||
} |
||||
(j, b2) = AddressArrayUtils.indexOf(addrs1PlusA, a); |
||||
if (!b2) { |
||||
return false; |
||||
} |
||||
if (addrs1PlusA[j] != a) { |
||||
return false; |
||||
} |
||||
if (AddressArrayUtils.contains(addrs1, a)) { |
||||
if (j >= (i-1)) { |
||||
return false; |
||||
} |
||||
if (!AddressArrayUtils.hasDuplicate(addrs1PlusA)) { |
||||
return false; |
||||
} |
||||
} else { |
||||
if (j != (i-1)) { |
||||
return false; |
||||
} |
||||
} |
||||
return true; |
||||
} |
||||
|
||||
function echidna_extend() public view returns (bool) { |
||||
if (!everSet) { |
||||
return true; |
||||
} |
||||
address [] memory addrs1PlusAddrs2 = AddressArrayUtils.extend(addrs1, addrs2); |
||||
uint256 i; |
||||
for (i = 0; i < addrs1.length; i++) { |
||||
if (!AddressArrayUtils.contains(addrs1PlusAddrs2, addrs1[i])) { |
||||
return false; |
||||
} |
||||
} |
||||
for (i = 0; i < addrs2.length; i++) { |
||||
if (!AddressArrayUtils.contains(addrs1PlusAddrs2, addrs2[i])) { |
||||
return false; |
||||
} |
||||
} |
||||
if (!AddressArrayUtils.contains(addrs1, a) && !AddressArrayUtils.contains(addrs2, a)) { |
||||
if (AddressArrayUtils.contains(addrs1PlusAddrs2, a)) { |
||||
return false; |
||||
} |
||||
} |
||||
return true; |
||||
} |
||||
|
||||
function echidna_sExtend() public returns (bool) { |
||||
if (!everSet) { |
||||
return true; |
||||
} |
||||
bool notInEither = !AddressArrayUtils.contains(addrs1, a) && !AddressArrayUtils.contains(addrs2, a); |
||||
uint256 addrs1Length = addrs1.length; |
||||
uint256 addrs2Length = addrs2.length; |
||||
AddressArrayUtils.sExtend(addrs1, addrs2); |
||||
uint256 i; |
||||
for (i = 0; i < addrs2.length; i++) { |
||||
if (!AddressArrayUtils.contains(addrs1, addrs2[i])) { |
||||
return false; |
||||
} |
||||
} |
||||
if (addrs1.length != (addrs1Length + addrs2Length)) { |
||||
return false; |
||||
} |
||||
if (notInEither && AddressArrayUtils.contains(addrs1, a)) { |
||||
return false; |
||||
} |
||||
return true; |
||||
} |
||||
|
||||
function echidna_hasDuplicate() public view returns (bool) { |
||||
if (!everSet) { |
||||
return true; |
||||
} |
||||
bool hasDup = false; |
||||
uint i1; |
||||
uint i2; |
||||
bool b; |
||||
for (uint i = 0; i < addrs1.length; i++) { |
||||
(i1, b) = AddressArrayUtils.indexOf(addrs1, addrs1[i]); |
||||
(i2, b) = AddressArrayUtils.indexOfFromEnd(addrs1, addrs1[i]); |
||||
if (i1 != (i2-1)) { |
||||
hasDup = true; |
||||
} |
||||
} |
||||
return hasDup == AddressArrayUtils.hasDuplicate(addrs1); |
||||
} |
||||
|
||||
function echidna_isEqual() public view returns (bool) { |
||||
if (!everSet) { |
||||
return true; |
||||
} |
||||
uint256 length1 = addrs1.length; |
||||
uint256 length2 = addrs2.length; |
||||
bool areEqual = AddressArrayUtils.isEqual(addrs1, addrs2); |
||||
if (length1 != length2) { |
||||
return !areEqual; |
||||
} |
||||
for (uint i = 0; i < length1; i++) { |
||||
if (addrs1[i] != addrs2[i]) { |
||||
return !areEqual; |
||||
} |
||||
} |
||||
return areEqual; |
||||
} |
||||
|
||||
function echidna_sReverse() public returns (bool) { |
||||
if (!everSet) { |
||||
return true; |
||||
} |
||||
uint256 length = addrs1.length; |
||||
address a0; |
||||
address a1; |
||||
if (length > 0) { |
||||
a0 = addrs1[0]; |
||||
a1 = addrs1[length-1]; |
||||
} |
||||
AddressArrayUtils.sReverse(addrs1); |
||||
if (addrs1.length != length) { |
||||
return false; |
||||
} |
||||
if (length > 0) { |
||||
if (a0 != addrs1[length-1]) { |
||||
return false; |
||||
} |
||||
if (a1 != addrs1[0]) { |
||||
return false; |
||||
} |
||||
} |
||||
return true; |
||||
} |
||||
|
||||
function ourEqual(address[] memory A, address[] memory B) internal pure returns (bool) { |
||||
uint256 i; |
||||
uint256 j; |
||||
bool found; |
||||
for (i = 0; i < A.length; i++) { |
||||
found = false; |
||||
for (j = 0; j < B.length; j++) { |
||||
if (A[i] == B[j]) { |
||||
found = true; |
||||
break; |
||||
} |
||||
} |
||||
if (!found) { |
||||
return false; |
||||
} |
||||
} |
||||
for (i = 0; i < B.length; i++) { |
||||
found = false; |
||||
for (j = 0; j < A.length; j++) { |
||||
if (A[j] == B[i]) { |
||||
found = true; |
||||
break; |
||||
} |
||||
} |
||||
if (!found) { |
||||
return false; |
||||
} |
||||
} |
||||
return true; |
||||
} |
||||
|
||||
function echidna_diff() public view returns (bool) { |
||||
if (!everSet) { |
||||
return true; |
||||
} |
||||
address [] memory empty = new address[](0); |
||||
address [] memory diff1 = AddressArrayUtils.difference(addrs1, addrs2); |
||||
address [] memory diff2 = AddressArrayUtils.difference(addrs2, addrs1); |
||||
if (!ourEqual(addrs1, addrs2) == ourEqual(diff1, diff2)) { |
||||
return false; |
||||
} |
||||
if (!ourEqual(AddressArrayUtils.difference(addrs1, addrs1), empty)) { |
||||
return false; |
||||
} |
||||
return true; |
||||
} |
||||
|
||||
function echidna_union() public view returns (bool) { |
||||
if (!everSet) { |
||||
return true; |
||||
} |
||||
address [] memory empty = new address[](0); |
||||
address [] memory union1 = AddressArrayUtils.union(addrs1, addrs2); |
||||
address [] memory union2 = AddressArrayUtils.union(addrs2, addrs1); |
||||
address [] memory unionB1 = AddressArrayUtils.unionB(addrs1, addrs2); |
||||
address [] memory unionB2 = AddressArrayUtils.unionB(addrs2, addrs1); |
||||
if (!ourEqual(union1, union2)) { |
||||
return false; |
||||
} |
||||
if (!AddressArrayUtils.hasDuplicate(addrs1) && !AddressArrayUtils.hasDuplicate(addrs2)) { |
||||
if (!ourEqual(unionB1, unionB2)) { |
||||
return false; |
||||
} |
||||
} |
||||
if (!ourEqual(AddressArrayUtils.union(addrs1, empty), addrs1)) { |
||||
return false; |
||||
} |
||||
return true; |
||||
} |
||||
|
||||
function echidna_intersect() public view returns (bool) { |
||||
if (!everSet) { |
||||
return true; |
||||
} |
||||
address [] memory empty = new address[](0); |
||||
address [] memory intersect1 = AddressArrayUtils.intersect(addrs1, addrs2); |
||||
address [] memory intersect2 = AddressArrayUtils.intersect(addrs2, addrs1); |
||||
if (!ourEqual(intersect1, intersect2)) { |
||||
return false; |
||||
} |
||||
if (!ourEqual(AddressArrayUtils.intersect(addrs1, empty), empty)) { |
||||
return false; |
||||
} |
||||
return true; |
||||
} |
||||
|
||||
function echidna_remove() public view returns (bool) { |
||||
if (!everSet) { |
||||
return true; |
||||
} |
||||
if (!AddressArrayUtils.contains(addrs1, a)) { |
||||
return true; |
||||
} |
||||
uint256 acount = 0; |
||||
uint256 i; |
||||
for (i = 0; i < addrs1.length; i++) { |
||||
if (addrs1[i] == a) { |
||||
acount++; |
||||
} |
||||
} |
||||
address [] memory removed = AddressArrayUtils.remove(addrs1, a); |
||||
if (removed.length != (addrs1.length-1)) { |
||||
return false; |
||||
} |
||||
uint256 acountNew = 0; |
||||
for (i = 0; i < removed.length; i++) { |
||||
if (removed[i] == a) { |
||||
acountNew++; |
||||
} |
||||
} |
||||
if (acountNew != (acount-1)) { |
||||
return false; |
||||
} |
||||
if (!AddressArrayUtils.hasDuplicate(addrs1)) { |
||||
if (AddressArrayUtils.contains(removed, a)) { |
||||
return false; |
||||
} |
||||
} |
||||
return true; |
||||
} |
||||
|
||||
function echidna_revert_remove() public view returns (bool) { |
||||
if (!everSet) { |
||||
revert(); |
||||
} |
||||
if (AddressArrayUtils.contains(addrs1, a)) { |
||||
revert(); |
||||
} |
||||
AddressArrayUtils.remove(addrs1, a); |
||||
} |
||||
|
||||
function echidna_pop() public view returns (bool) { |
||||
if (!everSet) { |
||||
return true; |
||||
} |
||||
if (!AddressArrayUtils.contains(addrs1, a)) { |
||||
return true; |
||||
} |
||||
uint256 aIndex; |
||||
bool aFound; |
||||
(aIndex, aFound) = AddressArrayUtils.indexOf(addrs1, a); |
||||
uint256 acount = 0; |
||||
uint256 i; |
||||
for (i = 0; i < addrs1.length; i++) { |
||||
if (addrs1[i] == a) { |
||||
acount++; |
||||
} |
||||
} |
||||
address [] memory removed; |
||||
address apop; |
||||
(removed, apop) = AddressArrayUtils.pop(addrs1, aIndex); |
||||
if (apop != a) { |
||||
return false; |
||||
} |
||||
if (removed.length != (addrs1.length-1)) { |
||||
return false; |
||||
} |
||||
uint256 acountNew = 0; |
||||
for (i = 0; i < removed.length; i++) { |
||||
if (removed[i] == a) { |
||||
acountNew++; |
||||
} |
||||
} |
||||
if (acountNew != (acount-1)) { |
||||
return false; |
||||
} |
||||
if (!AddressArrayUtils.hasDuplicate(addrs1)) { |
||||
if (AddressArrayUtils.contains(removed, a)) { |
||||
return false; |
||||
} |
||||
} |
||||
return true; |
||||
} |
||||
|
||||
function echidna_sRemoveCheap() public returns (bool) { |
||||
if (!everSet) { |
||||
return true; |
||||
} |
||||
if (!AddressArrayUtils.contains(addrs1, a)) { |
||||
return true; |
||||
} |
||||
uint256 acount = 0; |
||||
uint256 i; |
||||
for (i = 0; i < addrs1.length; i++) { |
||||
if (addrs1[i] == a) { |
||||
acount++; |
||||
} |
||||
} |
||||
uint256 oldLength = addrs1.length; |
||||
bool anyDuplicates = AddressArrayUtils.hasDuplicate(addrs1); |
||||
AddressArrayUtils.sRemoveCheap(addrs1, a); |
||||
if (addrs1.length != (oldLength-1)) { |
||||
return false; |
||||
} |
||||
uint256 acountNew = 0; |
||||
for (i = 0; i < addrs1.length; i++) { |
||||
if (addrs1[i] == a) { |
||||
acountNew++; |
||||
} |
||||
} |
||||
if (acountNew != (acount-1)) { |
||||
return false; |
||||
} |
||||
if (!anyDuplicates) { |
||||
if (AddressArrayUtils.contains(addrs1, a)) { |
||||
return false; |
||||
} |
||||
} |
||||
return true; |
||||
} |
||||
|
||||
function echidna_revert_sRemoveCheap() public returns (bool) { |
||||
if (!everSet) { |
||||
revert(); |
||||
} |
||||
if (AddressArrayUtils.contains(addrs1, a)) { |
||||
revert(); |
||||
} |
||||
AddressArrayUtils.sRemoveCheap(addrs1, a); |
||||
} |
||||
|
||||
function echidna_sPop() public returns (bool) { |
||||
if (!everSet) { |
||||
return true; |
||||
} |
||||
if (!AddressArrayUtils.contains(addrs1, a)) { |
||||
return true; |
||||
} |
||||
uint256 aIndex; |
||||
bool aFound; |
||||
(aIndex, aFound) = AddressArrayUtils.indexOf(addrs1, a); |
||||
uint256 acount = 0; |
||||
uint256 i; |
||||
for (i = 0; i < addrs1.length; i++) { |
||||
if (addrs1[i] == a) { |
||||
acount++; |
||||
} |
||||
} |
||||
uint256 oldLength = addrs1.length; |
||||
bool anyDuplicates = AddressArrayUtils.hasDuplicate(addrs1); |
||||
address apop = AddressArrayUtils.sPop(addrs1, aIndex); |
||||
if (apop != a) { |
||||
return false; |
||||
} |
||||
if (addrs1.length != (oldLength-1)) { |
||||
return false; |
||||
} |
||||
uint256 acountNew = 0; |
||||
for (i = 0; i < addrs1.length; i++) { |
||||
if (addrs1[i] == a) { |
||||
acountNew++; |
||||
} |
||||
} |
||||
if (acountNew != (acount-1)) { |
||||
return false; |
||||
} |
||||
if (!anyDuplicates) { |
||||
if (AddressArrayUtils.contains(addrs1, a)) { |
||||
return false; |
||||
} |
||||
} |
||||
return true; |
||||
} |
||||
|
||||
function echidna_revert_sPop() public returns (bool) { |
||||
if (!everSet) { |
||||
revert(); |
||||
} |
||||
uint256 index = addrs1.length; |
||||
AddressArrayUtils.sPop(addrs1, index); |
||||
} |
||||
|
||||
function echidna_sPopCheap() public returns (bool) { |
||||
if (!everSet) { |
||||
return true; |
||||
} |
||||
if (!AddressArrayUtils.contains(addrs1, a)) { |
||||
return true; |
||||
} |
||||
uint256 aIndex; |
||||
bool aFound; |
||||
(aIndex, aFound) = AddressArrayUtils.indexOf(addrs1, a); |
||||
uint256 acount = 0; |
||||
uint256 i; |
||||
for (i = 0; i < addrs1.length; i++) { |
||||
if (addrs1[i] == a) { |
||||
acount++; |
||||
} |
||||
} |
||||
uint256 oldLength = addrs1.length; |
||||
bool anyDuplicates = AddressArrayUtils.hasDuplicate(addrs1); |
||||
address apop = AddressArrayUtils.sPopCheap(addrs1, aIndex); |
||||
if (apop != a) { |
||||
return false; |
||||
} |
||||
if (addrs1.length != (oldLength-1)) { |
||||
return false; |
||||
} |
||||
uint256 acountNew = 0; |
||||
for (i = 0; i < addrs1.length; i++) { |
||||
if (addrs1[i] == a) { |
||||
acountNew++; |
||||
} |
||||
} |
||||
if (acountNew != (acount-1)) { |
||||
return false; |
||||
} |
||||
if (!anyDuplicates) { |
||||
if (AddressArrayUtils.contains(addrs1, a)) { |
||||
return false; |
||||
} |
||||
} |
||||
return true; |
||||
} |
||||
|
||||
function echidna_revert_sPopCheap() public returns (bool) { |
||||
if (!everSet) { |
||||
revert(); |
||||
} |
||||
uint256 index = addrs1.length; |
||||
AddressArrayUtils.sPopCheap(addrs1, index); |
||||
} |
||||
|
||||
function echidna_argGet() public view returns (bool) { |
||||
if (!everSet) { |
||||
return true; |
||||
} |
||||
if (addrs1.length < 1) { |
||||
return true; |
||||
} |
||||
bool found; |
||||
uint256 index; |
||||
uint256 i; |
||||
uint256[] memory indexArray = new uint256[](addrs2.length); |
||||
for (i = 0; i < indexArray.length; i++) { |
||||
(index, found) = AddressArrayUtils.indexOf(addrs1, addrs2[i]); |
||||
if (found) { |
||||
indexArray[i] = index; |
||||
} else { |
||||
indexArray[i] = 0; |
||||
} |
||||
} |
||||
address[] memory argGetResult = AddressArrayUtils.argGet(addrs1, indexArray); |
||||
for (i = 0; i < argGetResult.length; i++) { |
||||
if (argGetResult[i] != addrs1[indexArray[i]]) { |
||||
return false; |
||||
} |
||||
} |
||||
return true; |
||||
} |
||||
|
||||
} |
Loading…
Reference in new issue