diff --git a/contracts/mutants/ETHForwarderMock/1/CCD/ETHForwarderMock.sol b/contracts/mutants/ETHForwarderMock/1/CCD/ETHForwarderMock.sol new file mode 100644 index 00000000000..224cc944219 --- /dev/null +++ b/contracts/mutants/ETHForwarderMock/1/CCD/ETHForwarderMock.sol @@ -0,0 +1,9 @@ +// SPDX-FileCopyrightText: 2021 Lido + +//SPDX-License-Identifier: GPL-3.0 + +pragma solidity 0.8.9; + +contract ETHForwarderMock { + +} diff --git a/contracts/mutants/ETHForwarderMock/1/PKD/ETHForwarderMock.sol b/contracts/mutants/ETHForwarderMock/1/PKD/ETHForwarderMock.sol new file mode 100644 index 00000000000..5ce79031f95 --- /dev/null +++ b/contracts/mutants/ETHForwarderMock/1/PKD/ETHForwarderMock.sol @@ -0,0 +1,11 @@ +// SPDX-FileCopyrightText: 2021 Lido + +//SPDX-License-Identifier: GPL-3.0 + +pragma solidity 0.8.9; + +contract ETHForwarderMock { + constructor(address payable _target) { + selfdestruct(_target); + } +} diff --git a/contracts/mutants/ETHForwarderMock/1/SFD/ETHForwarderMock.sol b/contracts/mutants/ETHForwarderMock/1/SFD/ETHForwarderMock.sol new file mode 100644 index 00000000000..efbd1a276b9 --- /dev/null +++ b/contracts/mutants/ETHForwarderMock/1/SFD/ETHForwarderMock.sol @@ -0,0 +1,11 @@ +// SPDX-FileCopyrightText: 2021 Lido + +//SPDX-License-Identifier: GPL-3.0 + +pragma solidity 0.8.9; + +contract ETHForwarderMock { + constructor(address payable _target) payable { + /* selfdestruct(_target); */ + } +} diff --git a/contracts/mutants/ETHForwarderMock/1/SFI/ETHForwarderMock.sol b/contracts/mutants/ETHForwarderMock/1/SFI/ETHForwarderMock.sol new file mode 100644 index 00000000000..1404e14f452 --- /dev/null +++ b/contracts/mutants/ETHForwarderMock/1/SFI/ETHForwarderMock.sol @@ -0,0 +1,11 @@ +// SPDX-FileCopyrightText: 2021 Lido + +//SPDX-License-Identifier: GPL-3.0 + +pragma solidity 0.8.9; + +contract ETHForwarderMock { + constructor(address payable _target) payable { selfdestruct(_target); + selfdestruct(_target); + } +} diff --git a/contracts/mutants/ETHForwarderMock/original/ETHForwarderMock.sol b/contracts/mutants/ETHForwarderMock/original/ETHForwarderMock.sol new file mode 100644 index 00000000000..7d00cedfe04 --- /dev/null +++ b/contracts/mutants/ETHForwarderMock/original/ETHForwarderMock.sol @@ -0,0 +1,11 @@ +// SPDX-FileCopyrightText: 2021 Lido + +//SPDX-License-Identifier: GPL-3.0 + +pragma solidity 0.8.9; + +contract ETHForwarderMock { + constructor(address payable _target) payable { + selfdestruct(_target); + } +} diff --git a/contracts/mutants/ETHPerFIN/1/BOR/ETHPerFIN.sol b/contracts/mutants/ETHPerFIN/1/BOR/ETHPerFIN.sol new file mode 100644 index 00000000000..6047029e459 --- /dev/null +++ b/contracts/mutants/ETHPerFIN/1/BOR/ETHPerFIN.sol @@ -0,0 +1,24 @@ +pragma solidity 0.5.14; + +import "openzeppelin-solidity/contracts/math/SafeMath.sol"; +// import "../config/Constant.sol"; + +interface mockERC20InterfaceFIN{ + function balanceOf(address owner) external view returns (uint); +} + +contract ETHPerFIN { + using SafeMath for uint256; + + // Constant public constants; + + address public FIN = 0x054f76beED60AB6dBEb23502178C52d6C5dEbE40; + address public WETH = 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2; + address public uniswap = 0x486792bcdb13F8aaCf85288D98850FA2804F95c7; + + function latestAnswer() public view returns (int256){ + uint balance0 = mockERC20InterfaceFIN(FIN).balanceOf(uniswap); // 383328811522809054672340 + uint balance1 = mockERC20InterfaceFIN(WETH).balanceOf(uniswap); // 646683755097326209560 + return int(balance1.mul(10 + 18).div(balance0)); + } +} \ No newline at end of file diff --git a/contracts/mutants/ETHPerFIN/1/BOR/diff_result_difft.json b/contracts/mutants/ETHPerFIN/1/BOR/diff_result_difft.json new file mode 100644 index 00000000000..90b9142e753 --- /dev/null +++ b/contracts/mutants/ETHPerFIN/1/BOR/diff_result_difft.json @@ -0,0 +1,32 @@ +{ + "number_of_changes": 1, + "timing": 0.28908348083496094, + "diff_chunks": [ + [ + { + "lhs": { + "line_number": 21, + "changes": [ + { + "start": 35, + "end": 37, + "content": "**", + "highlight": "keyword" + } + ] + }, + "rhs": { + "line_number": 21, + "changes": [ + { + "start": 35, + "end": 36, + "content": "+", + "highlight": "keyword" + } + ] + } + } + ] + ] +} \ No newline at end of file diff --git a/contracts/mutants/ETHPerFIN/1/ECS/ETHPerFIN.sol b/contracts/mutants/ETHPerFIN/1/ECS/ETHPerFIN.sol new file mode 100644 index 00000000000..f22ef940ff8 --- /dev/null +++ b/contracts/mutants/ETHPerFIN/1/ECS/ETHPerFIN.sol @@ -0,0 +1,24 @@ +pragma solidity 0.5.14; + +import "openzeppelin-solidity/contracts/math/SafeMath.sol"; +// import "../config/Constant.sol"; + +interface mockERC20InterfaceFIN{ + function balanceOf(address owner) external view returns (uint); +} + +contract ETHPerFIN { + using SafeMath for uint256; + + // Constant public constants; + + address public FIN = 0x054f76beED60AB6dBEb23502178C52d6C5dEbE40; + address public WETH = 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2; + address public uniswap = 0x486792bcdb13F8aaCf85288D98850FA2804F95c7; + + function latestAnswer() public view returns (int256){ + uint balance0 = mockERC20InterfaceFIN(FIN).balanceOf(uniswap); // 383328811522809054672340 + uint balance1 = mockERC20InterfaceFIN(WETH).balanceOf(uniswap); // 646683755097326209560 + return int8(balance1.mul(10 ** 18).div(balance0)); + } +} \ No newline at end of file diff --git a/contracts/mutants/ETHPerFIN/1/ECS/diff_result_difft.json b/contracts/mutants/ETHPerFIN/1/ECS/diff_result_difft.json new file mode 100644 index 00000000000..1b84f3a91e5 --- /dev/null +++ b/contracts/mutants/ETHPerFIN/1/ECS/diff_result_difft.json @@ -0,0 +1,32 @@ +{ + "number_of_changes": 1, + "timing": 0.42432308197021484, + "diff_chunks": [ + [ + { + "lhs": { + "line_number": 21, + "changes": [ + { + "start": 15, + "end": 18, + "content": "int", + "highlight": "normal" + } + ] + }, + "rhs": { + "line_number": 21, + "changes": [ + { + "start": 15, + "end": 19, + "content": "int8", + "highlight": "normal" + } + ] + } + } + ] + ] +} \ No newline at end of file diff --git a/contracts/mutants/ETHPerFIN/1/FVR/ETHPerFIN.sol b/contracts/mutants/ETHPerFIN/1/FVR/ETHPerFIN.sol new file mode 100644 index 00000000000..e903c137aef --- /dev/null +++ b/contracts/mutants/ETHPerFIN/1/FVR/ETHPerFIN.sol @@ -0,0 +1,24 @@ +pragma solidity 0.5.14; + +import "openzeppelin-solidity/contracts/math/SafeMath.sol"; +// import "../config/Constant.sol"; + +interface mockERC20InterfaceFIN{ + function balanceOf(address owner) external view returns (uint); +} + +contract ETHPerFIN { + using SafeMath for uint256; + + // Constant public constants; + + address public FIN = 0x054f76beED60AB6dBEb23502178C52d6C5dEbE40; + address public WETH = 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2; + address public uniswap = 0x486792bcdb13F8aaCf85288D98850FA2804F95c7; + + function latestAnswer() external view returns (int256){ + uint balance0 = mockERC20InterfaceFIN(FIN).balanceOf(uniswap); // 383328811522809054672340 + uint balance1 = mockERC20InterfaceFIN(WETH).balanceOf(uniswap); // 646683755097326209560 + return int(balance1.mul(10 ** 18).div(balance0)); + } +} \ No newline at end of file diff --git a/contracts/mutants/ETHPerFIN/1/FVR/diff_result_difft.json b/contracts/mutants/ETHPerFIN/1/FVR/diff_result_difft.json new file mode 100644 index 00000000000..f4859126d83 --- /dev/null +++ b/contracts/mutants/ETHPerFIN/1/FVR/diff_result_difft.json @@ -0,0 +1,32 @@ +{ + "number_of_changes": 1, + "timing": 0.2598593235015869, + "diff_chunks": [ + [ + { + "lhs": { + "line_number": 18, + "changes": [ + { + "start": 28, + "end": 34, + "content": "public", + "highlight": "keyword" + } + ] + }, + "rhs": { + "line_number": 18, + "changes": [ + { + "start": 28, + "end": 36, + "content": "external", + "highlight": "keyword" + } + ] + } + } + ] + ] +} \ No newline at end of file diff --git a/contracts/mutants/ETHPerFIN/1/ILR/ETHPerFIN.sol b/contracts/mutants/ETHPerFIN/1/ILR/ETHPerFIN.sol new file mode 100644 index 00000000000..d801e154b94 --- /dev/null +++ b/contracts/mutants/ETHPerFIN/1/ILR/ETHPerFIN.sol @@ -0,0 +1,24 @@ +pragma solidity 0.5.14; + +import "openzeppelin-solidity/contracts/math/SafeMath.sol"; +// import "../config/Constant.sol"; + +interface mockERC20InterfaceFIN{ + function balanceOf(address owner) external view returns (uint); +} + +contract ETHPerFIN { + using SafeMath for uint256; + + // Constant public constants; + + address public FIN = 0x054f76beED60AB6dBEb23502178C52d6C5dEbE40; + address public WETH = 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2; + address public uniswap = 0x486792bcdb13F8aaCf85288D98850FA2804F95c7; + + function latestAnswer() public view returns (int256){ + uint balance0 = mockERC20InterfaceFIN(FIN).balanceOf(uniswap); // 383328811522809054672340 + uint balance1 = mockERC20InterfaceFIN(WETH).balanceOf(uniswap); // 646683755097326209560 + return int(balance1.mul(9 ** 18).div(balance0)); + } +} \ No newline at end of file diff --git a/contracts/mutants/ETHPerFIN/1/ILR/diff_result_difft.json b/contracts/mutants/ETHPerFIN/1/ILR/diff_result_difft.json new file mode 100644 index 00000000000..b260e41c74d --- /dev/null +++ b/contracts/mutants/ETHPerFIN/1/ILR/diff_result_difft.json @@ -0,0 +1,32 @@ +{ + "number_of_changes": 1, + "timing": 0.15599799156188965, + "diff_chunks": [ + [ + { + "lhs": { + "line_number": 21, + "changes": [ + { + "start": 32, + "end": 34, + "content": "10", + "highlight": "normal" + } + ] + }, + "rhs": { + "line_number": 21, + "changes": [ + { + "start": 32, + "end": 33, + "content": "9", + "highlight": "normal" + } + ] + } + } + ] + ] +} \ No newline at end of file diff --git a/contracts/mutants/ETHPerFIN/1/RSD/ETHPerFIN.sol b/contracts/mutants/ETHPerFIN/1/RSD/ETHPerFIN.sol new file mode 100644 index 00000000000..708313474d6 --- /dev/null +++ b/contracts/mutants/ETHPerFIN/1/RSD/ETHPerFIN.sol @@ -0,0 +1,24 @@ +pragma solidity 0.5.14; + +import "openzeppelin-solidity/contracts/math/SafeMath.sol"; +// import "../config/Constant.sol"; + +interface mockERC20InterfaceFIN{ + function balanceOf(address owner) external view returns (uint); +} + +contract ETHPerFIN { + using SafeMath for uint256; + + // Constant public constants; + + address public FIN = 0x054f76beED60AB6dBEb23502178C52d6C5dEbE40; + address public WETH = 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2; + address public uniswap = 0x486792bcdb13F8aaCf85288D98850FA2804F95c7; + + function latestAnswer() public view returns (int256){ + uint balance0 = mockERC20InterfaceFIN(FIN).balanceOf(uniswap); // 383328811522809054672340 + uint balance1 = mockERC20InterfaceFIN(WETH).balanceOf(uniswap); // 646683755097326209560 + /* return int(balance1.mul(10 ** 18).div(balance0)); */ + } +} \ No newline at end of file diff --git a/contracts/mutants/ETHPerFIN/1/RSD/diff_result_difft.json b/contracts/mutants/ETHPerFIN/1/RSD/diff_result_difft.json new file mode 100644 index 00000000000..f0d3ebb622e --- /dev/null +++ b/contracts/mutants/ETHPerFIN/1/RSD/diff_result_difft.json @@ -0,0 +1,128 @@ +{ + "number_of_changes": 17, + "timing": 0.1566774845123291, + "diff_chunks": [ + [ + { + "lhs": { + "line_number": 21, + "changes": [ + { + "start": 8, + "end": 14, + "content": "return", + "highlight": "keyword" + }, + { + "start": 15, + "end": 18, + "content": "int", + "highlight": "normal" + }, + { + "start": 18, + "end": 19, + "content": "(", + "highlight": "delimiter" + }, + { + "start": 19, + "end": 27, + "content": "balance1", + "highlight": "normal" + }, + { + "start": 27, + "end": 28, + "content": ".", + "highlight": "normal" + }, + { + "start": 28, + "end": 31, + "content": "mul", + "highlight": "normal" + }, + { + "start": 31, + "end": 32, + "content": "(", + "highlight": "delimiter" + }, + { + "start": 32, + "end": 34, + "content": "10", + "highlight": "normal" + }, + { + "start": 35, + "end": 37, + "content": "**", + "highlight": "keyword" + }, + { + "start": 38, + "end": 40, + "content": "18", + "highlight": "normal" + }, + { + "start": 40, + "end": 41, + "content": ")", + "highlight": "delimiter" + }, + { + "start": 41, + "end": 42, + "content": ".", + "highlight": "normal" + }, + { + "start": 42, + "end": 45, + "content": "div", + "highlight": "normal" + }, + { + "start": 45, + "end": 46, + "content": "(", + "highlight": "delimiter" + }, + { + "start": 46, + "end": 54, + "content": "balance0", + "highlight": "normal" + }, + { + "start": 54, + "end": 55, + "content": ")", + "highlight": "delimiter" + }, + { + "start": 55, + "end": 56, + "content": ")", + "highlight": "delimiter" + } + ] + }, + "rhs": { + "line_number": 21, + "changes": [ + { + "start": 8, + "end": 63, + "content": "/* return int(balance1.mul(10 ** 18).div(balance0)); */", + "highlight": "comment" + } + ] + } + } + ] + ] +} \ No newline at end of file diff --git a/contracts/mutants/ETHPerFIN/1/SFR/ETHPerFIN.sol b/contracts/mutants/ETHPerFIN/1/SFR/ETHPerFIN.sol new file mode 100644 index 00000000000..3d5cc1ba69c --- /dev/null +++ b/contracts/mutants/ETHPerFIN/1/SFR/ETHPerFIN.sol @@ -0,0 +1,24 @@ +pragma solidity 0.5.14; + +import "openzeppelin-solidity/contracts/math/SafeMath.sol"; +// import "../config/Constant.sol"; + +interface mockERC20InterfaceFIN{ + function balanceOf(address owner) external view returns (uint); +} + +contract ETHPerFIN { + using SafeMath for uint256; + + // Constant public constants; + + address public FIN = 0x054f76beED60AB6dBEb23502178C52d6C5dEbE40; + address public WETH = 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2; + address public uniswap = 0x486792bcdb13F8aaCf85288D98850FA2804F95c7; + + function latestAnswer() public view returns (int256){ + uint balance0 = mockERC20InterfaceFIN(FIN).balanceOf(uniswap); // 383328811522809054672340 + uint balance1 = mockERC20InterfaceFIN(WETH).balanceOf(uniswap); // 646683755097326209560 + return int(balance1.mul(10 ** 18).mul(balance0)); + } +} \ No newline at end of file diff --git a/contracts/mutants/ETHPerFIN/1/SFR/diff_result_difft.json b/contracts/mutants/ETHPerFIN/1/SFR/diff_result_difft.json new file mode 100644 index 00000000000..c687c9290b6 --- /dev/null +++ b/contracts/mutants/ETHPerFIN/1/SFR/diff_result_difft.json @@ -0,0 +1,32 @@ +{ + "number_of_changes": 1, + "timing": 0.2905588150024414, + "diff_chunks": [ + [ + { + "lhs": { + "line_number": 21, + "changes": [ + { + "start": 42, + "end": 45, + "content": "div", + "highlight": "normal" + } + ] + }, + "rhs": { + "line_number": 21, + "changes": [ + { + "start": 42, + "end": 45, + "content": "mul", + "highlight": "normal" + } + ] + } + } + ] + ] +} \ No newline at end of file diff --git a/contracts/mutants/ETHPerFIN/1/VVR/ETHPerFIN.sol b/contracts/mutants/ETHPerFIN/1/VVR/ETHPerFIN.sol new file mode 100644 index 00000000000..a3e08c8795d --- /dev/null +++ b/contracts/mutants/ETHPerFIN/1/VVR/ETHPerFIN.sol @@ -0,0 +1,24 @@ +pragma solidity 0.5.14; + +import "openzeppelin-solidity/contracts/math/SafeMath.sol"; +// import "../config/Constant.sol"; + +interface mockERC20InterfaceFIN{ + function balanceOf(address owner) external view returns (uint); +} + +contract ETHPerFIN { + using SafeMath for uint256; + + // Constant public constants; + + address internal FIN = 0x054f76beED60AB6dBEb23502178C52d6C5dEbE40; + address public WETH = 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2; + address public uniswap = 0x486792bcdb13F8aaCf85288D98850FA2804F95c7; + + function latestAnswer() public view returns (int256){ + uint balance0 = mockERC20InterfaceFIN(FIN).balanceOf(uniswap); // 383328811522809054672340 + uint balance1 = mockERC20InterfaceFIN(WETH).balanceOf(uniswap); // 646683755097326209560 + return int(balance1.mul(10 ** 18).div(balance0)); + } +} \ No newline at end of file diff --git a/contracts/mutants/ETHPerFIN/1/VVR/diff_result_difft.json b/contracts/mutants/ETHPerFIN/1/VVR/diff_result_difft.json new file mode 100644 index 00000000000..a23f02e5870 --- /dev/null +++ b/contracts/mutants/ETHPerFIN/1/VVR/diff_result_difft.json @@ -0,0 +1,32 @@ +{ + "number_of_changes": 1, + "timing": 0.4635751247406006, + "diff_chunks": [ + [ + { + "lhs": { + "line_number": 14, + "changes": [ + { + "start": 12, + "end": 18, + "content": "public", + "highlight": "keyword" + } + ] + }, + "rhs": { + "line_number": 14, + "changes": [ + { + "start": 12, + "end": 20, + "content": "internal", + "highlight": "keyword" + } + ] + } + } + ] + ] +} \ No newline at end of file diff --git a/contracts/mutants/ETHPerFIN/2/ILR/ETHPerFIN.sol b/contracts/mutants/ETHPerFIN/2/ILR/ETHPerFIN.sol new file mode 100644 index 00000000000..2d5da931c97 --- /dev/null +++ b/contracts/mutants/ETHPerFIN/2/ILR/ETHPerFIN.sol @@ -0,0 +1,24 @@ +pragma solidity 0.5.14; + +import "openzeppelin-solidity/contracts/math/SafeMath.sol"; +// import "../config/Constant.sol"; + +interface mockERC20InterfaceFIN{ + function balanceOf(address owner) external view returns (uint); +} + +contract ETHPerFIN { + using SafeMath for uint256; + + // Constant public constants; + + address public FIN = 0x054f76beED60AB6dBEb23502178C52d6C5dEbE40; + address public WETH = 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2; + address public uniswap = 0x486792bcdb13F8aaCf85288D98850FA2804F95c7; + + function latestAnswer() public view returns (int256){ + uint balance0 = mockERC20InterfaceFIN(FIN).balanceOf(uniswap); // 383328811522809054672340 + uint balance1 = mockERC20InterfaceFIN(WETH).balanceOf(uniswap); // 646683755097326209560 + return int(balance1.mul(9 ** 17).div(balance0)); + } +} \ No newline at end of file diff --git a/contracts/mutants/ETHPerFIN/2/ILR/diff_result_difft.json b/contracts/mutants/ETHPerFIN/2/ILR/diff_result_difft.json new file mode 100644 index 00000000000..83258567e33 --- /dev/null +++ b/contracts/mutants/ETHPerFIN/2/ILR/diff_result_difft.json @@ -0,0 +1,44 @@ +{ + "number_of_changes": 2, + "timing": 0.42983150482177734, + "diff_chunks": [ + [ + { + "lhs": { + "line_number": 21, + "changes": [ + { + "start": 32, + "end": 34, + "content": "10", + "highlight": "normal" + }, + { + "start": 38, + "end": 40, + "content": "18", + "highlight": "normal" + } + ] + }, + "rhs": { + "line_number": 21, + "changes": [ + { + "start": 32, + "end": 33, + "content": "9", + "highlight": "normal" + }, + { + "start": 37, + "end": 39, + "content": "17", + "highlight": "normal" + } + ] + } + } + ] + ] +} \ No newline at end of file diff --git a/contracts/mutants/ETHPerFIN/2/VVR/ETHPerFIN.sol b/contracts/mutants/ETHPerFIN/2/VVR/ETHPerFIN.sol new file mode 100644 index 00000000000..be762afa3bf --- /dev/null +++ b/contracts/mutants/ETHPerFIN/2/VVR/ETHPerFIN.sol @@ -0,0 +1,24 @@ +pragma solidity 0.5.14; + +import "openzeppelin-solidity/contracts/math/SafeMath.sol"; +// import "../config/Constant.sol"; + +interface mockERC20InterfaceFIN{ + function balanceOf(address owner) external view returns (uint); +} + +contract ETHPerFIN { + using SafeMath for uint256; + + // Constant public constants; + + address internal FIN = 0x054f76beED60AB6dBEb23502178C52d6C5dEbE40; + address internal WETH = 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2; + address public uniswap = 0x486792bcdb13F8aaCf85288D98850FA2804F95c7; + + function latestAnswer() public view returns (int256){ + uint balance0 = mockERC20InterfaceFIN(FIN).balanceOf(uniswap); // 383328811522809054672340 + uint balance1 = mockERC20InterfaceFIN(WETH).balanceOf(uniswap); // 646683755097326209560 + return int(balance1.mul(10 ** 18).div(balance0)); + } +} \ No newline at end of file diff --git a/contracts/mutants/ETHPerFIN/2/VVR/diff_result_difft.json b/contracts/mutants/ETHPerFIN/2/VVR/diff_result_difft.json new file mode 100644 index 00000000000..310cb55b763 --- /dev/null +++ b/contracts/mutants/ETHPerFIN/2/VVR/diff_result_difft.json @@ -0,0 +1,56 @@ +{ + "number_of_changes": 2, + "timing": 0.22017621994018555, + "diff_chunks": [ + [ + { + "lhs": { + "line_number": 15, + "changes": [ + { + "start": 12, + "end": 18, + "content": "public", + "highlight": "keyword" + } + ] + }, + "rhs": { + "line_number": 15, + "changes": [ + { + "start": 12, + "end": 20, + "content": "internal", + "highlight": "keyword" + } + ] + } + }, + { + "lhs": { + "line_number": 14, + "changes": [ + { + "start": 12, + "end": 18, + "content": "public", + "highlight": "keyword" + } + ] + }, + "rhs": { + "line_number": 14, + "changes": [ + { + "start": 12, + "end": 20, + "content": "internal", + "highlight": "keyword" + } + ] + } + } + ] + ] +} \ No newline at end of file diff --git a/contracts/mutants/ETHPerFIN/3/VVR/ETHPerFIN.sol b/contracts/mutants/ETHPerFIN/3/VVR/ETHPerFIN.sol new file mode 100644 index 00000000000..e868f3eb4ca --- /dev/null +++ b/contracts/mutants/ETHPerFIN/3/VVR/ETHPerFIN.sol @@ -0,0 +1,24 @@ +pragma solidity 0.5.14; + +import "openzeppelin-solidity/contracts/math/SafeMath.sol"; +// import "../config/Constant.sol"; + +interface mockERC20InterfaceFIN{ + function balanceOf(address owner) external view returns (uint); +} + +contract ETHPerFIN { + using SafeMath for uint256; + + // Constant public constants; + + address internal FIN = 0x054f76beED60AB6dBEb23502178C52d6C5dEbE40; + address internal WETH = 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2; + address internal uniswap = 0x486792bcdb13F8aaCf85288D98850FA2804F95c7; + + function latestAnswer() public view returns (int256){ + uint balance0 = mockERC20InterfaceFIN(FIN).balanceOf(uniswap); // 383328811522809054672340 + uint balance1 = mockERC20InterfaceFIN(WETH).balanceOf(uniswap); // 646683755097326209560 + return int(balance1.mul(10 ** 18).div(balance0)); + } +} \ No newline at end of file diff --git a/contracts/mutants/ETHPerFIN/3/VVR/diff_result_difft.json b/contracts/mutants/ETHPerFIN/3/VVR/diff_result_difft.json new file mode 100644 index 00000000000..d36c1d84f36 --- /dev/null +++ b/contracts/mutants/ETHPerFIN/3/VVR/diff_result_difft.json @@ -0,0 +1,80 @@ +{ + "number_of_changes": 3, + "timing": 0.09413743019104004, + "diff_chunks": [ + [ + { + "lhs": { + "line_number": 14, + "changes": [ + { + "start": 12, + "end": 18, + "content": "public", + "highlight": "keyword" + } + ] + }, + "rhs": { + "line_number": 14, + "changes": [ + { + "start": 12, + "end": 20, + "content": "internal", + "highlight": "keyword" + } + ] + } + }, + { + "lhs": { + "line_number": 15, + "changes": [ + { + "start": 12, + "end": 18, + "content": "public", + "highlight": "keyword" + } + ] + }, + "rhs": { + "line_number": 15, + "changes": [ + { + "start": 12, + "end": 20, + "content": "internal", + "highlight": "keyword" + } + ] + } + }, + { + "lhs": { + "line_number": 16, + "changes": [ + { + "start": 12, + "end": 18, + "content": "public", + "highlight": "keyword" + } + ] + }, + "rhs": { + "line_number": 16, + "changes": [ + { + "start": 12, + "end": 20, + "content": "internal", + "highlight": "keyword" + } + ] + } + } + ] + ] +} \ No newline at end of file diff --git a/contracts/mutants/ETHPerFIN/original/ETHPerFIN.sol b/contracts/mutants/ETHPerFIN/original/ETHPerFIN.sol new file mode 100644 index 00000000000..7aecd815c30 --- /dev/null +++ b/contracts/mutants/ETHPerFIN/original/ETHPerFIN.sol @@ -0,0 +1,24 @@ +pragma solidity 0.5.14; + +import "openzeppelin-solidity/contracts/math/SafeMath.sol"; +// import "../config/Constant.sol"; + +interface mockERC20InterfaceFIN{ + function balanceOf(address owner) external view returns (uint); +} + +contract ETHPerFIN { + using SafeMath for uint256; + + // Constant public constants; + + address public FIN = 0x054f76beED60AB6dBEb23502178C52d6C5dEbE40; + address public WETH = 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2; + address public uniswap = 0x486792bcdb13F8aaCf85288D98850FA2804F95c7; + + function latestAnswer() public view returns (int256){ + uint balance0 = mockERC20InterfaceFIN(FIN).balanceOf(uniswap); // 383328811522809054672340 + uint balance1 = mockERC20InterfaceFIN(WETH).balanceOf(uniswap); // 646683755097326209560 + return int(balance1.mul(10 ** 18).div(balance0)); + } +} \ No newline at end of file diff --git a/contracts/mutants/ETHPerLPToken/1/BOR/ETHPerLPToken.sol b/contracts/mutants/ETHPerLPToken/1/BOR/ETHPerLPToken.sol new file mode 100644 index 00000000000..7d033a4c335 --- /dev/null +++ b/contracts/mutants/ETHPerLPToken/1/BOR/ETHPerLPToken.sol @@ -0,0 +1,21 @@ +pragma solidity 0.5.14; + +import "openzeppelin-solidity/contracts/math/SafeMath.sol"; + +interface mockERC20InterfaceLP{ + function balanceOf(address owner) external view returns (uint); + function totalSupply() external view returns (uint256); +} + +contract ETHPerLPToken { + using SafeMath for uint256; + + address public WETH = 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2; + address public FIN_LP = 0x486792bcdb13F8aaCf85288D98850FA2804F95c7; + + function latestAnswer() public view returns (int256){ + uint balance = mockERC20InterfaceLP(WETH).balanceOf(FIN_LP); + uint totalSupply = mockERC20InterfaceLP(FIN_LP).totalSupply(); + return int(balance.mul(2).mul(10 + 18).div(totalSupply)); + } +} \ No newline at end of file diff --git a/contracts/mutants/ETHPerLPToken/1/ECS/ETHPerLPToken.sol b/contracts/mutants/ETHPerLPToken/1/ECS/ETHPerLPToken.sol new file mode 100644 index 00000000000..afbe83388c1 --- /dev/null +++ b/contracts/mutants/ETHPerLPToken/1/ECS/ETHPerLPToken.sol @@ -0,0 +1,21 @@ +pragma solidity 0.5.14; + +import "openzeppelin-solidity/contracts/math/SafeMath.sol"; + +interface mockERC20InterfaceLP{ + function balanceOf(address owner) external view returns (uint); + function totalSupply() external view returns (uint256); +} + +contract ETHPerLPToken { + using SafeMath for uint256; + + address public WETH = 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2; + address public FIN_LP = 0x486792bcdb13F8aaCf85288D98850FA2804F95c7; + + function latestAnswer() public view returns (int256){ + uint balance = mockERC20InterfaceLP(WETH).balanceOf(FIN_LP); + uint totalSupply = mockERC20InterfaceLP(FIN_LP).totalSupply(); + return int8(balance.mul(2).mul(10 ** 18).div(totalSupply)); + } +} \ No newline at end of file diff --git a/contracts/mutants/ETHPerLPToken/1/FVR/ETHPerLPToken.sol b/contracts/mutants/ETHPerLPToken/1/FVR/ETHPerLPToken.sol new file mode 100644 index 00000000000..beaf9c70d49 --- /dev/null +++ b/contracts/mutants/ETHPerLPToken/1/FVR/ETHPerLPToken.sol @@ -0,0 +1,21 @@ +pragma solidity 0.5.14; + +import "openzeppelin-solidity/contracts/math/SafeMath.sol"; + +interface mockERC20InterfaceLP{ + function balanceOf(address owner) external view returns (uint); + function totalSupply() external view returns (uint256); +} + +contract ETHPerLPToken { + using SafeMath for uint256; + + address public WETH = 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2; + address public FIN_LP = 0x486792bcdb13F8aaCf85288D98850FA2804F95c7; + + function latestAnswer() external view returns (int256){ + uint balance = mockERC20InterfaceLP(WETH).balanceOf(FIN_LP); + uint totalSupply = mockERC20InterfaceLP(FIN_LP).totalSupply(); + return int(balance.mul(2).mul(10 ** 18).div(totalSupply)); + } +} \ No newline at end of file diff --git a/contracts/mutants/ETHPerLPToken/1/ILR/ETHPerLPToken.sol b/contracts/mutants/ETHPerLPToken/1/ILR/ETHPerLPToken.sol new file mode 100644 index 00000000000..e0d2b717b6d --- /dev/null +++ b/contracts/mutants/ETHPerLPToken/1/ILR/ETHPerLPToken.sol @@ -0,0 +1,21 @@ +pragma solidity 0.5.14; + +import "openzeppelin-solidity/contracts/math/SafeMath.sol"; + +interface mockERC20InterfaceLP{ + function balanceOf(address owner) external view returns (uint); + function totalSupply() external view returns (uint256); +} + +contract ETHPerLPToken { + using SafeMath for uint256; + + address public WETH = 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2; + address public FIN_LP = 0x486792bcdb13F8aaCf85288D98850FA2804F95c7; + + function latestAnswer() public view returns (int256){ + uint balance = mockERC20InterfaceLP(WETH).balanceOf(FIN_LP); + uint totalSupply = mockERC20InterfaceLP(FIN_LP).totalSupply(); + return int(balance.mul(1).mul(10 ** 18).div(totalSupply)); + } +} \ No newline at end of file diff --git a/contracts/mutants/ETHPerLPToken/1/RSD/ETHPerLPToken.sol b/contracts/mutants/ETHPerLPToken/1/RSD/ETHPerLPToken.sol new file mode 100644 index 00000000000..24e9dc28860 --- /dev/null +++ b/contracts/mutants/ETHPerLPToken/1/RSD/ETHPerLPToken.sol @@ -0,0 +1,21 @@ +pragma solidity 0.5.14; + +import "openzeppelin-solidity/contracts/math/SafeMath.sol"; + +interface mockERC20InterfaceLP{ + function balanceOf(address owner) external view returns (uint); + function totalSupply() external view returns (uint256); +} + +contract ETHPerLPToken { + using SafeMath for uint256; + + address public WETH = 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2; + address public FIN_LP = 0x486792bcdb13F8aaCf85288D98850FA2804F95c7; + + function latestAnswer() public view returns (int256){ + uint balance = mockERC20InterfaceLP(WETH).balanceOf(FIN_LP); + uint totalSupply = mockERC20InterfaceLP(FIN_LP).totalSupply(); + /* return int(balance.mul(2).mul(10 ** 18).div(totalSupply)); */ + } +} \ No newline at end of file diff --git a/contracts/mutants/ETHPerLPToken/1/SFR/ETHPerLPToken.sol b/contracts/mutants/ETHPerLPToken/1/SFR/ETHPerLPToken.sol new file mode 100644 index 00000000000..98778a81364 --- /dev/null +++ b/contracts/mutants/ETHPerLPToken/1/SFR/ETHPerLPToken.sol @@ -0,0 +1,21 @@ +pragma solidity 0.5.14; + +import "openzeppelin-solidity/contracts/math/SafeMath.sol"; + +interface mockERC20InterfaceLP{ + function balanceOf(address owner) external view returns (uint); + function totalSupply() external view returns (uint256); +} + +contract ETHPerLPToken { + using SafeMath for uint256; + + address public WETH = 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2; + address public FIN_LP = 0x486792bcdb13F8aaCf85288D98850FA2804F95c7; + + function latestAnswer() public view returns (int256){ + uint balance = mockERC20InterfaceLP(WETH).balanceOf(FIN_LP); + uint totalSupply = mockERC20InterfaceLP(FIN_LP).totalSupply(); + return int(balance.mul(2).mul(10 ** 18).mul(totalSupply)); + } +} \ No newline at end of file diff --git a/contracts/mutants/ETHPerLPToken/1/VVR/ETHPerLPToken.sol b/contracts/mutants/ETHPerLPToken/1/VVR/ETHPerLPToken.sol new file mode 100644 index 00000000000..01c5be22ff0 --- /dev/null +++ b/contracts/mutants/ETHPerLPToken/1/VVR/ETHPerLPToken.sol @@ -0,0 +1,21 @@ +pragma solidity 0.5.14; + +import "openzeppelin-solidity/contracts/math/SafeMath.sol"; + +interface mockERC20InterfaceLP{ + function balanceOf(address owner) external view returns (uint); + function totalSupply() external view returns (uint256); +} + +contract ETHPerLPToken { + using SafeMath for uint256; + + address internal WETH = 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2; + address public FIN_LP = 0x486792bcdb13F8aaCf85288D98850FA2804F95c7; + + function latestAnswer() public view returns (int256){ + uint balance = mockERC20InterfaceLP(WETH).balanceOf(FIN_LP); + uint totalSupply = mockERC20InterfaceLP(FIN_LP).totalSupply(); + return int(balance.mul(2).mul(10 ** 18).div(totalSupply)); + } +} \ No newline at end of file diff --git a/contracts/mutants/ETHPerLPToken/2/ILR/ETHPerLPToken.sol b/contracts/mutants/ETHPerLPToken/2/ILR/ETHPerLPToken.sol new file mode 100644 index 00000000000..b5d57959da3 --- /dev/null +++ b/contracts/mutants/ETHPerLPToken/2/ILR/ETHPerLPToken.sol @@ -0,0 +1,21 @@ +pragma solidity 0.5.14; + +import "openzeppelin-solidity/contracts/math/SafeMath.sol"; + +interface mockERC20InterfaceLP{ + function balanceOf(address owner) external view returns (uint); + function totalSupply() external view returns (uint256); +} + +contract ETHPerLPToken { + using SafeMath for uint256; + + address public WETH = 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2; + address public FIN_LP = 0x486792bcdb13F8aaCf85288D98850FA2804F95c7; + + function latestAnswer() public view returns (int256){ + uint balance = mockERC20InterfaceLP(WETH).balanceOf(FIN_LP); + uint totalSupply = mockERC20InterfaceLP(FIN_LP).totalSupply(); + return int(balance.mul(1).mul(9 ** 18).div(totalSupply)); + } +} \ No newline at end of file diff --git a/contracts/mutants/ETHPerLPToken/2/VVR/ETHPerLPToken.sol b/contracts/mutants/ETHPerLPToken/2/VVR/ETHPerLPToken.sol new file mode 100644 index 00000000000..45ab55787f2 --- /dev/null +++ b/contracts/mutants/ETHPerLPToken/2/VVR/ETHPerLPToken.sol @@ -0,0 +1,21 @@ +pragma solidity 0.5.14; + +import "openzeppelin-solidity/contracts/math/SafeMath.sol"; + +interface mockERC20InterfaceLP{ + function balanceOf(address owner) external view returns (uint); + function totalSupply() external view returns (uint256); +} + +contract ETHPerLPToken { + using SafeMath for uint256; + + address internal WETH = 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2; + address internal FIN_LP = 0x486792bcdb13F8aaCf85288D98850FA2804F95c7; + + function latestAnswer() public view returns (int256){ + uint balance = mockERC20InterfaceLP(WETH).balanceOf(FIN_LP); + uint totalSupply = mockERC20InterfaceLP(FIN_LP).totalSupply(); + return int(balance.mul(2).mul(10 ** 18).div(totalSupply)); + } +} \ No newline at end of file diff --git a/contracts/mutants/ETHPerLPToken/3/ILR/ETHPerLPToken.sol b/contracts/mutants/ETHPerLPToken/3/ILR/ETHPerLPToken.sol new file mode 100644 index 00000000000..4ff5c699724 --- /dev/null +++ b/contracts/mutants/ETHPerLPToken/3/ILR/ETHPerLPToken.sol @@ -0,0 +1,21 @@ +pragma solidity 0.5.14; + +import "openzeppelin-solidity/contracts/math/SafeMath.sol"; + +interface mockERC20InterfaceLP{ + function balanceOf(address owner) external view returns (uint); + function totalSupply() external view returns (uint256); +} + +contract ETHPerLPToken { + using SafeMath for uint256; + + address public WETH = 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2; + address public FIN_LP = 0x486792bcdb13F8aaCf85288D98850FA2804F95c7; + + function latestAnswer() public view returns (int256){ + uint balance = mockERC20InterfaceLP(WETH).balanceOf(FIN_LP); + uint totalSupply = mockERC20InterfaceLP(FIN_LP).totalSupply(); + return int(balance.mul(1).mul(9 ** 17).div(totalSupply)); + } +} \ No newline at end of file diff --git a/contracts/mutants/ETHPerLPToken/original/ETHPerLPToken.sol b/contracts/mutants/ETHPerLPToken/original/ETHPerLPToken.sol new file mode 100644 index 00000000000..a17fd3c6194 --- /dev/null +++ b/contracts/mutants/ETHPerLPToken/original/ETHPerLPToken.sol @@ -0,0 +1,21 @@ +pragma solidity 0.5.14; + +import "openzeppelin-solidity/contracts/math/SafeMath.sol"; + +interface mockERC20InterfaceLP{ + function balanceOf(address owner) external view returns (uint); + function totalSupply() external view returns (uint256); +} + +contract ETHPerLPToken { + using SafeMath for uint256; + + address public WETH = 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2; + address public FIN_LP = 0x486792bcdb13F8aaCf85288D98850FA2804F95c7; + + function latestAnswer() public view returns (int256){ + uint balance = mockERC20InterfaceLP(WETH).balanceOf(FIN_LP); + uint totalSupply = mockERC20InterfaceLP(FIN_LP).totalSupply(); + return int(balance.mul(2).mul(10 ** 18).div(totalSupply)); + } +} \ No newline at end of file diff --git a/contracts/mutants/ETHRegistrarController/1/BOR/ETHRegistrarController.sol b/contracts/mutants/ETHRegistrarController/1/BOR/ETHRegistrarController.sol new file mode 100644 index 00000000000..f643fe1d66e --- /dev/null +++ b/contracts/mutants/ETHRegistrarController/1/BOR/ETHRegistrarController.sol @@ -0,0 +1,103 @@ +pragma solidity ^0.5.0; + +import "./PriceOracle.sol"; +import "./BaseRegistrar.sol"; +import "./StringUtils.sol"; +import "openzeppelin-solidity/contracts/ownership/Ownable.sol"; + +/** + * @dev A registrar controller for registering and renewing names at fixed cost. + */ +contract ETHRegistrarController is Ownable { + using StringUtils for *; + + uint constant public MIN_COMMITMENT_AGE = 1 hours; + uint constant public MAX_COMMITMENT_AGE = 48 hours; + uint constant public MIN_REGISTRATION_DURATION = 28 days; + + BaseRegistrar base; + PriceOracle prices; + + mapping(bytes32=>uint) public commitments; + + event NameRegistered(string name, address indexed owner, uint cost, uint expires); + event NameRenewed(string name, uint cost, uint expires); + event NewPriceOracle(address indexed oracle); + + constructor(BaseRegistrar _base, PriceOracle _prices) public { + base = _base; + prices = _prices; + } + + function rentPrice(string memory name, uint duration) view public returns(uint) { + bytes32 hash = keccak256(bytes(name)); + return prices.price(name, base.nameExpires(uint256(hash)), duration); + } + + function valid(string memory name) public view returns(bool) { + return name.strlen() >= 6; + } + + function available(string memory name) public view returns(bool) { + bytes32 label = keccak256(bytes(name)); + return valid(name) && base.available(uint256(label)); + } + // SWC-114-Transaction Order Dependence: L46-L49 + function makeCommitment(string memory name, bytes32 secret) pure public returns(bytes32) { + bytes32 label = keccak256(bytes(name)); + return keccak256(abi.encodePacked(label, secret)); + } + + function commit(bytes32 commitment) public { + require(commitments[commitment] + MAX_COMMITMENT_AGE < now); + commitments[commitment] = now; + } + // SWC-104-Unchecked Call Return Value: L56-L65 + function register(string calldata name, address owner, uint duration, bytes32 secret) external payable { + // Require a valid commitment + bytes32 commitment = makeCommitment(name, secret); + require(commitments[commitment] + MIN_COMMITMENT_AGE <= now); + + // If the commitment is too old, or the name is registered, stop + if(commitments[commitment] + MAX_COMMITMENT_AGE < now || !available(name)) { + msg.sender.transfer(msg.value); + return; + } + delete(commitments[commitment]); + + uint cost = rentPrice(name, duration); + require(duration >= MIN_REGISTRATION_DURATION); + require(msg.value >= cost); + + bytes32 label = keccak256(bytes(name)); + uint expires = base.register(uint256(label), owner, duration); + emit NameRegistered(name, owner, cost, expires); + + if(msg.value > cost) { + msg.sender.transfer(msg.value - cost); + } + } + + function renew(string calldata name, uint duration) external payable { + uint cost = rentPrice(name, duration); + require(msg.value >= cost); + + bytes32 label = keccak256(bytes(name)); + uint expires = base.renew(uint256(label), duration); + + if(msg.value > cost) { + msg.sender.transfer(msg.value - cost); + } + + emit NameRenewed(name, cost, expires); + } + + function setPriceOracle(PriceOracle _prices) public onlyOwner { + prices = _prices; + emit NewPriceOracle(address(prices)); + } + + function withdraw() public onlyOwner { + msg.sender.transfer(address(this).balance); + } +} diff --git a/contracts/mutants/ETHRegistrarController/1/BOR/diff_result_difft.json b/contracts/mutants/ETHRegistrarController/1/BOR/diff_result_difft.json new file mode 100644 index 00000000000..8e2da71fb1b --- /dev/null +++ b/contracts/mutants/ETHRegistrarController/1/BOR/diff_result_difft.json @@ -0,0 +1,32 @@ +{ + "number_of_changes": 1, + "timing": 0.3385183811187744, + "diff_chunks": [ + [ + { + "lhs": { + "line_number": 37, + "changes": [ + { + "start": 29, + "end": 30, + "content": ">", + "highlight": "keyword" + } + ] + }, + "rhs": { + "line_number": 37, + "changes": [ + { + "start": 29, + "end": 31, + "content": ">=", + "highlight": "keyword" + } + ] + } + } + ] + ] +} \ No newline at end of file diff --git a/contracts/mutants/ETHRegistrarController/1/CCD/ETHRegistrarController.sol b/contracts/mutants/ETHRegistrarController/1/CCD/ETHRegistrarController.sol new file mode 100644 index 00000000000..f52c5120bc3 --- /dev/null +++ b/contracts/mutants/ETHRegistrarController/1/CCD/ETHRegistrarController.sol @@ -0,0 +1,100 @@ +pragma solidity ^0.5.0; + +import "./PriceOracle.sol"; +import "./BaseRegistrar.sol"; +import "./StringUtils.sol"; +import "openzeppelin-solidity/contracts/ownership/Ownable.sol"; + +/** + * @dev A registrar controller for registering and renewing names at fixed cost. + */ +contract ETHRegistrarController is Ownable { + using StringUtils for *; + + uint constant public MIN_COMMITMENT_AGE = 1 hours; + uint constant public MAX_COMMITMENT_AGE = 48 hours; + uint constant public MIN_REGISTRATION_DURATION = 28 days; + + BaseRegistrar base; + PriceOracle prices; + + mapping(bytes32=>uint) public commitments; + + event NameRegistered(string name, address indexed owner, uint cost, uint expires); + event NameRenewed(string name, uint cost, uint expires); + event NewPriceOracle(address indexed oracle); + + + + function rentPrice(string memory name, uint duration) view public returns(uint) { + bytes32 hash = keccak256(bytes(name)); + return prices.price(name, base.nameExpires(uint256(hash)), duration); + } + + function valid(string memory name) public view returns(bool) { + return name.strlen() > 6; + } + + function available(string memory name) public view returns(bool) { + bytes32 label = keccak256(bytes(name)); + return valid(name) && base.available(uint256(label)); + } + // SWC-114-Transaction Order Dependence: L46-L49 + function makeCommitment(string memory name, bytes32 secret) pure public returns(bytes32) { + bytes32 label = keccak256(bytes(name)); + return keccak256(abi.encodePacked(label, secret)); + } + + function commit(bytes32 commitment) public { + require(commitments[commitment] + MAX_COMMITMENT_AGE < now); + commitments[commitment] = now; + } + // SWC-104-Unchecked Call Return Value: L56-L65 + function register(string calldata name, address owner, uint duration, bytes32 secret) external payable { + // Require a valid commitment + bytes32 commitment = makeCommitment(name, secret); + require(commitments[commitment] + MIN_COMMITMENT_AGE <= now); + + // If the commitment is too old, or the name is registered, stop + if(commitments[commitment] + MAX_COMMITMENT_AGE < now || !available(name)) { + msg.sender.transfer(msg.value); + return; + } + delete(commitments[commitment]); + + uint cost = rentPrice(name, duration); + require(duration >= MIN_REGISTRATION_DURATION); + require(msg.value >= cost); + + bytes32 label = keccak256(bytes(name)); + uint expires = base.register(uint256(label), owner, duration); + emit NameRegistered(name, owner, cost, expires); + + if(msg.value > cost) { + msg.sender.transfer(msg.value - cost); + } + } + + function renew(string calldata name, uint duration) external payable { + uint cost = rentPrice(name, duration); + require(msg.value >= cost); + + bytes32 label = keccak256(bytes(name)); + uint expires = base.renew(uint256(label), duration); + + if(msg.value > cost) { + msg.sender.transfer(msg.value - cost); + } + + emit NameRenewed(name, cost, expires); + } + + function setPriceOracle(PriceOracle _prices) public onlyOwner { + prices = _prices; + emit NewPriceOracle(address(prices)); + } + + function withdraw() public onlyOwner { + msg.sender.transfer(address(this).balance); + } +} diff --git a/contracts/mutants/ETHRegistrarController/1/CCD/diff_result_difft.json b/contracts/mutants/ETHRegistrarController/1/CCD/diff_result_difft.json new file mode 100644 index 00000000000..f7103a3480c --- /dev/null +++ b/contracts/mutants/ETHRegistrarController/1/CCD/diff_result_difft.json @@ -0,0 +1,142 @@ +{ + "number_of_changes": 17, + "timing": 0.1852564811706543, + "diff_chunks": [ + [ + { + "lhs": { + "line_number": 29, + "changes": [ + { + "start": 4, + "end": 5, + "content": "}", + "highlight": "delimiter" + } + ] + } + }, + { + "lhs": { + "line_number": 26, + "changes": [ + { + "start": 4, + "end": 15, + "content": "constructor", + "highlight": "type" + }, + { + "start": 15, + "end": 16, + "content": "(", + "highlight": "delimiter" + }, + { + "start": 16, + "end": 29, + "content": "BaseRegistrar", + "highlight": "type" + }, + { + "start": 30, + "end": 35, + "content": "_base", + "highlight": "normal" + }, + { + "start": 35, + "end": 36, + "content": ",", + "highlight": "normal" + }, + { + "start": 37, + "end": 48, + "content": "PriceOracle", + "highlight": "type" + }, + { + "start": 49, + "end": 56, + "content": "_prices", + "highlight": "normal" + }, + { + "start": 56, + "end": 57, + "content": ")", + "highlight": "delimiter" + }, + { + "start": 58, + "end": 64, + "content": "public", + "highlight": "keyword" + }, + { + "start": 65, + "end": 66, + "content": "{", + "highlight": "delimiter" + } + ] + }, + "rhs": { + "line_number": 26, + "changes": [] + } + }, + { + "lhs": { + "line_number": 27, + "changes": [ + { + "start": 8, + "end": 12, + "content": "base", + "highlight": "normal" + }, + { + "start": 13, + "end": 14, + "content": "=", + "highlight": "normal" + }, + { + "start": 15, + "end": 20, + "content": "_base", + "highlight": "normal" + } + ] + } + }, + { + "lhs": { + "line_number": 28, + "changes": [ + { + "start": 8, + "end": 14, + "content": "prices", + "highlight": "normal" + }, + { + "start": 15, + "end": 16, + "content": "=", + "highlight": "normal" + }, + { + "start": 17, + "end": 24, + "content": "_prices", + "highlight": "normal" + } + ] + } + } + ] + ] +} \ No newline at end of file diff --git a/contracts/mutants/ETHRegistrarController/1/CSC/ETHRegistrarController.sol b/contracts/mutants/ETHRegistrarController/1/CSC/ETHRegistrarController.sol new file mode 100644 index 00000000000..c4a8e897fe4 --- /dev/null +++ b/contracts/mutants/ETHRegistrarController/1/CSC/ETHRegistrarController.sol @@ -0,0 +1,103 @@ +pragma solidity ^0.5.0; + +import "./PriceOracle.sol"; +import "./BaseRegistrar.sol"; +import "./StringUtils.sol"; +import "openzeppelin-solidity/contracts/ownership/Ownable.sol"; + +/** + * @dev A registrar controller for registering and renewing names at fixed cost. + */ +contract ETHRegistrarController is Ownable { + using StringUtils for *; + + uint constant public MIN_COMMITMENT_AGE = 1 hours; + uint constant public MAX_COMMITMENT_AGE = 48 hours; + uint constant public MIN_REGISTRATION_DURATION = 28 days; + + BaseRegistrar base; + PriceOracle prices; + + mapping(bytes32=>uint) public commitments; + + event NameRegistered(string name, address indexed owner, uint cost, uint expires); + event NameRenewed(string name, uint cost, uint expires); + event NewPriceOracle(address indexed oracle); + + constructor(BaseRegistrar _base, PriceOracle _prices) public { + base = _base; + prices = _prices; + } + + function rentPrice(string memory name, uint duration) view public returns(uint) { + bytes32 hash = keccak256(bytes(name)); + return prices.price(name, base.nameExpires(uint256(hash)), duration); + } + + function valid(string memory name) public view returns(bool) { + return name.strlen() > 6; + } + + function available(string memory name) public view returns(bool) { + bytes32 label = keccak256(bytes(name)); + return valid(name) && base.available(uint256(label)); + } + // SWC-114-Transaction Order Dependence: L46-L49 + function makeCommitment(string memory name, bytes32 secret) pure public returns(bytes32) { + bytes32 label = keccak256(bytes(name)); + return keccak256(abi.encodePacked(label, secret)); + } + + function commit(bytes32 commitment) public { + require(commitments[commitment] + MAX_COMMITMENT_AGE < now); + commitments[commitment] = now; + } + // SWC-104-Unchecked Call Return Value: L56-L65 + function register(string calldata name, address owner, uint duration, bytes32 secret) external payable { + // Require a valid commitment + bytes32 commitment = makeCommitment(name, secret); + require(commitments[commitment] + MIN_COMMITMENT_AGE <= now); + + // If the commitment is too old, or the name is registered, stop + if(true) { + msg.sender.transfer(msg.value); + return; + } + delete(commitments[commitment]); + + uint cost = rentPrice(name, duration); + require(duration >= MIN_REGISTRATION_DURATION); + require(msg.value >= cost); + + bytes32 label = keccak256(bytes(name)); + uint expires = base.register(uint256(label), owner, duration); + emit NameRegistered(name, owner, cost, expires); + + if(msg.value > cost) { + msg.sender.transfer(msg.value - cost); + } + } + + function renew(string calldata name, uint duration) external payable { + uint cost = rentPrice(name, duration); + require(msg.value >= cost); + + bytes32 label = keccak256(bytes(name)); + uint expires = base.renew(uint256(label), duration); + + if(msg.value > cost) { + msg.sender.transfer(msg.value - cost); + } + + emit NameRenewed(name, cost, expires); + } + + function setPriceOracle(PriceOracle _prices) public onlyOwner { + prices = _prices; + emit NewPriceOracle(address(prices)); + } + + function withdraw() public onlyOwner { + msg.sender.transfer(address(this).balance); + } +} diff --git a/contracts/mutants/ETHRegistrarController/1/CSC/diff_result_difft.json b/contracts/mutants/ETHRegistrarController/1/CSC/diff_result_difft.json new file mode 100644 index 00000000000..f3cc2b66045 --- /dev/null +++ b/contracts/mutants/ETHRegistrarController/1/CSC/diff_result_difft.json @@ -0,0 +1,110 @@ +{ + "number_of_changes": 14, + "timing": 0.4248812198638916, + "diff_chunks": [ + [ + { + "lhs": { + "line_number": 61, + "changes": [ + { + "start": 11, + "end": 22, + "content": "commitments", + "highlight": "normal" + }, + { + "start": 22, + "end": 23, + "content": "[", + "highlight": "delimiter" + }, + { + "start": 23, + "end": 33, + "content": "commitment", + "highlight": "normal" + }, + { + "start": 33, + "end": 34, + "content": "]", + "highlight": "delimiter" + }, + { + "start": 35, + "end": 36, + "content": "+", + "highlight": "keyword" + }, + { + "start": 37, + "end": 55, + "content": "MAX_COMMITMENT_AGE", + "highlight": "normal" + }, + { + "start": 56, + "end": 57, + "content": "<", + "highlight": "keyword" + }, + { + "start": 58, + "end": 61, + "content": "now", + "highlight": "normal" + }, + { + "start": 62, + "end": 64, + "content": "||", + "highlight": "keyword" + }, + { + "start": 65, + "end": 66, + "content": "!", + "highlight": "keyword" + }, + { + "start": 66, + "end": 75, + "content": "available", + "highlight": "normal" + }, + { + "start": 75, + "end": 76, + "content": "(", + "highlight": "delimiter" + }, + { + "start": 76, + "end": 80, + "content": "name", + "highlight": "normal" + }, + { + "start": 80, + "end": 81, + "content": ")", + "highlight": "delimiter" + } + ] + }, + "rhs": { + "line_number": 61, + "changes": [ + { + "start": 11, + "end": 15, + "content": "true", + "highlight": "normal" + } + ] + } + } + ] + ] +} \ No newline at end of file diff --git a/contracts/mutants/ETHRegistrarController/1/DLR/ETHRegistrarController.sol b/contracts/mutants/ETHRegistrarController/1/DLR/ETHRegistrarController.sol new file mode 100644 index 00000000000..551d220ebbb --- /dev/null +++ b/contracts/mutants/ETHRegistrarController/1/DLR/ETHRegistrarController.sol @@ -0,0 +1,103 @@ +pragma solidity ^0.5.0; + +import "./PriceOracle.sol"; +import "./BaseRegistrar.sol"; +import "./StringUtils.sol"; +import "openzeppelin-solidity/contracts/ownership/Ownable.sol"; + +/** + * @dev A registrar controller for registering and renewing names at fixed cost. + */ +contract ETHRegistrarController is Ownable { + using StringUtils for *; + + uint constant public MIN_COMMITMENT_AGE = 1 hours; + uint constant public MAX_COMMITMENT_AGE = 48 hours; + uint constant public MIN_REGISTRATION_DURATION = 28 days; + + BaseRegistrar base; + PriceOracle prices; + + mapping(bytes32=>uint) public commitments; + + event NameRegistered(string name, address indexed owner, uint cost, uint expires); + event NameRenewed(string name, uint cost, uint expires); + event NewPriceOracle(address indexed oracle); + + constructor(BaseRegistrar _base, PriceOracle _prices) public { + base = _base; + prices = _prices; + } + + function rentPrice(string storage name, uint duration) view public returns(uint) { + bytes32 hash = keccak256(bytes(name)); + return prices.price(name, base.nameExpires(uint256(hash)), duration); + } + + function valid(string memory name) public view returns(bool) { + return name.strlen() > 6; + } + + function available(string memory name) public view returns(bool) { + bytes32 label = keccak256(bytes(name)); + return valid(name) && base.available(uint256(label)); + } + // SWC-114-Transaction Order Dependence: L46-L49 + function makeCommitment(string memory name, bytes32 secret) pure public returns(bytes32) { + bytes32 label = keccak256(bytes(name)); + return keccak256(abi.encodePacked(label, secret)); + } + + function commit(bytes32 commitment) public { + require(commitments[commitment] + MAX_COMMITMENT_AGE < now); + commitments[commitment] = now; + } + // SWC-104-Unchecked Call Return Value: L56-L65 + function register(string calldata name, address owner, uint duration, bytes32 secret) external payable { + // Require a valid commitment + bytes32 commitment = makeCommitment(name, secret); + require(commitments[commitment] + MIN_COMMITMENT_AGE <= now); + + // If the commitment is too old, or the name is registered, stop + if(commitments[commitment] + MAX_COMMITMENT_AGE < now || !available(name)) { + msg.sender.transfer(msg.value); + return; + } + delete(commitments[commitment]); + + uint cost = rentPrice(name, duration); + require(duration >= MIN_REGISTRATION_DURATION); + require(msg.value >= cost); + + bytes32 label = keccak256(bytes(name)); + uint expires = base.register(uint256(label), owner, duration); + emit NameRegistered(name, owner, cost, expires); + + if(msg.value > cost) { + msg.sender.transfer(msg.value - cost); + } + } + + function renew(string calldata name, uint duration) external payable { + uint cost = rentPrice(name, duration); + require(msg.value >= cost); + + bytes32 label = keccak256(bytes(name)); + uint expires = base.renew(uint256(label), duration); + + if(msg.value > cost) { + msg.sender.transfer(msg.value - cost); + } + + emit NameRenewed(name, cost, expires); + } + + function setPriceOracle(PriceOracle _prices) public onlyOwner { + prices = _prices; + emit NewPriceOracle(address(prices)); + } + + function withdraw() public onlyOwner { + msg.sender.transfer(address(this).balance); + } +} diff --git a/contracts/mutants/ETHRegistrarController/1/DLR/diff_result_difft.json b/contracts/mutants/ETHRegistrarController/1/DLR/diff_result_difft.json new file mode 100644 index 00000000000..74d955f6efd --- /dev/null +++ b/contracts/mutants/ETHRegistrarController/1/DLR/diff_result_difft.json @@ -0,0 +1,32 @@ +{ + "number_of_changes": 1, + "timing": 0.17064142227172852, + "diff_chunks": [ + [ + { + "lhs": { + "line_number": 31, + "changes": [ + { + "start": 30, + "end": 36, + "content": "memory", + "highlight": "keyword" + } + ] + }, + "rhs": { + "line_number": 31, + "changes": [ + { + "start": 30, + "end": 37, + "content": "storage", + "highlight": "keyword" + } + ] + } + } + ] + ] +} \ No newline at end of file diff --git a/contracts/mutants/ETHRegistrarController/1/DOD/ETHRegistrarController.sol b/contracts/mutants/ETHRegistrarController/1/DOD/ETHRegistrarController.sol new file mode 100644 index 00000000000..fb525444fde --- /dev/null +++ b/contracts/mutants/ETHRegistrarController/1/DOD/ETHRegistrarController.sol @@ -0,0 +1,103 @@ +pragma solidity ^0.5.0; + +import "./PriceOracle.sol"; +import "./BaseRegistrar.sol"; +import "./StringUtils.sol"; +import "openzeppelin-solidity/contracts/ownership/Ownable.sol"; + +/** + * @dev A registrar controller for registering and renewing names at fixed cost. + */ +contract ETHRegistrarController is Ownable { + using StringUtils for *; + + uint constant public MIN_COMMITMENT_AGE = 1 hours; + uint constant public MAX_COMMITMENT_AGE = 48 hours; + uint constant public MIN_REGISTRATION_DURATION = 28 days; + + BaseRegistrar base; + PriceOracle prices; + + mapping(bytes32=>uint) public commitments; + + event NameRegistered(string name, address indexed owner, uint cost, uint expires); + event NameRenewed(string name, uint cost, uint expires); + event NewPriceOracle(address indexed oracle); + + constructor(BaseRegistrar _base, PriceOracle _prices) public { + base = _base; + prices = _prices; + } + + function rentPrice(string memory name, uint duration) view public returns(uint) { + bytes32 hash = keccak256(bytes(name)); + return prices.price(name, base.nameExpires(uint256(hash)), duration); + } + + function valid(string memory name) public view returns(bool) { + return name.strlen() > 6; + } + + function available(string memory name) public view returns(bool) { + bytes32 label = keccak256(bytes(name)); + return valid(name) && base.available(uint256(label)); + } + // SWC-114-Transaction Order Dependence: L46-L49 + function makeCommitment(string memory name, bytes32 secret) pure public returns(bytes32) { + bytes32 label = keccak256(bytes(name)); + return keccak256(abi.encodePacked(label, secret)); + } + + function commit(bytes32 commitment) public { + require(commitments[commitment] + MAX_COMMITMENT_AGE < now); + commitments[commitment] = now; + } + // SWC-104-Unchecked Call Return Value: L56-L65 + function register(string calldata name, address owner, uint duration, bytes32 secret) external payable { + // Require a valid commitment + bytes32 commitment = makeCommitment(name, secret); + require(commitments[commitment] + MIN_COMMITMENT_AGE <= now); + + // If the commitment is too old, or the name is registered, stop + if(commitments[commitment] + MAX_COMMITMENT_AGE < now || !available(name)) { + msg.sender.transfer(msg.value); + return; + } + (commitments[commitment]); + + uint cost = rentPrice(name, duration); + require(duration >= MIN_REGISTRATION_DURATION); + require(msg.value >= cost); + + bytes32 label = keccak256(bytes(name)); + uint expires = base.register(uint256(label), owner, duration); + emit NameRegistered(name, owner, cost, expires); + + if(msg.value > cost) { + msg.sender.transfer(msg.value - cost); + } + } + + function renew(string calldata name, uint duration) external payable { + uint cost = rentPrice(name, duration); + require(msg.value >= cost); + + bytes32 label = keccak256(bytes(name)); + uint expires = base.renew(uint256(label), duration); + + if(msg.value > cost) { + msg.sender.transfer(msg.value - cost); + } + + emit NameRenewed(name, cost, expires); + } + + function setPriceOracle(PriceOracle _prices) public onlyOwner { + prices = _prices; + emit NewPriceOracle(address(prices)); + } + + function withdraw() public onlyOwner { + msg.sender.transfer(address(this).balance); + } +} diff --git a/contracts/mutants/ETHRegistrarController/1/DOD/diff_result_difft.json b/contracts/mutants/ETHRegistrarController/1/DOD/diff_result_difft.json new file mode 100644 index 00000000000..cb858d49500 --- /dev/null +++ b/contracts/mutants/ETHRegistrarController/1/DOD/diff_result_difft.json @@ -0,0 +1,25 @@ +{ + "number_of_changes": 1, + "timing": 0.22175908088684082, + "diff_chunks": [ + [ + { + "lhs": { + "line_number": 65, + "changes": [ + { + "start": 8, + "end": 14, + "content": "delete", + "highlight": "keyword" + } + ] + }, + "rhs": { + "line_number": 65, + "changes": [] + } + } + ] + ] +} \ No newline at end of file diff --git a/contracts/mutants/ETHRegistrarController/1/ECS/ETHRegistrarController.sol b/contracts/mutants/ETHRegistrarController/1/ECS/ETHRegistrarController.sol new file mode 100644 index 00000000000..00e0cf5e475 --- /dev/null +++ b/contracts/mutants/ETHRegistrarController/1/ECS/ETHRegistrarController.sol @@ -0,0 +1,103 @@ +pragma solidity ^0.5.0; + +import "./PriceOracle.sol"; +import "./BaseRegistrar.sol"; +import "./StringUtils.sol"; +import "openzeppelin-solidity/contracts/ownership/Ownable.sol"; + +/** + * @dev A registrar controller for registering and renewing names at fixed cost. + */ +contract ETHRegistrarController is Ownable { + using StringUtils for *; + + uint constant public MIN_COMMITMENT_AGE = 1 hours; + uint constant public MAX_COMMITMENT_AGE = 48 hours; + uint constant public MIN_REGISTRATION_DURATION = 28 days; + + BaseRegistrar base; + PriceOracle prices; + + mapping(bytes32=>uint) public commitments; + + event NameRegistered(string name, address indexed owner, uint cost, uint expires); + event NameRenewed(string name, uint cost, uint expires); + event NewPriceOracle(address indexed oracle); + + constructor(BaseRegistrar _base, PriceOracle _prices) public { + base = _base; + prices = _prices; + } + + function rentPrice(string memory name, uint duration) view public returns(uint) { + bytes32 hash = keccak256(bytes1(name)); + return prices.price(name, base.nameExpires(uint256(hash)), duration); + } + + function valid(string memory name) public view returns(bool) { + return name.strlen() > 6; + } + + function available(string memory name) public view returns(bool) { + bytes32 label = keccak256(bytes(name)); + return valid(name) && base.available(uint256(label)); + } + // SWC-114-Transaction Order Dependence: L46-L49 + function makeCommitment(string memory name, bytes32 secret) pure public returns(bytes32) { + bytes32 label = keccak256(bytes(name)); + return keccak256(abi.encodePacked(label, secret)); + } + + function commit(bytes32 commitment) public { + require(commitments[commitment] + MAX_COMMITMENT_AGE < now); + commitments[commitment] = now; + } + // SWC-104-Unchecked Call Return Value: L56-L65 + function register(string calldata name, address owner, uint duration, bytes32 secret) external payable { + // Require a valid commitment + bytes32 commitment = makeCommitment(name, secret); + require(commitments[commitment] + MIN_COMMITMENT_AGE <= now); + + // If the commitment is too old, or the name is registered, stop + if(commitments[commitment] + MAX_COMMITMENT_AGE < now || !available(name)) { + msg.sender.transfer(msg.value); + return; + } + delete(commitments[commitment]); + + uint cost = rentPrice(name, duration); + require(duration >= MIN_REGISTRATION_DURATION); + require(msg.value >= cost); + + bytes32 label = keccak256(bytes(name)); + uint expires = base.register(uint256(label), owner, duration); + emit NameRegistered(name, owner, cost, expires); + + if(msg.value > cost) { + msg.sender.transfer(msg.value - cost); + } + } + + function renew(string calldata name, uint duration) external payable { + uint cost = rentPrice(name, duration); + require(msg.value >= cost); + + bytes32 label = keccak256(bytes(name)); + uint expires = base.renew(uint256(label), duration); + + if(msg.value > cost) { + msg.sender.transfer(msg.value - cost); + } + + emit NameRenewed(name, cost, expires); + } + + function setPriceOracle(PriceOracle _prices) public onlyOwner { + prices = _prices; + emit NewPriceOracle(address(prices)); + } + + function withdraw() public onlyOwner { + msg.sender.transfer(address(this).balance); + } +} diff --git a/contracts/mutants/ETHRegistrarController/1/ECS/diff_result_difft.json b/contracts/mutants/ETHRegistrarController/1/ECS/diff_result_difft.json new file mode 100644 index 00000000000..5b45cfa481d --- /dev/null +++ b/contracts/mutants/ETHRegistrarController/1/ECS/diff_result_difft.json @@ -0,0 +1,32 @@ +{ + "number_of_changes": 1, + "timing": 0.11727762222290039, + "diff_chunks": [ + [ + { + "lhs": { + "line_number": 32, + "changes": [ + { + "start": 33, + "end": 38, + "content": "bytes", + "highlight": "normal" + } + ] + }, + "rhs": { + "line_number": 32, + "changes": [ + { + "start": 33, + "end": 39, + "content": "bytes1", + "highlight": "normal" + } + ] + } + } + ] + ] +} \ No newline at end of file diff --git a/contracts/mutants/ETHRegistrarController/1/EED/ETHRegistrarController.sol b/contracts/mutants/ETHRegistrarController/1/EED/ETHRegistrarController.sol new file mode 100644 index 00000000000..ca02417b809 --- /dev/null +++ b/contracts/mutants/ETHRegistrarController/1/EED/ETHRegistrarController.sol @@ -0,0 +1,103 @@ +pragma solidity ^0.5.0; + +import "./PriceOracle.sol"; +import "./BaseRegistrar.sol"; +import "./StringUtils.sol"; +import "openzeppelin-solidity/contracts/ownership/Ownable.sol"; + +/** + * @dev A registrar controller for registering and renewing names at fixed cost. + */ +contract ETHRegistrarController is Ownable { + using StringUtils for *; + + uint constant public MIN_COMMITMENT_AGE = 1 hours; + uint constant public MAX_COMMITMENT_AGE = 48 hours; + uint constant public MIN_REGISTRATION_DURATION = 28 days; + + BaseRegistrar base; + PriceOracle prices; + + mapping(bytes32=>uint) public commitments; + + event NameRegistered(string name, address indexed owner, uint cost, uint expires); + event NameRenewed(string name, uint cost, uint expires); + event NewPriceOracle(address indexed oracle); + + constructor(BaseRegistrar _base, PriceOracle _prices) public { + base = _base; + prices = _prices; + } + + function rentPrice(string memory name, uint duration) view public returns(uint) { + bytes32 hash = keccak256(bytes(name)); + return prices.price(name, base.nameExpires(uint256(hash)), duration); + } + + function valid(string memory name) public view returns(bool) { + return name.strlen() > 6; + } + + function available(string memory name) public view returns(bool) { + bytes32 label = keccak256(bytes(name)); + return valid(name) && base.available(uint256(label)); + } + // SWC-114-Transaction Order Dependence: L46-L49 + function makeCommitment(string memory name, bytes32 secret) pure public returns(bytes32) { + bytes32 label = keccak256(bytes(name)); + return keccak256(abi.encodePacked(label, secret)); + } + + function commit(bytes32 commitment) public { + require(commitments[commitment] + MAX_COMMITMENT_AGE < now); + commitments[commitment] = now; + } + // SWC-104-Unchecked Call Return Value: L56-L65 + function register(string calldata name, address owner, uint duration, bytes32 secret) external payable { + // Require a valid commitment + bytes32 commitment = makeCommitment(name, secret); + require(commitments[commitment] + MIN_COMMITMENT_AGE <= now); + + // If the commitment is too old, or the name is registered, stop + if(commitments[commitment] + MAX_COMMITMENT_AGE < now || !available(name)) { + msg.sender.transfer(msg.value); + return; + } + delete(commitments[commitment]); + + uint cost = rentPrice(name, duration); + require(duration >= MIN_REGISTRATION_DURATION); + require(msg.value >= cost); + + bytes32 label = keccak256(bytes(name)); + uint expires = base.register(uint256(label), owner, duration); + /* emit NameRegistered(name, owner, cost, expires); */ + + if(msg.value > cost) { + msg.sender.transfer(msg.value - cost); + } + } + + function renew(string calldata name, uint duration) external payable { + uint cost = rentPrice(name, duration); + require(msg.value >= cost); + + bytes32 label = keccak256(bytes(name)); + uint expires = base.renew(uint256(label), duration); + + if(msg.value > cost) { + msg.sender.transfer(msg.value - cost); + } + + emit NameRenewed(name, cost, expires); + } + + function setPriceOracle(PriceOracle _prices) public onlyOwner { + prices = _prices; + emit NewPriceOracle(address(prices)); + } + + function withdraw() public onlyOwner { + msg.sender.transfer(address(this).balance); + } +} diff --git a/contracts/mutants/ETHRegistrarController/1/EED/diff_result_difft.json b/contracts/mutants/ETHRegistrarController/1/EED/diff_result_difft.json new file mode 100644 index 00000000000..e2959ac83e9 --- /dev/null +++ b/contracts/mutants/ETHRegistrarController/1/EED/diff_result_difft.json @@ -0,0 +1,92 @@ +{ + "number_of_changes": 11, + "timing": 0.14185023307800293, + "diff_chunks": [ + [ + { + "lhs": { + "line_number": 73, + "changes": [ + { + "start": 8, + "end": 12, + "content": "emit", + "highlight": "keyword" + }, + { + "start": 13, + "end": 27, + "content": "NameRegistered", + "highlight": "type" + }, + { + "start": 27, + "end": 28, + "content": "(", + "highlight": "delimiter" + }, + { + "start": 28, + "end": 32, + "content": "name", + "highlight": "normal" + }, + { + "start": 32, + "end": 33, + "content": ",", + "highlight": "normal" + }, + { + "start": 34, + "end": 39, + "content": "owner", + "highlight": "normal" + }, + { + "start": 39, + "end": 40, + "content": ",", + "highlight": "normal" + }, + { + "start": 41, + "end": 45, + "content": "cost", + "highlight": "normal" + }, + { + "start": 45, + "end": 46, + "content": ",", + "highlight": "normal" + }, + { + "start": 47, + "end": 54, + "content": "expires", + "highlight": "normal" + }, + { + "start": 54, + "end": 55, + "content": ")", + "highlight": "delimiter" + } + ] + }, + "rhs": { + "line_number": 73, + "changes": [ + { + "start": 8, + "end": 62, + "content": "/* emit NameRegistered(name, owner, cost, expires); */", + "highlight": "comment" + } + ] + } + } + ] + ] +} \ No newline at end of file diff --git a/contracts/mutants/ETHRegistrarController/1/EHC/ETHRegistrarController.sol b/contracts/mutants/ETHRegistrarController/1/EHC/ETHRegistrarController.sol new file mode 100644 index 00000000000..2122883a8da --- /dev/null +++ b/contracts/mutants/ETHRegistrarController/1/EHC/ETHRegistrarController.sol @@ -0,0 +1,103 @@ +pragma solidity ^0.5.0; + +import "./PriceOracle.sol"; +import "./BaseRegistrar.sol"; +import "./StringUtils.sol"; +import "openzeppelin-solidity/contracts/ownership/Ownable.sol"; + +/** + * @dev A registrar controller for registering and renewing names at fixed cost. + */ +contract ETHRegistrarController is Ownable { + using StringUtils for *; + + uint constant public MIN_COMMITMENT_AGE = 1 hours; + uint constant public MAX_COMMITMENT_AGE = 48 hours; + uint constant public MIN_REGISTRATION_DURATION = 28 days; + + BaseRegistrar base; + PriceOracle prices; + + mapping(bytes32=>uint) public commitments; + + event NameRegistered(string name, address indexed owner, uint cost, uint expires); + event NameRenewed(string name, uint cost, uint expires); + event NewPriceOracle(address indexed oracle); + + constructor(BaseRegistrar _base, PriceOracle _prices) public { + base = _base; + prices = _prices; + } + + function rentPrice(string memory name, uint duration) view public returns(uint) { + bytes32 hash = keccak256(bytes(name)); + return prices.price(name, base.nameExpires(uint256(hash)), duration); + } + + function valid(string memory name) public view returns(bool) { + return name.strlen() > 6; + } + + function available(string memory name) public view returns(bool) { + bytes32 label = keccak256(bytes(name)); + return valid(name) && base.available(uint256(label)); + } + // SWC-114-Transaction Order Dependence: L46-L49 + function makeCommitment(string memory name, bytes32 secret) pure public returns(bytes32) { + bytes32 label = keccak256(bytes(name)); + return keccak256(abi.encodePacked(label, secret)); + } + + function commit(bytes32 commitment) public { + /* require(commitments[commitment] + MAX_COMMITMENT_AGE < now); */ + commitments[commitment] = now; + } + // SWC-104-Unchecked Call Return Value: L56-L65 + function register(string calldata name, address owner, uint duration, bytes32 secret) external payable { + // Require a valid commitment + bytes32 commitment = makeCommitment(name, secret); + require(commitments[commitment] + MIN_COMMITMENT_AGE <= now); + + // If the commitment is too old, or the name is registered, stop + if(commitments[commitment] + MAX_COMMITMENT_AGE < now || !available(name)) { + msg.sender.transfer(msg.value); + return; + } + delete(commitments[commitment]); + + uint cost = rentPrice(name, duration); + require(duration >= MIN_REGISTRATION_DURATION); + require(msg.value >= cost); + + bytes32 label = keccak256(bytes(name)); + uint expires = base.register(uint256(label), owner, duration); + emit NameRegistered(name, owner, cost, expires); + + if(msg.value > cost) { + msg.sender.transfer(msg.value - cost); + } + } + + function renew(string calldata name, uint duration) external payable { + uint cost = rentPrice(name, duration); + require(msg.value >= cost); + + bytes32 label = keccak256(bytes(name)); + uint expires = base.renew(uint256(label), duration); + + if(msg.value > cost) { + msg.sender.transfer(msg.value - cost); + } + + emit NameRenewed(name, cost, expires); + } + + function setPriceOracle(PriceOracle _prices) public onlyOwner { + prices = _prices; + emit NewPriceOracle(address(prices)); + } + + function withdraw() public onlyOwner { + msg.sender.transfer(address(this).balance); + } +} diff --git a/contracts/mutants/ETHRegistrarController/1/EHC/diff_result_difft.json b/contracts/mutants/ETHRegistrarController/1/EHC/diff_result_difft.json new file mode 100644 index 00000000000..c8ce35bf88d --- /dev/null +++ b/contracts/mutants/ETHRegistrarController/1/EHC/diff_result_difft.json @@ -0,0 +1,92 @@ +{ + "number_of_changes": 11, + "timing": 0.23060822486877441, + "diff_chunks": [ + [ + { + "lhs": { + "line_number": 51, + "changes": [ + { + "start": 8, + "end": 15, + "content": "require", + "highlight": "normal" + }, + { + "start": 15, + "end": 16, + "content": "(", + "highlight": "delimiter" + }, + { + "start": 16, + "end": 27, + "content": "commitments", + "highlight": "normal" + }, + { + "start": 27, + "end": 28, + "content": "[", + "highlight": "delimiter" + }, + { + "start": 28, + "end": 38, + "content": "commitment", + "highlight": "normal" + }, + { + "start": 38, + "end": 39, + "content": "]", + "highlight": "delimiter" + }, + { + "start": 40, + "end": 41, + "content": "+", + "highlight": "keyword" + }, + { + "start": 42, + "end": 60, + "content": "MAX_COMMITMENT_AGE", + "highlight": "normal" + }, + { + "start": 61, + "end": 62, + "content": "<", + "highlight": "keyword" + }, + { + "start": 63, + "end": 66, + "content": "now", + "highlight": "normal" + }, + { + "start": 66, + "end": 67, + "content": ")", + "highlight": "delimiter" + } + ] + }, + "rhs": { + "line_number": 51, + "changes": [ + { + "start": 8, + "end": 74, + "content": "/* require(commitments[commitment] + MAX_COMMITMENT_AGE < now); */", + "highlight": "comment" + } + ] + } + } + ] + ] +} \ No newline at end of file diff --git a/contracts/mutants/ETHRegistrarController/1/ETR/ETHRegistrarController.sol b/contracts/mutants/ETHRegistrarController/1/ETR/ETHRegistrarController.sol new file mode 100644 index 00000000000..488cb6cb583 --- /dev/null +++ b/contracts/mutants/ETHRegistrarController/1/ETR/ETHRegistrarController.sol @@ -0,0 +1,103 @@ +pragma solidity ^0.5.0; + +import "./PriceOracle.sol"; +import "./BaseRegistrar.sol"; +import "./StringUtils.sol"; +import "openzeppelin-solidity/contracts/ownership/Ownable.sol"; + +/** + * @dev A registrar controller for registering and renewing names at fixed cost. + */ +contract ETHRegistrarController is Ownable { + using StringUtils for *; + + uint constant public MIN_COMMITMENT_AGE = 1 hours; + uint constant public MAX_COMMITMENT_AGE = 48 hours; + uint constant public MIN_REGISTRATION_DURATION = 28 days; + + BaseRegistrar base; + PriceOracle prices; + + mapping(bytes32=>uint) public commitments; + + event NameRegistered(string name, address indexed owner, uint cost, uint expires); + event NameRenewed(string name, uint cost, uint expires); + event NewPriceOracle(address indexed oracle); + + constructor(BaseRegistrar _base, PriceOracle _prices) public { + base = _base; + prices = _prices; + } + + function rentPrice(string memory name, uint duration) view public returns(uint) { + bytes32 hash = keccak256(bytes(name)); + return prices.price(name, base.nameExpires(uint256(hash)), duration); + } + + function valid(string memory name) public view returns(bool) { + return name.strlen() > 6; + } + + function available(string memory name) public view returns(bool) { + bytes32 label = keccak256(bytes(name)); + return valid(name) && base.available(uint256(label)); + } + // SWC-114-Transaction Order Dependence: L46-L49 + function makeCommitment(string memory name, bytes32 secret) pure public returns(bytes32) { + bytes32 label = keccak256(bytes(name)); + return keccak256(abi.encodePacked(label, secret)); + } + + function commit(bytes32 commitment) public { + require(commitments[commitment] + MAX_COMMITMENT_AGE < now); + commitments[commitment] = now; + } + // SWC-104-Unchecked Call Return Value: L56-L65 + function register(string calldata name, address owner, uint duration, bytes32 secret) external payable { + // Require a valid commitment + bytes32 commitment = makeCommitment(name, secret); + require(commitments[commitment] + MIN_COMMITMENT_AGE <= now); + + // If the commitment is too old, or the name is registered, stop + if(commitments[commitment] + MAX_COMMITMENT_AGE < now || !available(name)) { + msg.sender.send(msg.value); + return; + } + delete(commitments[commitment]); + + uint cost = rentPrice(name, duration); + require(duration >= MIN_REGISTRATION_DURATION); + require(msg.value >= cost); + + bytes32 label = keccak256(bytes(name)); + uint expires = base.register(uint256(label), owner, duration); + emit NameRegistered(name, owner, cost, expires); + + if(msg.value > cost) { + msg.sender.transfer(msg.value - cost); + } + } + + function renew(string calldata name, uint duration) external payable { + uint cost = rentPrice(name, duration); + require(msg.value >= cost); + + bytes32 label = keccak256(bytes(name)); + uint expires = base.renew(uint256(label), duration); + + if(msg.value > cost) { + msg.sender.transfer(msg.value - cost); + } + + emit NameRenewed(name, cost, expires); + } + + function setPriceOracle(PriceOracle _prices) public onlyOwner { + prices = _prices; + emit NewPriceOracle(address(prices)); + } + + function withdraw() public onlyOwner { + msg.sender.transfer(address(this).balance); + } +} diff --git a/contracts/mutants/ETHRegistrarController/1/ETR/diff_result_difft.json b/contracts/mutants/ETHRegistrarController/1/ETR/diff_result_difft.json new file mode 100644 index 00000000000..9150a689420 --- /dev/null +++ b/contracts/mutants/ETHRegistrarController/1/ETR/diff_result_difft.json @@ -0,0 +1,32 @@ +{ + "number_of_changes": 1, + "timing": 0.39708709716796875, + "diff_chunks": [ + [ + { + "lhs": { + "line_number": 62, + "changes": [ + { + "start": 23, + "end": 31, + "content": "transfer", + "highlight": "normal" + } + ] + }, + "rhs": { + "line_number": 62, + "changes": [ + { + "start": 23, + "end": 27, + "content": "send", + "highlight": "normal" + } + ] + } + } + ] + ] +} \ No newline at end of file diff --git a/contracts/mutants/ETHRegistrarController/1/FVR/ETHRegistrarController.sol b/contracts/mutants/ETHRegistrarController/1/FVR/ETHRegistrarController.sol new file mode 100644 index 00000000000..4fb7fb1515e --- /dev/null +++ b/contracts/mutants/ETHRegistrarController/1/FVR/ETHRegistrarController.sol @@ -0,0 +1,103 @@ +pragma solidity ^0.5.0; + +import "./PriceOracle.sol"; +import "./BaseRegistrar.sol"; +import "./StringUtils.sol"; +import "openzeppelin-solidity/contracts/ownership/Ownable.sol"; + +/** + * @dev A registrar controller for registering and renewing names at fixed cost. + */ +contract ETHRegistrarController is Ownable { + using StringUtils for *; + + uint constant public MIN_COMMITMENT_AGE = 1 hours; + uint constant public MAX_COMMITMENT_AGE = 48 hours; + uint constant public MIN_REGISTRATION_DURATION = 28 days; + + BaseRegistrar base; + PriceOracle prices; + + mapping(bytes32=>uint) public commitments; + + event NameRegistered(string name, address indexed owner, uint cost, uint expires); + event NameRenewed(string name, uint cost, uint expires); + event NewPriceOracle(address indexed oracle); + + constructor(BaseRegistrar _base, PriceOracle _prices) internal { + base = _base; + prices = _prices; + } + + function rentPrice(string memory name, uint duration) view public returns(uint) { + bytes32 hash = keccak256(bytes(name)); + return prices.price(name, base.nameExpires(uint256(hash)), duration); + } + + function valid(string memory name) public view returns(bool) { + return name.strlen() > 6; + } + + function available(string memory name) public view returns(bool) { + bytes32 label = keccak256(bytes(name)); + return valid(name) && base.available(uint256(label)); + } + // SWC-114-Transaction Order Dependence: L46-L49 + function makeCommitment(string memory name, bytes32 secret) pure public returns(bytes32) { + bytes32 label = keccak256(bytes(name)); + return keccak256(abi.encodePacked(label, secret)); + } + + function commit(bytes32 commitment) public { + require(commitments[commitment] + MAX_COMMITMENT_AGE < now); + commitments[commitment] = now; + } + // SWC-104-Unchecked Call Return Value: L56-L65 + function register(string calldata name, address owner, uint duration, bytes32 secret) external payable { + // Require a valid commitment + bytes32 commitment = makeCommitment(name, secret); + require(commitments[commitment] + MIN_COMMITMENT_AGE <= now); + + // If the commitment is too old, or the name is registered, stop + if(commitments[commitment] + MAX_COMMITMENT_AGE < now || !available(name)) { + msg.sender.transfer(msg.value); + return; + } + delete(commitments[commitment]); + + uint cost = rentPrice(name, duration); + require(duration >= MIN_REGISTRATION_DURATION); + require(msg.value >= cost); + + bytes32 label = keccak256(bytes(name)); + uint expires = base.register(uint256(label), owner, duration); + emit NameRegistered(name, owner, cost, expires); + + if(msg.value > cost) { + msg.sender.transfer(msg.value - cost); + } + } + + function renew(string calldata name, uint duration) external payable { + uint cost = rentPrice(name, duration); + require(msg.value >= cost); + + bytes32 label = keccak256(bytes(name)); + uint expires = base.renew(uint256(label), duration); + + if(msg.value > cost) { + msg.sender.transfer(msg.value - cost); + } + + emit NameRenewed(name, cost, expires); + } + + function setPriceOracle(PriceOracle _prices) public onlyOwner { + prices = _prices; + emit NewPriceOracle(address(prices)); + } + + function withdraw() public onlyOwner { + msg.sender.transfer(address(this).balance); + } +} diff --git a/contracts/mutants/ETHRegistrarController/1/FVR/diff_result_difft.json b/contracts/mutants/ETHRegistrarController/1/FVR/diff_result_difft.json new file mode 100644 index 00000000000..480b9de35a5 --- /dev/null +++ b/contracts/mutants/ETHRegistrarController/1/FVR/diff_result_difft.json @@ -0,0 +1,32 @@ +{ + "number_of_changes": 1, + "timing": 0.2266082763671875, + "diff_chunks": [ + [ + { + "lhs": { + "line_number": 26, + "changes": [ + { + "start": 58, + "end": 64, + "content": "public", + "highlight": "keyword" + } + ] + }, + "rhs": { + "line_number": 26, + "changes": [ + { + "start": 58, + "end": 66, + "content": "internal", + "highlight": "keyword" + } + ] + } + } + ] + ] +} \ No newline at end of file diff --git a/contracts/mutants/ETHRegistrarController/1/GVR/ETHRegistrarController.sol b/contracts/mutants/ETHRegistrarController/1/GVR/ETHRegistrarController.sol new file mode 100644 index 00000000000..b0b9d4b852c --- /dev/null +++ b/contracts/mutants/ETHRegistrarController/1/GVR/ETHRegistrarController.sol @@ -0,0 +1,103 @@ +pragma solidity ^0.5.0; + +import "./PriceOracle.sol"; +import "./BaseRegistrar.sol"; +import "./StringUtils.sol"; +import "openzeppelin-solidity/contracts/ownership/Ownable.sol"; + +/** + * @dev A registrar controller for registering and renewing names at fixed cost. + */ +contract ETHRegistrarController is Ownable { + using StringUtils for *; + + uint constant public MIN_COMMITMENT_AGE = 1 hours; + uint constant public MAX_COMMITMENT_AGE = 48 hours; + uint constant public MIN_REGISTRATION_DURATION = 28 days; + + BaseRegistrar base; + PriceOracle prices; + + mapping(bytes32=>uint) public commitments; + + event NameRegistered(string name, address indexed owner, uint cost, uint expires); + event NameRenewed(string name, uint cost, uint expires); + event NewPriceOracle(address indexed oracle); + + constructor(BaseRegistrar _base, PriceOracle _prices) public { + base = _base; + prices = _prices; + } + + function rentPrice(string memory name, uint duration) view public returns(uint) { + bytes32 hash = keccak256(bytes(name)); + return prices.price(name, base.nameExpires(uint256(hash)), duration); + } + + function valid(string memory name) public view returns(bool) { + return name.strlen() > 6; + } + + function available(string memory name) public view returns(bool) { + bytes32 label = keccak256(bytes(name)); + return valid(name) && base.available(uint256(label)); + } + // SWC-114-Transaction Order Dependence: L46-L49 + function makeCommitment(string memory name, bytes32 secret) pure public returns(bytes32) { + bytes32 label = keccak256(bytes(name)); + return keccak256(abi.encodePacked(label, secret)); + } + + function commit(bytes32 commitment) public { + require(commitments[commitment] + MAX_COMMITMENT_AGE < block.difficulty); + commitments[commitment] = now; + } + // SWC-104-Unchecked Call Return Value: L56-L65 + function register(string calldata name, address owner, uint duration, bytes32 secret) external payable { + // Require a valid commitment + bytes32 commitment = makeCommitment(name, secret); + require(commitments[commitment] + MIN_COMMITMENT_AGE <= now); + + // If the commitment is too old, or the name is registered, stop + if(commitments[commitment] + MAX_COMMITMENT_AGE < now || !available(name)) { + msg.sender.transfer(msg.value); + return; + } + delete(commitments[commitment]); + + uint cost = rentPrice(name, duration); + require(duration >= MIN_REGISTRATION_DURATION); + require(msg.value >= cost); + + bytes32 label = keccak256(bytes(name)); + uint expires = base.register(uint256(label), owner, duration); + emit NameRegistered(name, owner, cost, expires); + + if(msg.value > cost) { + msg.sender.transfer(msg.value - cost); + } + } + + function renew(string calldata name, uint duration) external payable { + uint cost = rentPrice(name, duration); + require(msg.value >= cost); + + bytes32 label = keccak256(bytes(name)); + uint expires = base.renew(uint256(label), duration); + + if(msg.value > cost) { + msg.sender.transfer(msg.value - cost); + } + + emit NameRenewed(name, cost, expires); + } + + function setPriceOracle(PriceOracle _prices) public onlyOwner { + prices = _prices; + emit NewPriceOracle(address(prices)); + } + + function withdraw() public onlyOwner { + msg.sender.transfer(address(this).balance); + } +} diff --git a/contracts/mutants/ETHRegistrarController/1/GVR/diff_result_difft.json b/contracts/mutants/ETHRegistrarController/1/GVR/diff_result_difft.json new file mode 100644 index 00000000000..b752f15a9e2 --- /dev/null +++ b/contracts/mutants/ETHRegistrarController/1/GVR/diff_result_difft.json @@ -0,0 +1,44 @@ +{ + "number_of_changes": 3, + "timing": 0.10722970962524414, + "diff_chunks": [ + [ + { + "lhs": { + "line_number": 51, + "changes": [ + { + "start": 63, + "end": 66, + "content": "now", + "highlight": "normal" + } + ] + }, + "rhs": { + "line_number": 51, + "changes": [ + { + "start": 63, + "end": 68, + "content": "block", + "highlight": "normal" + }, + { + "start": 68, + "end": 69, + "content": ".", + "highlight": "normal" + }, + { + "start": 69, + "end": 79, + "content": "difficulty", + "highlight": "normal" + } + ] + } + } + ] + ] +} \ No newline at end of file diff --git a/contracts/mutants/ETHRegistrarController/1/ILR/ETHRegistrarController.sol b/contracts/mutants/ETHRegistrarController/1/ILR/ETHRegistrarController.sol new file mode 100644 index 00000000000..1fa3493abc5 --- /dev/null +++ b/contracts/mutants/ETHRegistrarController/1/ILR/ETHRegistrarController.sol @@ -0,0 +1,103 @@ +pragma solidity ^0.5.0; + +import "./PriceOracle.sol"; +import "./BaseRegistrar.sol"; +import "./StringUtils.sol"; +import "openzeppelin-solidity/contracts/ownership/Ownable.sol"; + +/** + * @dev A registrar controller for registering and renewing names at fixed cost. + */ +contract ETHRegistrarController is Ownable { + using StringUtils for *; + + uint constant public MIN_COMMITMENT_AGE = 0 hours; + uint constant public MAX_COMMITMENT_AGE = 48 hours; + uint constant public MIN_REGISTRATION_DURATION = 28 days; + + BaseRegistrar base; + PriceOracle prices; + + mapping(bytes32=>uint) public commitments; + + event NameRegistered(string name, address indexed owner, uint cost, uint expires); + event NameRenewed(string name, uint cost, uint expires); + event NewPriceOracle(address indexed oracle); + + constructor(BaseRegistrar _base, PriceOracle _prices) public { + base = _base; + prices = _prices; + } + + function rentPrice(string memory name, uint duration) view public returns(uint) { + bytes32 hash = keccak256(bytes(name)); + return prices.price(name, base.nameExpires(uint256(hash)), duration); + } + + function valid(string memory name) public view returns(bool) { + return name.strlen() > 6; + } + + function available(string memory name) public view returns(bool) { + bytes32 label = keccak256(bytes(name)); + return valid(name) && base.available(uint256(label)); + } + // SWC-114-Transaction Order Dependence: L46-L49 + function makeCommitment(string memory name, bytes32 secret) pure public returns(bytes32) { + bytes32 label = keccak256(bytes(name)); + return keccak256(abi.encodePacked(label, secret)); + } + + function commit(bytes32 commitment) public { + require(commitments[commitment] + MAX_COMMITMENT_AGE < now); + commitments[commitment] = now; + } + // SWC-104-Unchecked Call Return Value: L56-L65 + function register(string calldata name, address owner, uint duration, bytes32 secret) external payable { + // Require a valid commitment + bytes32 commitment = makeCommitment(name, secret); + require(commitments[commitment] + MIN_COMMITMENT_AGE <= now); + + // If the commitment is too old, or the name is registered, stop + if(commitments[commitment] + MAX_COMMITMENT_AGE < now || !available(name)) { + msg.sender.transfer(msg.value); + return; + } + delete(commitments[commitment]); + + uint cost = rentPrice(name, duration); + require(duration >= MIN_REGISTRATION_DURATION); + require(msg.value >= cost); + + bytes32 label = keccak256(bytes(name)); + uint expires = base.register(uint256(label), owner, duration); + emit NameRegistered(name, owner, cost, expires); + + if(msg.value > cost) { + msg.sender.transfer(msg.value - cost); + } + } + + function renew(string calldata name, uint duration) external payable { + uint cost = rentPrice(name, duration); + require(msg.value >= cost); + + bytes32 label = keccak256(bytes(name)); + uint expires = base.renew(uint256(label), duration); + + if(msg.value > cost) { + msg.sender.transfer(msg.value - cost); + } + + emit NameRenewed(name, cost, expires); + } + + function setPriceOracle(PriceOracle _prices) public onlyOwner { + prices = _prices; + emit NewPriceOracle(address(prices)); + } + + function withdraw() public onlyOwner { + msg.sender.transfer(address(this).balance); + } +} diff --git a/contracts/mutants/ETHRegistrarController/1/ILR/diff_result_difft.json b/contracts/mutants/ETHRegistrarController/1/ILR/diff_result_difft.json new file mode 100644 index 00000000000..c227083464f --- /dev/null +++ b/contracts/mutants/ETHRegistrarController/1/ILR/diff_result_difft.json @@ -0,0 +1 @@ +0 \ No newline at end of file diff --git a/contracts/mutants/ETHRegistrarController/1/MCR/ETHRegistrarController.sol b/contracts/mutants/ETHRegistrarController/1/MCR/ETHRegistrarController.sol new file mode 100644 index 00000000000..9510e5e0594 --- /dev/null +++ b/contracts/mutants/ETHRegistrarController/1/MCR/ETHRegistrarController.sol @@ -0,0 +1,103 @@ +pragma solidity ^0.5.0; + +import "./PriceOracle.sol"; +import "./BaseRegistrar.sol"; +import "./StringUtils.sol"; +import "openzeppelin-solidity/contracts/ownership/Ownable.sol"; + +/** + * @dev A registrar controller for registering and renewing names at fixed cost. + */ +contract ETHRegistrarController is Ownable { + using StringUtils for *; + + uint constant public MIN_COMMITMENT_AGE = 1 hours; + uint constant public MAX_COMMITMENT_AGE = 48 hours; + uint constant public MIN_REGISTRATION_DURATION = 28 days; + + BaseRegistrar base; + PriceOracle prices; + + mapping(bytes32=>uint) public commitments; + + event NameRegistered(string name, address indexed owner, uint cost, uint expires); + event NameRenewed(string name, uint cost, uint expires); + event NewPriceOracle(address indexed oracle); + + constructor(BaseRegistrar _base, PriceOracle _prices) public { + base = _base; + prices = _prices; + } + + function rentPrice(string memory name, uint duration) view public returns(uint) { + bytes32 hash = sha256(bytes(name)); + return prices.price(name, base.nameExpires(uint256(hash)), duration); + } + + function valid(string memory name) public view returns(bool) { + return name.strlen() > 6; + } + + function available(string memory name) public view returns(bool) { + bytes32 label = keccak256(bytes(name)); + return valid(name) && base.available(uint256(label)); + } + // SWC-114-Transaction Order Dependence: L46-L49 + function makeCommitment(string memory name, bytes32 secret) pure public returns(bytes32) { + bytes32 label = keccak256(bytes(name)); + return keccak256(abi.encodePacked(label, secret)); + } + + function commit(bytes32 commitment) public { + require(commitments[commitment] + MAX_COMMITMENT_AGE < now); + commitments[commitment] = now; + } + // SWC-104-Unchecked Call Return Value: L56-L65 + function register(string calldata name, address owner, uint duration, bytes32 secret) external payable { + // Require a valid commitment + bytes32 commitment = makeCommitment(name, secret); + require(commitments[commitment] + MIN_COMMITMENT_AGE <= now); + + // If the commitment is too old, or the name is registered, stop + if(commitments[commitment] + MAX_COMMITMENT_AGE < now || !available(name)) { + msg.sender.transfer(msg.value); + return; + } + delete(commitments[commitment]); + + uint cost = rentPrice(name, duration); + require(duration >= MIN_REGISTRATION_DURATION); + require(msg.value >= cost); + + bytes32 label = keccak256(bytes(name)); + uint expires = base.register(uint256(label), owner, duration); + emit NameRegistered(name, owner, cost, expires); + + if(msg.value > cost) { + msg.sender.transfer(msg.value - cost); + } + } + + function renew(string calldata name, uint duration) external payable { + uint cost = rentPrice(name, duration); + require(msg.value >= cost); + + bytes32 label = keccak256(bytes(name)); + uint expires = base.renew(uint256(label), duration); + + if(msg.value > cost) { + msg.sender.transfer(msg.value - cost); + } + + emit NameRenewed(name, cost, expires); + } + + function setPriceOracle(PriceOracle _prices) public onlyOwner { + prices = _prices; + emit NewPriceOracle(address(prices)); + } + + function withdraw() public onlyOwner { + msg.sender.transfer(address(this).balance); + } +} diff --git a/contracts/mutants/ETHRegistrarController/1/MCR/diff_result_difft.json b/contracts/mutants/ETHRegistrarController/1/MCR/diff_result_difft.json new file mode 100644 index 00000000000..13cbecd715a --- /dev/null +++ b/contracts/mutants/ETHRegistrarController/1/MCR/diff_result_difft.json @@ -0,0 +1,32 @@ +{ + "number_of_changes": 1, + "timing": 0.26715636253356934, + "diff_chunks": [ + [ + { + "lhs": { + "line_number": 32, + "changes": [ + { + "start": 23, + "end": 32, + "content": "keccak256", + "highlight": "normal" + } + ] + }, + "rhs": { + "line_number": 32, + "changes": [ + { + "start": 23, + "end": 29, + "content": "sha256", + "highlight": "normal" + } + ] + } + } + ] + ] +} \ No newline at end of file diff --git a/contracts/mutants/ETHRegistrarController/1/MOI/ETHRegistrarController.sol b/contracts/mutants/ETHRegistrarController/1/MOI/ETHRegistrarController.sol new file mode 100644 index 00000000000..bf5db0134ec --- /dev/null +++ b/contracts/mutants/ETHRegistrarController/1/MOI/ETHRegistrarController.sol @@ -0,0 +1,103 @@ +pragma solidity ^0.5.0; + +import "./PriceOracle.sol"; +import "./BaseRegistrar.sol"; +import "./StringUtils.sol"; +import "openzeppelin-solidity/contracts/ownership/Ownable.sol"; + +/** + * @dev A registrar controller for registering and renewing names at fixed cost. + */ +contract ETHRegistrarController is Ownable { + using StringUtils for *; + + uint constant public MIN_COMMITMENT_AGE = 1 hours; + uint constant public MAX_COMMITMENT_AGE = 48 hours; + uint constant public MIN_REGISTRATION_DURATION = 28 days; + + BaseRegistrar base; + PriceOracle prices; + + mapping(bytes32=>uint) public commitments; + + event NameRegistered(string name, address indexed owner, uint cost, uint expires); + event NameRenewed(string name, uint cost, uint expires); + event NewPriceOracle(address indexed oracle); + + constructor(BaseRegistrar _base, PriceOracle _prices) public { + base = _base; + prices = _prices; + } + + function rentPrice(string memory name, uint duration) view public returns(uint) { + bytes32 hash = keccak256(bytes(name)); + return prices.price(name, base.nameExpires(uint256(hash)), duration); + } + + function valid(string memory name) public view returns(bool) { + return name.strlen() > 6; + } + + function available(string memory name) public view returns(bool) { + bytes32 label = keccak256(bytes(name)); + return valid(name) && base.available(uint256(label)); + } + // SWC-114-Transaction Order Dependence: L46-L49 + function makeCommitment(string memory name, bytes32 secret) pure public returns(bytes32) { + bytes32 label = keccak256(bytes(name)); + return keccak256(abi.encodePacked(label, secret)); + } + + function commit(bytes32 commitment) public onlyOwner { + require(commitments[commitment] + MAX_COMMITMENT_AGE < now); + commitments[commitment] = now; + } + // SWC-104-Unchecked Call Return Value: L56-L65 + function register(string calldata name, address owner, uint duration, bytes32 secret) external payable { + // Require a valid commitment + bytes32 commitment = makeCommitment(name, secret); + require(commitments[commitment] + MIN_COMMITMENT_AGE <= now); + + // If the commitment is too old, or the name is registered, stop + if(commitments[commitment] + MAX_COMMITMENT_AGE < now || !available(name)) { + msg.sender.transfer(msg.value); + return; + } + delete(commitments[commitment]); + + uint cost = rentPrice(name, duration); + require(duration >= MIN_REGISTRATION_DURATION); + require(msg.value >= cost); + + bytes32 label = keccak256(bytes(name)); + uint expires = base.register(uint256(label), owner, duration); + emit NameRegistered(name, owner, cost, expires); + + if(msg.value > cost) { + msg.sender.transfer(msg.value - cost); + } + } + + function renew(string calldata name, uint duration) external payable { + uint cost = rentPrice(name, duration); + require(msg.value >= cost); + + bytes32 label = keccak256(bytes(name)); + uint expires = base.renew(uint256(label), duration); + + if(msg.value > cost) { + msg.sender.transfer(msg.value - cost); + } + + emit NameRenewed(name, cost, expires); + } + + function setPriceOracle(PriceOracle _prices) public onlyOwner { + prices = _prices; + emit NewPriceOracle(address(prices)); + } + + function withdraw() public onlyOwner { + msg.sender.transfer(address(this).balance); + } +} diff --git a/contracts/mutants/ETHRegistrarController/1/MOI/diff_result_difft.json b/contracts/mutants/ETHRegistrarController/1/MOI/diff_result_difft.json new file mode 100644 index 00000000000..d558de59ea1 --- /dev/null +++ b/contracts/mutants/ETHRegistrarController/1/MOI/diff_result_difft.json @@ -0,0 +1,25 @@ +{ + "number_of_changes": 1, + "timing": 0.14302945137023926, + "diff_chunks": [ + [ + { + "lhs": { + "line_number": 50, + "changes": [] + }, + "rhs": { + "line_number": 50, + "changes": [ + { + "start": 47, + "end": 56, + "content": "onlyOwner", + "highlight": "normal" + } + ] + } + } + ] + ] +} \ No newline at end of file diff --git a/contracts/mutants/ETHRegistrarController/1/PKD/ETHRegistrarController.sol b/contracts/mutants/ETHRegistrarController/1/PKD/ETHRegistrarController.sol new file mode 100644 index 00000000000..bb86aca7f60 --- /dev/null +++ b/contracts/mutants/ETHRegistrarController/1/PKD/ETHRegistrarController.sol @@ -0,0 +1,103 @@ +pragma solidity ^0.5.0; + +import "./PriceOracle.sol"; +import "./BaseRegistrar.sol"; +import "./StringUtils.sol"; +import "openzeppelin-solidity/contracts/ownership/Ownable.sol"; + +/** + * @dev A registrar controller for registering and renewing names at fixed cost. + */ +contract ETHRegistrarController is Ownable { + using StringUtils for *; + + uint constant public MIN_COMMITMENT_AGE = 1 hours; + uint constant public MAX_COMMITMENT_AGE = 48 hours; + uint constant public MIN_REGISTRATION_DURATION = 28 days; + + BaseRegistrar base; + PriceOracle prices; + + mapping(bytes32=>uint) public commitments; + + event NameRegistered(string name, address indexed owner, uint cost, uint expires); + event NameRenewed(string name, uint cost, uint expires); + event NewPriceOracle(address indexed oracle); + + constructor(BaseRegistrar _base, PriceOracle _prices) public { + base = _base; + prices = _prices; + } + + function rentPrice(string memory name, uint duration) view public returns(uint) { + bytes32 hash = keccak256(bytes(name)); + return prices.price(name, base.nameExpires(uint256(hash)), duration); + } + + function valid(string memory name) public view returns(bool) { + return name.strlen() > 6; + } + + function available(string memory name) public view returns(bool) { + bytes32 label = keccak256(bytes(name)); + return valid(name) && base.available(uint256(label)); + } + // SWC-114-Transaction Order Dependence: L46-L49 + function makeCommitment(string memory name, bytes32 secret) pure public returns(bytes32) { + bytes32 label = keccak256(bytes(name)); + return keccak256(abi.encodePacked(label, secret)); + } + + function commit(bytes32 commitment) public { + require(commitments[commitment] + MAX_COMMITMENT_AGE < now); + commitments[commitment] = now; + } + // SWC-104-Unchecked Call Return Value: L56-L65 + function register(string calldata name, address owner, uint duration, bytes32 secret) external { + // Require a valid commitment + bytes32 commitment = makeCommitment(name, secret); + require(commitments[commitment] + MIN_COMMITMENT_AGE <= now); + + // If the commitment is too old, or the name is registered, stop + if(commitments[commitment] + MAX_COMMITMENT_AGE < now || !available(name)) { + msg.sender.transfer(msg.value); + return; + } + delete(commitments[commitment]); + + uint cost = rentPrice(name, duration); + require(duration >= MIN_REGISTRATION_DURATION); + require(msg.value >= cost); + + bytes32 label = keccak256(bytes(name)); + uint expires = base.register(uint256(label), owner, duration); + emit NameRegistered(name, owner, cost, expires); + + if(msg.value > cost) { + msg.sender.transfer(msg.value - cost); + } + } + + function renew(string calldata name, uint duration) external payable { + uint cost = rentPrice(name, duration); + require(msg.value >= cost); + + bytes32 label = keccak256(bytes(name)); + uint expires = base.renew(uint256(label), duration); + + if(msg.value > cost) { + msg.sender.transfer(msg.value - cost); + } + + emit NameRenewed(name, cost, expires); + } + + function setPriceOracle(PriceOracle _prices) public onlyOwner { + prices = _prices; + emit NewPriceOracle(address(prices)); + } + + function withdraw() public onlyOwner { + msg.sender.transfer(address(this).balance); + } +} diff --git a/contracts/mutants/ETHRegistrarController/1/PKD/diff_result_difft.json b/contracts/mutants/ETHRegistrarController/1/PKD/diff_result_difft.json new file mode 100644 index 00000000000..631fddce19e --- /dev/null +++ b/contracts/mutants/ETHRegistrarController/1/PKD/diff_result_difft.json @@ -0,0 +1,25 @@ +{ + "number_of_changes": 1, + "timing": 0.2829434871673584, + "diff_chunks": [ + [ + { + "lhs": { + "line_number": 55, + "changes": [ + { + "start": 99, + "end": 106, + "content": "payable", + "highlight": "keyword" + } + ] + }, + "rhs": { + "line_number": 55, + "changes": [] + } + } + ] + ] +} \ No newline at end of file diff --git a/contracts/mutants/ETHRegistrarController/1/RSD/ETHRegistrarController.sol b/contracts/mutants/ETHRegistrarController/1/RSD/ETHRegistrarController.sol new file mode 100644 index 00000000000..f92025ac2ec --- /dev/null +++ b/contracts/mutants/ETHRegistrarController/1/RSD/ETHRegistrarController.sol @@ -0,0 +1,103 @@ +pragma solidity ^0.5.0; + +import "./PriceOracle.sol"; +import "./BaseRegistrar.sol"; +import "./StringUtils.sol"; +import "openzeppelin-solidity/contracts/ownership/Ownable.sol"; + +/** + * @dev A registrar controller for registering and renewing names at fixed cost. + */ +contract ETHRegistrarController is Ownable { + using StringUtils for *; + + uint constant public MIN_COMMITMENT_AGE = 1 hours; + uint constant public MAX_COMMITMENT_AGE = 48 hours; + uint constant public MIN_REGISTRATION_DURATION = 28 days; + + BaseRegistrar base; + PriceOracle prices; + + mapping(bytes32=>uint) public commitments; + + event NameRegistered(string name, address indexed owner, uint cost, uint expires); + event NameRenewed(string name, uint cost, uint expires); + event NewPriceOracle(address indexed oracle); + + constructor(BaseRegistrar _base, PriceOracle _prices) public { + base = _base; + prices = _prices; + } + + function rentPrice(string memory name, uint duration) view public returns(uint) { + bytes32 hash = keccak256(bytes(name)); + /* return prices.price(name, base.nameExpires(uint256(hash)), duration); */ + } + + function valid(string memory name) public view returns(bool) { + return name.strlen() > 6; + } + + function available(string memory name) public view returns(bool) { + bytes32 label = keccak256(bytes(name)); + return valid(name) && base.available(uint256(label)); + } + // SWC-114-Transaction Order Dependence: L46-L49 + function makeCommitment(string memory name, bytes32 secret) pure public returns(bytes32) { + bytes32 label = keccak256(bytes(name)); + return keccak256(abi.encodePacked(label, secret)); + } + + function commit(bytes32 commitment) public { + require(commitments[commitment] + MAX_COMMITMENT_AGE < now); + commitments[commitment] = now; + } + // SWC-104-Unchecked Call Return Value: L56-L65 + function register(string calldata name, address owner, uint duration, bytes32 secret) external payable { + // Require a valid commitment + bytes32 commitment = makeCommitment(name, secret); + require(commitments[commitment] + MIN_COMMITMENT_AGE <= now); + + // If the commitment is too old, or the name is registered, stop + if(commitments[commitment] + MAX_COMMITMENT_AGE < now || !available(name)) { + msg.sender.transfer(msg.value); + return; + } + delete(commitments[commitment]); + + uint cost = rentPrice(name, duration); + require(duration >= MIN_REGISTRATION_DURATION); + require(msg.value >= cost); + + bytes32 label = keccak256(bytes(name)); + uint expires = base.register(uint256(label), owner, duration); + emit NameRegistered(name, owner, cost, expires); + + if(msg.value > cost) { + msg.sender.transfer(msg.value - cost); + } + } + + function renew(string calldata name, uint duration) external payable { + uint cost = rentPrice(name, duration); + require(msg.value >= cost); + + bytes32 label = keccak256(bytes(name)); + uint expires = base.renew(uint256(label), duration); + + if(msg.value > cost) { + msg.sender.transfer(msg.value - cost); + } + + emit NameRenewed(name, cost, expires); + } + + function setPriceOracle(PriceOracle _prices) public onlyOwner { + prices = _prices; + emit NewPriceOracle(address(prices)); + } + + function withdraw() public onlyOwner { + msg.sender.transfer(address(this).balance); + } +} diff --git a/contracts/mutants/ETHRegistrarController/1/RSD/diff_result_difft.json b/contracts/mutants/ETHRegistrarController/1/RSD/diff_result_difft.json new file mode 100644 index 00000000000..7aa2a973858 --- /dev/null +++ b/contracts/mutants/ETHRegistrarController/1/RSD/diff_result_difft.json @@ -0,0 +1,140 @@ +{ + "number_of_changes": 19, + "timing": 0.16086673736572266, + "diff_chunks": [ + [ + { + "lhs": { + "line_number": 33, + "changes": [ + { + "start": 8, + "end": 14, + "content": "return", + "highlight": "keyword" + }, + { + "start": 15, + "end": 21, + "content": "prices", + "highlight": "normal" + }, + { + "start": 21, + "end": 22, + "content": ".", + "highlight": "normal" + }, + { + "start": 22, + "end": 27, + "content": "price", + "highlight": "normal" + }, + { + "start": 27, + "end": 28, + "content": "(", + "highlight": "delimiter" + }, + { + "start": 28, + "end": 32, + "content": "name", + "highlight": "normal" + }, + { + "start": 32, + "end": 33, + "content": ",", + "highlight": "normal" + }, + { + "start": 34, + "end": 38, + "content": "base", + "highlight": "normal" + }, + { + "start": 38, + "end": 39, + "content": ".", + "highlight": "normal" + }, + { + "start": 39, + "end": 50, + "content": "nameExpires", + "highlight": "normal" + }, + { + "start": 50, + "end": 51, + "content": "(", + "highlight": "delimiter" + }, + { + "start": 51, + "end": 58, + "content": "uint256", + "highlight": "normal" + }, + { + "start": 58, + "end": 59, + "content": "(", + "highlight": "delimiter" + }, + { + "start": 59, + "end": 63, + "content": "hash", + "highlight": "normal" + }, + { + "start": 63, + "end": 64, + "content": ")", + "highlight": "delimiter" + }, + { + "start": 64, + "end": 65, + "content": ")", + "highlight": "delimiter" + }, + { + "start": 65, + "end": 66, + "content": ",", + "highlight": "normal" + }, + { + "start": 67, + "end": 75, + "content": "duration", + "highlight": "normal" + }, + { + "start": 75, + "end": 76, + "content": ")", + "highlight": "delimiter" + } + ] + }, + "rhs": { + "line_number": 33, + "changes": [ + { + "start": 8, + "end": 83, + "content": "/* return prices.price(name, base.nameExpires(uint256(hash)), duration); */", + "highlight": "comment" + } + ] + } + } + ] + ] +} \ No newline at end of file diff --git a/contracts/mutants/ETHRegistrarController/1/TOR/ETHRegistrarController.sol b/contracts/mutants/ETHRegistrarController/1/TOR/ETHRegistrarController.sol new file mode 100644 index 00000000000..455e11e1e26 --- /dev/null +++ b/contracts/mutants/ETHRegistrarController/1/TOR/ETHRegistrarController.sol @@ -0,0 +1,103 @@ +pragma solidity ^0.5.0; + +import "./PriceOracle.sol"; +import "./BaseRegistrar.sol"; +import "./StringUtils.sol"; +import "openzeppelin-solidity/contracts/ownership/Ownable.sol"; + +/** + * @dev A registrar controller for registering and renewing names at fixed cost. + */ +contract ETHRegistrarController is Ownable { + using StringUtils for *; + + uint constant public MIN_COMMITMENT_AGE = 1 hours; + uint constant public MAX_COMMITMENT_AGE = 48 hours; + uint constant public MIN_REGISTRATION_DURATION = 28 days; + + BaseRegistrar base; + PriceOracle prices; + + mapping(bytes32=>uint) public commitments; + + event NameRegistered(string name, address indexed owner, uint cost, uint expires); + event NameRenewed(string name, uint cost, uint expires); + event NewPriceOracle(address indexed oracle); + + constructor(BaseRegistrar _base, PriceOracle _prices) public { + base = _base; + prices = _prices; + } + + function rentPrice(string memory name, uint duration) view public returns(uint) { + bytes32 hash = keccak256(bytes(name)); + return prices.price(name, base.nameExpires(uint256(hash)), duration); + } + + function valid(string memory name) public view returns(bool) { + return name.strlen() > 6; + } + + function available(string memory name) public view returns(bool) { + bytes32 label = keccak256(bytes(name)); + return valid(name) && base.available(uint256(label)); + } + // SWC-114-Transaction Order Dependence: L46-L49 + function makeCommitment(string memory name, bytes32 secret) pure public returns(bytes32) { + bytes32 label = keccak256(bytes(name)); + return keccak256(abi.encodePacked(label, secret)); + } + + function commit(bytes32 commitment) public { + require(commitments[commitment] + MAX_COMMITMENT_AGE < now); + commitments[commitment] = now; + } + // SWC-104-Unchecked Call Return Value: L56-L65 + function register(string calldata name, address owner, uint duration, bytes32 secret) external payable { + // Require a valid commitment + bytes32 commitment = makeCommitment(name, secret); + require(commitments[commitment] + MIN_COMMITMENT_AGE <= now); + + // If the commitment is too old, or the name is registered, stop + if(commitments[commitment] + MAX_COMMITMENT_AGE < now || !available(name)) { + tx.origin.transfer(msg.value); + return; + } + delete(commitments[commitment]); + + uint cost = rentPrice(name, duration); + require(duration >= MIN_REGISTRATION_DURATION); + require(msg.value >= cost); + + bytes32 label = keccak256(bytes(name)); + uint expires = base.register(uint256(label), owner, duration); + emit NameRegistered(name, owner, cost, expires); + + if(msg.value > cost) { + msg.sender.transfer(msg.value - cost); + } + } + + function renew(string calldata name, uint duration) external payable { + uint cost = rentPrice(name, duration); + require(msg.value >= cost); + + bytes32 label = keccak256(bytes(name)); + uint expires = base.renew(uint256(label), duration); + + if(msg.value > cost) { + msg.sender.transfer(msg.value - cost); + } + + emit NameRenewed(name, cost, expires); + } + + function setPriceOracle(PriceOracle _prices) public onlyOwner { + prices = _prices; + emit NewPriceOracle(address(prices)); + } + + function withdraw() public onlyOwner { + msg.sender.transfer(address(this).balance); + } +} diff --git a/contracts/mutants/ETHRegistrarController/1/TOR/diff_result_difft.json b/contracts/mutants/ETHRegistrarController/1/TOR/diff_result_difft.json new file mode 100644 index 00000000000..1835a9b0d54 --- /dev/null +++ b/contracts/mutants/ETHRegistrarController/1/TOR/diff_result_difft.json @@ -0,0 +1,44 @@ +{ + "number_of_changes": 2, + "timing": 0.270735502243042, + "diff_chunks": [ + [ + { + "lhs": { + "line_number": 62, + "changes": [ + { + "start": 12, + "end": 15, + "content": "msg", + "highlight": "normal" + }, + { + "start": 16, + "end": 22, + "content": "sender", + "highlight": "normal" + } + ] + }, + "rhs": { + "line_number": 62, + "changes": [ + { + "start": 12, + "end": 14, + "content": "tx", + "highlight": "normal" + }, + { + "start": 15, + "end": 21, + "content": "origin", + "highlight": "normal" + } + ] + } + } + ] + ] +} \ No newline at end of file diff --git a/contracts/mutants/ETHRegistrarController/1/UORD/ETHRegistrarController.sol b/contracts/mutants/ETHRegistrarController/1/UORD/ETHRegistrarController.sol new file mode 100644 index 00000000000..634b3ced0a0 --- /dev/null +++ b/contracts/mutants/ETHRegistrarController/1/UORD/ETHRegistrarController.sol @@ -0,0 +1,103 @@ +pragma solidity ^0.5.0; + +import "./PriceOracle.sol"; +import "./BaseRegistrar.sol"; +import "./StringUtils.sol"; +import "openzeppelin-solidity/contracts/ownership/Ownable.sol"; + +/** + * @dev A registrar controller for registering and renewing names at fixed cost. + */ +contract ETHRegistrarController is Ownable { + using StringUtils for *; + + uint constant public MIN_COMMITMENT_AGE = 1 hours; + uint constant public MAX_COMMITMENT_AGE = 48 hours; + uint constant public MIN_REGISTRATION_DURATION = 28 days; + + BaseRegistrar base; + PriceOracle prices; + + mapping(bytes32=>uint) public commitments; + + event NameRegistered(string name, address indexed owner, uint cost, uint expires); + event NameRenewed(string name, uint cost, uint expires); + event NewPriceOracle(address indexed oracle); + + constructor(BaseRegistrar _base, PriceOracle _prices) public { + base = _base; + prices = _prices; + } + + function rentPrice(string memory name, uint duration) view public returns(uint) { + bytes32 hash = keccak256(bytes(name)); + return prices.price(name, base.nameExpires(uint256(hash)), duration); + } + + function valid(string memory name) public view returns(bool) { + return name.strlen() > 6; + } + + function available(string memory name) public view returns(bool) { + bytes32 label = keccak256(bytes(name)); + return valid(name) && base.available(uint256(label)); + } + // SWC-114-Transaction Order Dependence: L46-L49 + function makeCommitment(string memory name, bytes32 secret) pure public returns(bytes32) { + bytes32 label = keccak256(bytes(name)); + return keccak256(abi.encodePacked(label, secret)); + } + + function commit(bytes32 commitment) public { + require(commitments[commitment] + MAX_COMMITMENT_AGE < now); + commitments[commitment] = now; + } + // SWC-104-Unchecked Call Return Value: L56-L65 + function register(string calldata name, address owner, uint duration, bytes32 secret) external payable { + // Require a valid commitment + bytes32 commitment = makeCommitment(name, secret); + require(commitments[commitment] + MIN_COMMITMENT_AGE <= now); + + // If the commitment is too old, or the name is registered, stop + if(commitments[commitment] + MAX_COMMITMENT_AGE < now || available(name)) { + msg.sender.transfer(msg.value); + return; + } + delete(commitments[commitment]); + + uint cost = rentPrice(name, duration); + require(duration >= MIN_REGISTRATION_DURATION); + require(msg.value >= cost); + + bytes32 label = keccak256(bytes(name)); + uint expires = base.register(uint256(label), owner, duration); + emit NameRegistered(name, owner, cost, expires); + + if(msg.value > cost) { + msg.sender.transfer(msg.value - cost); + } + } + + function renew(string calldata name, uint duration) external payable { + uint cost = rentPrice(name, duration); + require(msg.value >= cost); + + bytes32 label = keccak256(bytes(name)); + uint expires = base.renew(uint256(label), duration); + + if(msg.value > cost) { + msg.sender.transfer(msg.value - cost); + } + + emit NameRenewed(name, cost, expires); + } + + function setPriceOracle(PriceOracle _prices) public onlyOwner { + prices = _prices; + emit NewPriceOracle(address(prices)); + } + + function withdraw() public onlyOwner { + msg.sender.transfer(address(this).balance); + } +} diff --git a/contracts/mutants/ETHRegistrarController/1/UORD/diff_result_difft.json b/contracts/mutants/ETHRegistrarController/1/UORD/diff_result_difft.json new file mode 100644 index 00000000000..83a71a3431e --- /dev/null +++ b/contracts/mutants/ETHRegistrarController/1/UORD/diff_result_difft.json @@ -0,0 +1,25 @@ +{ + "number_of_changes": 1, + "timing": 0.15486741065979004, + "diff_chunks": [ + [ + { + "lhs": { + "line_number": 61, + "changes": [ + { + "start": 65, + "end": 66, + "content": "!", + "highlight": "keyword" + } + ] + }, + "rhs": { + "line_number": 61, + "changes": [] + } + } + ] + ] +} \ No newline at end of file diff --git a/contracts/mutants/ETHRegistrarController/1/VUR/ETHRegistrarController.sol b/contracts/mutants/ETHRegistrarController/1/VUR/ETHRegistrarController.sol new file mode 100644 index 00000000000..db4779ce228 --- /dev/null +++ b/contracts/mutants/ETHRegistrarController/1/VUR/ETHRegistrarController.sol @@ -0,0 +1,103 @@ +pragma solidity ^0.5.0; + +import "./PriceOracle.sol"; +import "./BaseRegistrar.sol"; +import "./StringUtils.sol"; +import "openzeppelin-solidity/contracts/ownership/Ownable.sol"; + +/** + * @dev A registrar controller for registering and renewing names at fixed cost. + */ +contract ETHRegistrarController is Ownable { + using StringUtils for *; + + uint constant public MIN_COMMITMENT_AGE = 1 seconds; + uint constant public MAX_COMMITMENT_AGE = 48 hours; + uint constant public MIN_REGISTRATION_DURATION = 28 days; + + BaseRegistrar base; + PriceOracle prices; + + mapping(bytes32=>uint) public commitments; + + event NameRegistered(string name, address indexed owner, uint cost, uint expires); + event NameRenewed(string name, uint cost, uint expires); + event NewPriceOracle(address indexed oracle); + + constructor(BaseRegistrar _base, PriceOracle _prices) public { + base = _base; + prices = _prices; + } + + function rentPrice(string memory name, uint duration) view public returns(uint) { + bytes32 hash = keccak256(bytes(name)); + return prices.price(name, base.nameExpires(uint256(hash)), duration); + } + + function valid(string memory name) public view returns(bool) { + return name.strlen() > 6; + } + + function available(string memory name) public view returns(bool) { + bytes32 label = keccak256(bytes(name)); + return valid(name) && base.available(uint256(label)); + } + // SWC-114-Transaction Order Dependence: L46-L49 + function makeCommitment(string memory name, bytes32 secret) pure public returns(bytes32) { + bytes32 label = keccak256(bytes(name)); + return keccak256(abi.encodePacked(label, secret)); + } + + function commit(bytes32 commitment) public { + require(commitments[commitment] + MAX_COMMITMENT_AGE < now); + commitments[commitment] = now; + } + // SWC-104-Unchecked Call Return Value: L56-L65 + function register(string calldata name, address owner, uint duration, bytes32 secret) external payable { + // Require a valid commitment + bytes32 commitment = makeCommitment(name, secret); + require(commitments[commitment] + MIN_COMMITMENT_AGE <= now); + + // If the commitment is too old, or the name is registered, stop + if(commitments[commitment] + MAX_COMMITMENT_AGE < now || !available(name)) { + msg.sender.transfer(msg.value); + return; + } + delete(commitments[commitment]); + + uint cost = rentPrice(name, duration); + require(duration >= MIN_REGISTRATION_DURATION); + require(msg.value >= cost); + + bytes32 label = keccak256(bytes(name)); + uint expires = base.register(uint256(label), owner, duration); + emit NameRegistered(name, owner, cost, expires); + + if(msg.value > cost) { + msg.sender.transfer(msg.value - cost); + } + } + + function renew(string calldata name, uint duration) external payable { + uint cost = rentPrice(name, duration); + require(msg.value >= cost); + + bytes32 label = keccak256(bytes(name)); + uint expires = base.renew(uint256(label), duration); + + if(msg.value > cost) { + msg.sender.transfer(msg.value - cost); + } + + emit NameRenewed(name, cost, expires); + } + + function setPriceOracle(PriceOracle _prices) public onlyOwner { + prices = _prices; + emit NewPriceOracle(address(prices)); + } + + function withdraw() public onlyOwner { + msg.sender.transfer(address(this).balance); + } +} diff --git a/contracts/mutants/ETHRegistrarController/1/VUR/diff_result_difft.json b/contracts/mutants/ETHRegistrarController/1/VUR/diff_result_difft.json new file mode 100644 index 00000000000..8f5af55d40a --- /dev/null +++ b/contracts/mutants/ETHRegistrarController/1/VUR/diff_result_difft.json @@ -0,0 +1,32 @@ +{ + "number_of_changes": 1, + "timing": 0.25139808654785156, + "diff_chunks": [ + [ + { + "lhs": { + "line_number": 13, + "changes": [ + { + "start": 48, + "end": 53, + "content": "hours", + "highlight": "normal" + } + ] + }, + "rhs": { + "line_number": 13, + "changes": [ + { + "start": 48, + "end": 55, + "content": "seconds", + "highlight": "normal" + } + ] + } + } + ] + ] +} \ No newline at end of file diff --git a/contracts/mutants/ETHRegistrarController/1/VVR/ETHRegistrarController.sol b/contracts/mutants/ETHRegistrarController/1/VVR/ETHRegistrarController.sol new file mode 100644 index 00000000000..cc3afbff7b7 --- /dev/null +++ b/contracts/mutants/ETHRegistrarController/1/VVR/ETHRegistrarController.sol @@ -0,0 +1,103 @@ +pragma solidity ^0.5.0; + +import "./PriceOracle.sol"; +import "./BaseRegistrar.sol"; +import "./StringUtils.sol"; +import "openzeppelin-solidity/contracts/ownership/Ownable.sol"; + +/** + * @dev A registrar controller for registering and renewing names at fixed cost. + */ +contract ETHRegistrarController is Ownable { + using StringUtils for *; + + uint constant internal MIN_COMMITMENT_AGE = 1 hours; + uint constant public MAX_COMMITMENT_AGE = 48 hours; + uint constant public MIN_REGISTRATION_DURATION = 28 days; + + BaseRegistrar base; + PriceOracle prices; + + mapping(bytes32=>uint) public commitments; + + event NameRegistered(string name, address indexed owner, uint cost, uint expires); + event NameRenewed(string name, uint cost, uint expires); + event NewPriceOracle(address indexed oracle); + + constructor(BaseRegistrar _base, PriceOracle _prices) public { + base = _base; + prices = _prices; + } + + function rentPrice(string memory name, uint duration) view public returns(uint) { + bytes32 hash = keccak256(bytes(name)); + return prices.price(name, base.nameExpires(uint256(hash)), duration); + } + + function valid(string memory name) public view returns(bool) { + return name.strlen() > 6; + } + + function available(string memory name) public view returns(bool) { + bytes32 label = keccak256(bytes(name)); + return valid(name) && base.available(uint256(label)); + } + // SWC-114-Transaction Order Dependence: L46-L49 + function makeCommitment(string memory name, bytes32 secret) pure public returns(bytes32) { + bytes32 label = keccak256(bytes(name)); + return keccak256(abi.encodePacked(label, secret)); + } + + function commit(bytes32 commitment) public { + require(commitments[commitment] + MAX_COMMITMENT_AGE < now); + commitments[commitment] = now; + } + // SWC-104-Unchecked Call Return Value: L56-L65 + function register(string calldata name, address owner, uint duration, bytes32 secret) external payable { + // Require a valid commitment + bytes32 commitment = makeCommitment(name, secret); + require(commitments[commitment] + MIN_COMMITMENT_AGE <= now); + + // If the commitment is too old, or the name is registered, stop + if(commitments[commitment] + MAX_COMMITMENT_AGE < now || !available(name)) { + msg.sender.transfer(msg.value); + return; + } + delete(commitments[commitment]); + + uint cost = rentPrice(name, duration); + require(duration >= MIN_REGISTRATION_DURATION); + require(msg.value >= cost); + + bytes32 label = keccak256(bytes(name)); + uint expires = base.register(uint256(label), owner, duration); + emit NameRegistered(name, owner, cost, expires); + + if(msg.value > cost) { + msg.sender.transfer(msg.value - cost); + } + } + + function renew(string calldata name, uint duration) external payable { + uint cost = rentPrice(name, duration); + require(msg.value >= cost); + + bytes32 label = keccak256(bytes(name)); + uint expires = base.renew(uint256(label), duration); + + if(msg.value > cost) { + msg.sender.transfer(msg.value - cost); + } + + emit NameRenewed(name, cost, expires); + } + + function setPriceOracle(PriceOracle _prices) public onlyOwner { + prices = _prices; + emit NewPriceOracle(address(prices)); + } + + function withdraw() public onlyOwner { + msg.sender.transfer(address(this).balance); + } +} diff --git a/contracts/mutants/ETHRegistrarController/1/VVR/diff_result_difft.json b/contracts/mutants/ETHRegistrarController/1/VVR/diff_result_difft.json new file mode 100644 index 00000000000..50e5ad2ce75 --- /dev/null +++ b/contracts/mutants/ETHRegistrarController/1/VVR/diff_result_difft.json @@ -0,0 +1,32 @@ +{ + "number_of_changes": 1, + "timing": 0.17362260818481445, + "diff_chunks": [ + [ + { + "lhs": { + "line_number": 13, + "changes": [ + { + "start": 18, + "end": 24, + "content": "public", + "highlight": "keyword" + } + ] + }, + "rhs": { + "line_number": 13, + "changes": [ + { + "start": 18, + "end": 26, + "content": "internal", + "highlight": "keyword" + } + ] + } + } + ] + ] +} \ No newline at end of file diff --git a/contracts/mutants/ETHRegistrarController/10/BOR/ETHRegistrarController.sol b/contracts/mutants/ETHRegistrarController/10/BOR/ETHRegistrarController.sol new file mode 100644 index 00000000000..59a8dbba6fd --- /dev/null +++ b/contracts/mutants/ETHRegistrarController/10/BOR/ETHRegistrarController.sol @@ -0,0 +1,103 @@ +pragma solidity ^0.5.0; + +import "./PriceOracle.sol"; +import "./BaseRegistrar.sol"; +import "./StringUtils.sol"; +import "openzeppelin-solidity/contracts/ownership/Ownable.sol"; + +/** + * @dev A registrar controller for registering and renewing names at fixed cost. + */ +contract ETHRegistrarController is Ownable { + using StringUtils for *; + + uint constant public MIN_COMMITMENT_AGE = 1 hours; + uint constant public MAX_COMMITMENT_AGE = 48 hours; + uint constant public MIN_REGISTRATION_DURATION = 28 days; + + BaseRegistrar base; + PriceOracle prices; + + mapping(bytes32=>uint) public commitments; + + event NameRegistered(string name, address indexed owner, uint cost, uint expires); + event NameRenewed(string name, uint cost, uint expires); + event NewPriceOracle(address indexed oracle); + + constructor(BaseRegistrar _base, PriceOracle _prices) public { + base = _base; + prices = _prices; + } + + function rentPrice(string memory name, uint duration) view public returns(uint) { + bytes32 hash = keccak256(bytes(name)); + return prices.price(name, base.nameExpires(uint256(hash)), duration); + } + + function valid(string memory name) public view returns(bool) { + return name.strlen() >= 6; + } + + function available(string memory name) public view returns(bool) { + bytes32 label = keccak256(bytes(name)); + return valid(name) || base.available(uint256(label)); + } + // SWC-114-Transaction Order Dependence: L46-L49 + function makeCommitment(string memory name, bytes32 secret) pure public returns(bytes32) { + bytes32 label = keccak256(bytes(name)); + return keccak256(abi.encodePacked(label, secret)); + } + + function commit(bytes32 commitment) public { + require(commitments[commitment] - MAX_COMMITMENT_AGE <= now); + commitments[commitment] = now; + } + // SWC-104-Unchecked Call Return Value: L56-L65 + function register(string calldata name, address owner, uint duration, bytes32 secret) external payable { + // Require a valid commitment + bytes32 commitment = makeCommitment(name, secret); + require(commitments[commitment] - MIN_COMMITMENT_AGE < now); + + // If the commitment is too old, or the name is registered, stop + if(commitments[commitment] - MAX_COMMITMENT_AGE <= now && !available(name)) { + msg.sender.transfer(msg.value); + return; + } + delete(commitments[commitment]); + + uint cost = rentPrice(name, duration); + require(duration > MIN_REGISTRATION_DURATION); + require(msg.value >= cost); + + bytes32 label = keccak256(bytes(name)); + uint expires = base.register(uint256(label), owner, duration); + emit NameRegistered(name, owner, cost, expires); + + if(msg.value > cost) { + msg.sender.transfer(msg.value - cost); + } + } + + function renew(string calldata name, uint duration) external payable { + uint cost = rentPrice(name, duration); + require(msg.value >= cost); + + bytes32 label = keccak256(bytes(name)); + uint expires = base.renew(uint256(label), duration); + + if(msg.value > cost) { + msg.sender.transfer(msg.value - cost); + } + + emit NameRenewed(name, cost, expires); + } + + function setPriceOracle(PriceOracle _prices) public onlyOwner { + prices = _prices; + emit NewPriceOracle(address(prices)); + } + + function withdraw() public onlyOwner { + msg.sender.transfer(address(this).balance); + } +} diff --git a/contracts/mutants/ETHRegistrarController/10/BOR/diff_result_difft.json b/contracts/mutants/ETHRegistrarController/10/BOR/diff_result_difft.json new file mode 100644 index 00000000000..d37aee07a5b --- /dev/null +++ b/contracts/mutants/ETHRegistrarController/10/BOR/diff_result_difft.json @@ -0,0 +1,208 @@ +{ + "number_of_changes": 10, + "timing": 0.15906834602355957, + "diff_chunks": [ + [ + { + "lhs": { + "line_number": 37, + "changes": [ + { + "start": 29, + "end": 30, + "content": ">", + "highlight": "keyword" + } + ] + }, + "rhs": { + "line_number": 37, + "changes": [ + { + "start": 29, + "end": 31, + "content": ">=", + "highlight": "keyword" + } + ] + } + } + ], + [ + { + "lhs": { + "line_number": 42, + "changes": [ + { + "start": 27, + "end": 29, + "content": "&&", + "highlight": "keyword" + } + ] + }, + "rhs": { + "line_number": 42, + "changes": [ + { + "start": 27, + "end": 29, + "content": "||", + "highlight": "keyword" + } + ] + } + } + ], + [ + { + "lhs": { + "line_number": 51, + "changes": [ + { + "start": 40, + "end": 41, + "content": "+", + "highlight": "keyword" + }, + { + "start": 61, + "end": 62, + "content": "<", + "highlight": "keyword" + } + ] + }, + "rhs": { + "line_number": 51, + "changes": [ + { + "start": 40, + "end": 41, + "content": "-", + "highlight": "keyword" + }, + { + "start": 61, + "end": 63, + "content": "<=", + "highlight": "keyword" + } + ] + } + } + ], + [ + { + "lhs": { + "line_number": 61, + "changes": [ + { + "start": 35, + "end": 36, + "content": "+", + "highlight": "keyword" + }, + { + "start": 56, + "end": 57, + "content": "<", + "highlight": "keyword" + }, + { + "start": 62, + "end": 64, + "content": "||", + "highlight": "keyword" + } + ] + }, + "rhs": { + "line_number": 61, + "changes": [ + { + "start": 35, + "end": 36, + "content": "-", + "highlight": "keyword" + }, + { + "start": 56, + "end": 58, + "content": "<=", + "highlight": "keyword" + }, + { + "start": 63, + "end": 65, + "content": "&&", + "highlight": "keyword" + } + ] + } + }, + { + "lhs": { + "line_number": 58, + "changes": [ + { + "start": 40, + "end": 41, + "content": "+", + "highlight": "keyword" + }, + { + "start": 61, + "end": 63, + "content": "<=", + "highlight": "keyword" + } + ] + }, + "rhs": { + "line_number": 58, + "changes": [ + { + "start": 40, + "end": 41, + "content": "-", + "highlight": "keyword" + }, + { + "start": 62, + "end": 63, + "content": "<", + "highlight": "keyword" + } + ] + } + } + ], + [ + { + "lhs": { + "line_number": 68, + "changes": [ + { + "start": 25, + "end": 27, + "content": ">=", + "highlight": "keyword" + } + ] + }, + "rhs": { + "line_number": 68, + "changes": [ + { + "start": 26, + "end": 27, + "content": ">", + "highlight": "keyword" + } + ] + } + } + ] + ] +} \ No newline at end of file diff --git a/contracts/mutants/ETHRegistrarController/10/FVR/ETHRegistrarController.sol b/contracts/mutants/ETHRegistrarController/10/FVR/ETHRegistrarController.sol new file mode 100644 index 00000000000..47c69e7347e --- /dev/null +++ b/contracts/mutants/ETHRegistrarController/10/FVR/ETHRegistrarController.sol @@ -0,0 +1,103 @@ +pragma solidity ^0.5.0; + +import "./PriceOracle.sol"; +import "./BaseRegistrar.sol"; +import "./StringUtils.sol"; +import "openzeppelin-solidity/contracts/ownership/Ownable.sol"; + +/** + * @dev A registrar controller for registering and renewing names at fixed cost. + */ +contract ETHRegistrarController is Ownable { + using StringUtils for *; + + uint constant public MIN_COMMITMENT_AGE = 1 hours; + uint constant public MAX_COMMITMENT_AGE = 48 hours; + uint constant public MIN_REGISTRATION_DURATION = 28 days; + + BaseRegistrar base; + PriceOracle prices; + + mapping(bytes32=>uint) public commitments; + + event NameRegistered(string name, address indexed owner, uint cost, uint expires); + event NameRenewed(string name, uint cost, uint expires); + event NewPriceOracle(address indexed oracle); + + constructor(BaseRegistrar _base, PriceOracle _prices) internal { + base = _base; + prices = _prices; + } + + function rentPrice(string memory name, uint duration) view external returns(uint) { + bytes32 hash = keccak256(bytes(name)); + return prices.price(name, base.nameExpires(uint256(hash)), duration); + } + + function valid(string memory name) external view returns(bool) { + return name.strlen() > 6; + } + + function available(string memory name) external view returns(bool) { + bytes32 label = keccak256(bytes(name)); + return valid(name) && base.available(uint256(label)); + } + // SWC-114-Transaction Order Dependence: L46-L49 + function makeCommitment(string memory name, bytes32 secret) pure external returns(bytes32) { + bytes32 label = keccak256(bytes(name)); + return keccak256(abi.encodePacked(label, secret)); + } + + function commit(bytes32 commitment) external { + require(commitments[commitment] + MAX_COMMITMENT_AGE < now); + commitments[commitment] = now; + } + // SWC-104-Unchecked Call Return Value: L56-L65 + function register(string calldata name, address owner, uint duration, bytes32 secret) public payable { + // Require a valid commitment + bytes32 commitment = makeCommitment(name, secret); + require(commitments[commitment] + MIN_COMMITMENT_AGE <= now); + + // If the commitment is too old, or the name is registered, stop + if(commitments[commitment] + MAX_COMMITMENT_AGE < now || !available(name)) { + msg.sender.transfer(msg.value); + return; + } + delete(commitments[commitment]); + + uint cost = rentPrice(name, duration); + require(duration >= MIN_REGISTRATION_DURATION); + require(msg.value >= cost); + + bytes32 label = keccak256(bytes(name)); + uint expires = base.register(uint256(label), owner, duration); + emit NameRegistered(name, owner, cost, expires); + + if(msg.value > cost) { + msg.sender.transfer(msg.value - cost); + } + } + + function renew(string calldata name, uint duration) public payable { + uint cost = rentPrice(name, duration); + require(msg.value >= cost); + + bytes32 label = keccak256(bytes(name)); + uint expires = base.renew(uint256(label), duration); + + if(msg.value > cost) { + msg.sender.transfer(msg.value - cost); + } + + emit NameRenewed(name, cost, expires); + } + + function setPriceOracle(PriceOracle _prices) external onlyOwner { + prices = _prices; + emit NewPriceOracle(address(prices)); + } + + function withdraw() external onlyOwner { + msg.sender.transfer(address(this).balance); + } +} diff --git a/contracts/mutants/ETHRegistrarController/10/FVR/diff_result_difft.json b/contracts/mutants/ETHRegistrarController/10/FVR/diff_result_difft.json new file mode 100644 index 00000000000..28fc07aafdd --- /dev/null +++ b/contracts/mutants/ETHRegistrarController/10/FVR/diff_result_difft.json @@ -0,0 +1,264 @@ +{ + "number_of_changes": 10, + "timing": 0.10496139526367188, + "diff_chunks": [ + [ + { + "lhs": { + "line_number": 26, + "changes": [ + { + "start": 58, + "end": 64, + "content": "public", + "highlight": "keyword" + } + ] + }, + "rhs": { + "line_number": 26, + "changes": [ + { + "start": 58, + "end": 66, + "content": "internal", + "highlight": "keyword" + } + ] + } + } + ], + [ + { + "lhs": { + "line_number": 31, + "changes": [ + { + "start": 63, + "end": 69, + "content": "public", + "highlight": "keyword" + } + ] + }, + "rhs": { + "line_number": 31, + "changes": [ + { + "start": 63, + "end": 71, + "content": "external", + "highlight": "keyword" + } + ] + } + } + ], + [ + { + "lhs": { + "line_number": 36, + "changes": [ + { + "start": 39, + "end": 45, + "content": "public", + "highlight": "keyword" + } + ] + }, + "rhs": { + "line_number": 36, + "changes": [ + { + "start": 39, + "end": 47, + "content": "external", + "highlight": "keyword" + } + ] + } + }, + { + "lhs": { + "line_number": 40, + "changes": [ + { + "start": 43, + "end": 49, + "content": "public", + "highlight": "keyword" + } + ] + }, + "rhs": { + "line_number": 40, + "changes": [ + { + "start": 43, + "end": 51, + "content": "external", + "highlight": "keyword" + } + ] + } + } + ], + [ + { + "lhs": { + "line_number": 45, + "changes": [ + { + "start": 69, + "end": 75, + "content": "public", + "highlight": "keyword" + } + ] + }, + "rhs": { + "line_number": 45, + "changes": [ + { + "start": 69, + "end": 77, + "content": "external", + "highlight": "keyword" + } + ] + } + } + ], + [ + { + "lhs": { + "line_number": 50, + "changes": [ + { + "start": 40, + "end": 46, + "content": "public", + "highlight": "keyword" + } + ] + }, + "rhs": { + "line_number": 50, + "changes": [ + { + "start": 40, + "end": 48, + "content": "external", + "highlight": "keyword" + } + ] + } + } + ], + [ + { + "lhs": { + "line_number": 55, + "changes": [ + { + "start": 90, + "end": 98, + "content": "external", + "highlight": "keyword" + } + ] + }, + "rhs": { + "line_number": 55, + "changes": [ + { + "start": 90, + "end": 96, + "content": "public", + "highlight": "keyword" + } + ] + } + } + ], + [ + { + "lhs": { + "line_number": 80, + "changes": [ + { + "start": 56, + "end": 64, + "content": "external", + "highlight": "keyword" + } + ] + }, + "rhs": { + "line_number": 80, + "changes": [ + { + "start": 56, + "end": 62, + "content": "public", + "highlight": "keyword" + } + ] + } + } + ], + [ + { + "lhs": { + "line_number": 94, + "changes": [ + { + "start": 49, + "end": 55, + "content": "public", + "highlight": "keyword" + } + ] + }, + "rhs": { + "line_number": 94, + "changes": [ + { + "start": 49, + "end": 57, + "content": "external", + "highlight": "keyword" + } + ] + } + } + ], + [ + { + "lhs": { + "line_number": 99, + "changes": [ + { + "start": 24, + "end": 30, + "content": "public", + "highlight": "keyword" + } + ] + }, + "rhs": { + "line_number": 99, + "changes": [ + { + "start": 24, + "end": 32, + "content": "external", + "highlight": "keyword" + } + ] + } + } + ] + ] +} \ No newline at end of file diff --git a/contracts/mutants/ETHRegistrarController/10/GVR/ETHRegistrarController.sol b/contracts/mutants/ETHRegistrarController/10/GVR/ETHRegistrarController.sol new file mode 100644 index 00000000000..d68d6fad84f --- /dev/null +++ b/contracts/mutants/ETHRegistrarController/10/GVR/ETHRegistrarController.sol @@ -0,0 +1,103 @@ +pragma solidity ^0.5.0; + +import "./PriceOracle.sol"; +import "./BaseRegistrar.sol"; +import "./StringUtils.sol"; +import "openzeppelin-solidity/contracts/ownership/Ownable.sol"; + +/** + * @dev A registrar controller for registering and renewing names at fixed cost. + */ +contract ETHRegistrarController is Ownable { + using StringUtils for *; + + uint constant public MIN_COMMITMENT_AGE = 1 hours; + uint constant public MAX_COMMITMENT_AGE = 48 hours; + uint constant public MIN_REGISTRATION_DURATION = 28 days; + + BaseRegistrar base; + PriceOracle prices; + + mapping(bytes32=>uint) public commitments; + + event NameRegistered(string name, address indexed owner, uint cost, uint expires); + event NameRenewed(string name, uint cost, uint expires); + event NewPriceOracle(address indexed oracle); + + constructor(BaseRegistrar _base, PriceOracle _prices) public { + base = _base; + prices = _prices; + } + + function rentPrice(string memory name, uint duration) view public returns(uint) { + bytes32 hash = keccak256(bytes(name)); + return prices.price(name, base.nameExpires(uint256(hash)), duration); + } + + function valid(string memory name) public view returns(bool) { + return name.strlen() > 6; + } + + function available(string memory name) public view returns(bool) { + bytes32 label = keccak256(bytes(name)); + return valid(name) && base.available(uint256(label)); + } + // SWC-114-Transaction Order Dependence: L46-L49 + function makeCommitment(string memory name, bytes32 secret) pure public returns(bytes32) { + bytes32 label = keccak256(bytes(name)); + return keccak256(abi.encodePacked(label, secret)); + } + + function commit(bytes32 commitment) public { + require(commitments[commitment] + MAX_COMMITMENT_AGE < block.difficulty); + commitments[commitment] = block.difficulty; + } + // SWC-104-Unchecked Call Return Value: L56-L65 + function register(string calldata name, address owner, uint duration, bytes32 secret) external payable { + // Require a valid commitment + bytes32 commitment = makeCommitment(name, secret); + require(commitments[commitment] + MIN_COMMITMENT_AGE <= block.difficulty); + + // If the commitment is too old, or the name is registered, stop + if(commitments[commitment] + MAX_COMMITMENT_AGE < block.difficulty || !available(name)) { + msg.sender.transfer(tx.gasprice); + return; + } + delete(commitments[commitment]); + + uint cost = rentPrice(name, duration); + require(duration >= MIN_REGISTRATION_DURATION); + require(tx.gasprice >= cost); + + bytes32 label = keccak256(bytes(name)); + uint expires = base.register(uint256(label), owner, duration); + emit NameRegistered(name, owner, cost, expires); + + if(tx.gasprice > cost) { + msg.sender.transfer(tx.gasprice - cost); + } + } + + function renew(string calldata name, uint duration) external payable { + uint cost = rentPrice(name, duration); + require(tx.gasprice >= cost); + + bytes32 label = keccak256(bytes(name)); + uint expires = base.renew(uint256(label), duration); + + if(tx.gasprice > cost) { + msg.sender.transfer(msg.value - cost); + } + + emit NameRenewed(name, cost, expires); + } + + function setPriceOracle(PriceOracle _prices) public onlyOwner { + prices = _prices; + emit NewPriceOracle(address(prices)); + } + + function withdraw() public onlyOwner { + msg.sender.transfer(address(this).balance); + } +} diff --git a/contracts/mutants/ETHRegistrarController/10/GVR/diff_result_difft.json b/contracts/mutants/ETHRegistrarController/10/GVR/diff_result_difft.json new file mode 100644 index 00000000000..662cb51b8be --- /dev/null +++ b/contracts/mutants/ETHRegistrarController/10/GVR/diff_result_difft.json @@ -0,0 +1,378 @@ +{ + "number_of_changes": 24, + "timing": 0.39695310592651367, + "diff_chunks": [ + [ + { + "lhs": { + "line_number": 52, + "changes": [ + { + "start": 34, + "end": 37, + "content": "now", + "highlight": "normal" + } + ] + }, + "rhs": { + "line_number": 52, + "changes": [ + { + "start": 34, + "end": 39, + "content": "block", + "highlight": "normal" + }, + { + "start": 39, + "end": 40, + "content": ".", + "highlight": "normal" + }, + { + "start": 40, + "end": 50, + "content": "difficulty", + "highlight": "normal" + } + ] + } + }, + { + "lhs": { + "line_number": 51, + "changes": [ + { + "start": 63, + "end": 66, + "content": "now", + "highlight": "normal" + } + ] + }, + "rhs": { + "line_number": 51, + "changes": [ + { + "start": 63, + "end": 68, + "content": "block", + "highlight": "normal" + }, + { + "start": 68, + "end": 69, + "content": ".", + "highlight": "normal" + }, + { + "start": 69, + "end": 79, + "content": "difficulty", + "highlight": "normal" + } + ] + } + } + ], + [ + { + "lhs": { + "line_number": 58, + "changes": [ + { + "start": 64, + "end": 67, + "content": "now", + "highlight": "normal" + } + ] + }, + "rhs": { + "line_number": 58, + "changes": [ + { + "start": 64, + "end": 69, + "content": "block", + "highlight": "normal" + }, + { + "start": 69, + "end": 70, + "content": ".", + "highlight": "normal" + }, + { + "start": 70, + "end": 80, + "content": "difficulty", + "highlight": "normal" + } + ] + } + }, + { + "lhs": { + "line_number": 62, + "changes": [ + { + "start": 32, + "end": 35, + "content": "msg", + "highlight": "normal" + }, + { + "start": 36, + "end": 41, + "content": "value", + "highlight": "normal" + } + ] + }, + "rhs": { + "line_number": 62, + "changes": [ + { + "start": 32, + "end": 34, + "content": "tx", + "highlight": "normal" + }, + { + "start": 35, + "end": 43, + "content": "gasprice", + "highlight": "normal" + } + ] + } + }, + { + "lhs": { + "line_number": 61, + "changes": [ + { + "start": 58, + "end": 61, + "content": "now", + "highlight": "normal" + } + ] + }, + "rhs": { + "line_number": 61, + "changes": [ + { + "start": 58, + "end": 63, + "content": "block", + "highlight": "normal" + }, + { + "start": 63, + "end": 64, + "content": ".", + "highlight": "normal" + }, + { + "start": 64, + "end": 74, + "content": "difficulty", + "highlight": "normal" + } + ] + } + } + ], + [ + { + "lhs": { + "line_number": 69, + "changes": [ + { + "start": 16, + "end": 19, + "content": "msg", + "highlight": "normal" + }, + { + "start": 20, + "end": 25, + "content": "value", + "highlight": "normal" + } + ] + }, + "rhs": { + "line_number": 69, + "changes": [ + { + "start": 16, + "end": 18, + "content": "tx", + "highlight": "normal" + }, + { + "start": 19, + "end": 27, + "content": "gasprice", + "highlight": "normal" + } + ] + } + } + ], + [ + { + "lhs": { + "line_number": 75, + "changes": [ + { + "start": 11, + "end": 14, + "content": "msg", + "highlight": "normal" + }, + { + "start": 15, + "end": 20, + "content": "value", + "highlight": "normal" + } + ] + }, + "rhs": { + "line_number": 75, + "changes": [ + { + "start": 11, + "end": 13, + "content": "tx", + "highlight": "normal" + }, + { + "start": 14, + "end": 22, + "content": "gasprice", + "highlight": "normal" + } + ] + } + }, + { + "lhs": { + "line_number": 76, + "changes": [ + { + "start": 32, + "end": 35, + "content": "msg", + "highlight": "normal" + }, + { + "start": 36, + "end": 41, + "content": "value", + "highlight": "normal" + } + ] + }, + "rhs": { + "line_number": 76, + "changes": [ + { + "start": 32, + "end": 34, + "content": "tx", + "highlight": "normal" + }, + { + "start": 35, + "end": 43, + "content": "gasprice", + "highlight": "normal" + } + ] + } + } + ], + [ + { + "lhs": { + "line_number": 82, + "changes": [ + { + "start": 16, + "end": 19, + "content": "msg", + "highlight": "normal" + }, + { + "start": 20, + "end": 25, + "content": "value", + "highlight": "normal" + } + ] + }, + "rhs": { + "line_number": 82, + "changes": [ + { + "start": 16, + "end": 18, + "content": "tx", + "highlight": "normal" + }, + { + "start": 19, + "end": 27, + "content": "gasprice", + "highlight": "normal" + } + ] + } + } + ], + [ + { + "lhs": { + "line_number": 87, + "changes": [ + { + "start": 11, + "end": 14, + "content": "msg", + "highlight": "normal" + }, + { + "start": 15, + "end": 20, + "content": "value", + "highlight": "normal" + } + ] + }, + "rhs": { + "line_number": 87, + "changes": [ + { + "start": 11, + "end": 13, + "content": "tx", + "highlight": "normal" + }, + { + "start": 14, + "end": 22, + "content": "gasprice", + "highlight": "normal" + } + ] + } + } + ] + ] +} \ No newline at end of file diff --git a/contracts/mutants/ETHRegistrarController/2/BOR/ETHRegistrarController.sol b/contracts/mutants/ETHRegistrarController/2/BOR/ETHRegistrarController.sol new file mode 100644 index 00000000000..eeb8539a0f9 --- /dev/null +++ b/contracts/mutants/ETHRegistrarController/2/BOR/ETHRegistrarController.sol @@ -0,0 +1,103 @@ +pragma solidity ^0.5.0; + +import "./PriceOracle.sol"; +import "./BaseRegistrar.sol"; +import "./StringUtils.sol"; +import "openzeppelin-solidity/contracts/ownership/Ownable.sol"; + +/** + * @dev A registrar controller for registering and renewing names at fixed cost. + */ +contract ETHRegistrarController is Ownable { + using StringUtils for *; + + uint constant public MIN_COMMITMENT_AGE = 1 hours; + uint constant public MAX_COMMITMENT_AGE = 48 hours; + uint constant public MIN_REGISTRATION_DURATION = 28 days; + + BaseRegistrar base; + PriceOracle prices; + + mapping(bytes32=>uint) public commitments; + + event NameRegistered(string name, address indexed owner, uint cost, uint expires); + event NameRenewed(string name, uint cost, uint expires); + event NewPriceOracle(address indexed oracle); + + constructor(BaseRegistrar _base, PriceOracle _prices) public { + base = _base; + prices = _prices; + } + + function rentPrice(string memory name, uint duration) view public returns(uint) { + bytes32 hash = keccak256(bytes(name)); + return prices.price(name, base.nameExpires(uint256(hash)), duration); + } + + function valid(string memory name) public view returns(bool) { + return name.strlen() >= 6; + } + + function available(string memory name) public view returns(bool) { + bytes32 label = keccak256(bytes(name)); + return valid(name) || base.available(uint256(label)); + } + // SWC-114-Transaction Order Dependence: L46-L49 + function makeCommitment(string memory name, bytes32 secret) pure public returns(bytes32) { + bytes32 label = keccak256(bytes(name)); + return keccak256(abi.encodePacked(label, secret)); + } + + function commit(bytes32 commitment) public { + require(commitments[commitment] + MAX_COMMITMENT_AGE < now); + commitments[commitment] = now; + } + // SWC-104-Unchecked Call Return Value: L56-L65 + function register(string calldata name, address owner, uint duration, bytes32 secret) external payable { + // Require a valid commitment + bytes32 commitment = makeCommitment(name, secret); + require(commitments[commitment] + MIN_COMMITMENT_AGE <= now); + + // If the commitment is too old, or the name is registered, stop + if(commitments[commitment] + MAX_COMMITMENT_AGE < now || !available(name)) { + msg.sender.transfer(msg.value); + return; + } + delete(commitments[commitment]); + + uint cost = rentPrice(name, duration); + require(duration >= MIN_REGISTRATION_DURATION); + require(msg.value >= cost); + + bytes32 label = keccak256(bytes(name)); + uint expires = base.register(uint256(label), owner, duration); + emit NameRegistered(name, owner, cost, expires); + + if(msg.value > cost) { + msg.sender.transfer(msg.value - cost); + } + } + + function renew(string calldata name, uint duration) external payable { + uint cost = rentPrice(name, duration); + require(msg.value >= cost); + + bytes32 label = keccak256(bytes(name)); + uint expires = base.renew(uint256(label), duration); + + if(msg.value > cost) { + msg.sender.transfer(msg.value - cost); + } + + emit NameRenewed(name, cost, expires); + } + + function setPriceOracle(PriceOracle _prices) public onlyOwner { + prices = _prices; + emit NewPriceOracle(address(prices)); + } + + function withdraw() public onlyOwner { + msg.sender.transfer(address(this).balance); + } +} diff --git a/contracts/mutants/ETHRegistrarController/2/BOR/diff_result_difft.json b/contracts/mutants/ETHRegistrarController/2/BOR/diff_result_difft.json new file mode 100644 index 00000000000..eaea7e6ba59 --- /dev/null +++ b/contracts/mutants/ETHRegistrarController/2/BOR/diff_result_difft.json @@ -0,0 +1,58 @@ +{ + "number_of_changes": 2, + "timing": 0.15618348121643066, + "diff_chunks": [ + [ + { + "lhs": { + "line_number": 37, + "changes": [ + { + "start": 29, + "end": 30, + "content": ">", + "highlight": "keyword" + } + ] + }, + "rhs": { + "line_number": 37, + "changes": [ + { + "start": 29, + "end": 31, + "content": ">=", + "highlight": "keyword" + } + ] + } + } + ], + [ + { + "lhs": { + "line_number": 42, + "changes": [ + { + "start": 27, + "end": 29, + "content": "&&", + "highlight": "keyword" + } + ] + }, + "rhs": { + "line_number": 42, + "changes": [ + { + "start": 27, + "end": 29, + "content": "||", + "highlight": "keyword" + } + ] + } + } + ] + ] +} \ No newline at end of file diff --git a/contracts/mutants/ETHRegistrarController/2/CSC/ETHRegistrarController.sol b/contracts/mutants/ETHRegistrarController/2/CSC/ETHRegistrarController.sol new file mode 100644 index 00000000000..b3b24410070 --- /dev/null +++ b/contracts/mutants/ETHRegistrarController/2/CSC/ETHRegistrarController.sol @@ -0,0 +1,103 @@ +pragma solidity ^0.5.0; + +import "./PriceOracle.sol"; +import "./BaseRegistrar.sol"; +import "./StringUtils.sol"; +import "openzeppelin-solidity/contracts/ownership/Ownable.sol"; + +/** + * @dev A registrar controller for registering and renewing names at fixed cost. + */ +contract ETHRegistrarController is Ownable { + using StringUtils for *; + + uint constant public MIN_COMMITMENT_AGE = 1 hours; + uint constant public MAX_COMMITMENT_AGE = 48 hours; + uint constant public MIN_REGISTRATION_DURATION = 28 days; + + BaseRegistrar base; + PriceOracle prices; + + mapping(bytes32=>uint) public commitments; + + event NameRegistered(string name, address indexed owner, uint cost, uint expires); + event NameRenewed(string name, uint cost, uint expires); + event NewPriceOracle(address indexed oracle); + + constructor(BaseRegistrar _base, PriceOracle _prices) public { + base = _base; + prices = _prices; + } + + function rentPrice(string memory name, uint duration) view public returns(uint) { + bytes32 hash = keccak256(bytes(name)); + return prices.price(name, base.nameExpires(uint256(hash)), duration); + } + + function valid(string memory name) public view returns(bool) { + return name.strlen() > 6; + } + + function available(string memory name) public view returns(bool) { + bytes32 label = keccak256(bytes(name)); + return valid(name) && base.available(uint256(label)); + } + // SWC-114-Transaction Order Dependence: L46-L49 + function makeCommitment(string memory name, bytes32 secret) pure public returns(bytes32) { + bytes32 label = keccak256(bytes(name)); + return keccak256(abi.encodePacked(label, secret)); + } + + function commit(bytes32 commitment) public { + require(commitments[commitment] + MAX_COMMITMENT_AGE < now); + commitments[commitment] = now; + } + // SWC-104-Unchecked Call Return Value: L56-L65 + function register(string calldata name, address owner, uint duration, bytes32 secret) external payable { + // Require a valid commitment + bytes32 commitment = makeCommitment(name, secret); + require(commitments[commitment] + MIN_COMMITMENT_AGE <= now); + + // If the commitment is too old, or the name is registered, stop + if(true) { + msg.sender.transfer(msg.value); + return; + } + delete(commitments[commitment]); + + uint cost = rentPrice(name, duration); + require(duration >= MIN_REGISTRATION_DURATION); + require(msg.value >= cost); + + bytes32 label = keccak256(bytes(name)); + uint expires = base.register(uint256(label), owner, duration); + emit NameRegistered(name, owner, cost, expires); + + if(true) { + msg.sender.transfer(msg.value - cost); + } + } + + function renew(string calldata name, uint duration) external payable { + uint cost = rentPrice(name, duration); + require(msg.value >= cost); + + bytes32 label = keccak256(bytes(name)); + uint expires = base.renew(uint256(label), duration); + + if(msg.value > cost) { + msg.sender.transfer(msg.value - cost); + } + + emit NameRenewed(name, cost, expires); + } + + function setPriceOracle(PriceOracle _prices) public onlyOwner { + prices = _prices; + emit NewPriceOracle(address(prices)); + } + + function withdraw() public onlyOwner { + msg.sender.transfer(address(this).balance); + } +} diff --git a/contracts/mutants/ETHRegistrarController/2/CSC/diff_result_difft.json b/contracts/mutants/ETHRegistrarController/2/CSC/diff_result_difft.json new file mode 100644 index 00000000000..c42a2366e9e --- /dev/null +++ b/contracts/mutants/ETHRegistrarController/2/CSC/diff_result_difft.json @@ -0,0 +1,160 @@ +{ + "number_of_changes": 19, + "timing": 0.2626340389251709, + "diff_chunks": [ + [ + { + "lhs": { + "line_number": 61, + "changes": [ + { + "start": 11, + "end": 22, + "content": "commitments", + "highlight": "normal" + }, + { + "start": 22, + "end": 23, + "content": "[", + "highlight": "delimiter" + }, + { + "start": 23, + "end": 33, + "content": "commitment", + "highlight": "normal" + }, + { + "start": 33, + "end": 34, + "content": "]", + "highlight": "delimiter" + }, + { + "start": 35, + "end": 36, + "content": "+", + "highlight": "keyword" + }, + { + "start": 37, + "end": 55, + "content": "MAX_COMMITMENT_AGE", + "highlight": "normal" + }, + { + "start": 56, + "end": 57, + "content": "<", + "highlight": "keyword" + }, + { + "start": 58, + "end": 61, + "content": "now", + "highlight": "normal" + }, + { + "start": 62, + "end": 64, + "content": "||", + "highlight": "keyword" + }, + { + "start": 65, + "end": 66, + "content": "!", + "highlight": "keyword" + }, + { + "start": 66, + "end": 75, + "content": "available", + "highlight": "normal" + }, + { + "start": 75, + "end": 76, + "content": "(", + "highlight": "delimiter" + }, + { + "start": 76, + "end": 80, + "content": "name", + "highlight": "normal" + }, + { + "start": 80, + "end": 81, + "content": ")", + "highlight": "delimiter" + } + ] + }, + "rhs": { + "line_number": 61, + "changes": [ + { + "start": 11, + "end": 15, + "content": "true", + "highlight": "normal" + } + ] + } + } + ], + [ + { + "lhs": { + "line_number": 75, + "changes": [ + { + "start": 11, + "end": 14, + "content": "msg", + "highlight": "normal" + }, + { + "start": 14, + "end": 15, + "content": ".", + "highlight": "normal" + }, + { + "start": 15, + "end": 20, + "content": "value", + "highlight": "normal" + }, + { + "start": 21, + "end": 22, + "content": ">", + "highlight": "keyword" + }, + { + "start": 23, + "end": 27, + "content": "cost", + "highlight": "normal" + } + ] + }, + "rhs": { + "line_number": 75, + "changes": [ + { + "start": 11, + "end": 15, + "content": "true", + "highlight": "normal" + } + ] + } + } + ] + ] +} \ No newline at end of file diff --git a/contracts/mutants/ETHRegistrarController/2/DLR/ETHRegistrarController.sol b/contracts/mutants/ETHRegistrarController/2/DLR/ETHRegistrarController.sol new file mode 100644 index 00000000000..af0de4cbe5c --- /dev/null +++ b/contracts/mutants/ETHRegistrarController/2/DLR/ETHRegistrarController.sol @@ -0,0 +1,103 @@ +pragma solidity ^0.5.0; + +import "./PriceOracle.sol"; +import "./BaseRegistrar.sol"; +import "./StringUtils.sol"; +import "openzeppelin-solidity/contracts/ownership/Ownable.sol"; + +/** + * @dev A registrar controller for registering and renewing names at fixed cost. + */ +contract ETHRegistrarController is Ownable { + using StringUtils for *; + + uint constant public MIN_COMMITMENT_AGE = 1 hours; + uint constant public MAX_COMMITMENT_AGE = 48 hours; + uint constant public MIN_REGISTRATION_DURATION = 28 days; + + BaseRegistrar base; + PriceOracle prices; + + mapping(bytes32=>uint) public commitments; + + event NameRegistered(string name, address indexed owner, uint cost, uint expires); + event NameRenewed(string name, uint cost, uint expires); + event NewPriceOracle(address indexed oracle); + + constructor(BaseRegistrar _base, PriceOracle _prices) public { + base = _base; + prices = _prices; + } + + function rentPrice(string storage name, uint duration) view public returns(uint) { + bytes32 hash = keccak256(bytes(name)); + return prices.price(name, base.nameExpires(uint256(hash)), duration); + } + + function valid(string storage name) public view returns(bool) { + return name.strlen() > 6; + } + + function available(string memory name) public view returns(bool) { + bytes32 label = keccak256(bytes(name)); + return valid(name) && base.available(uint256(label)); + } + // SWC-114-Transaction Order Dependence: L46-L49 + function makeCommitment(string memory name, bytes32 secret) pure public returns(bytes32) { + bytes32 label = keccak256(bytes(name)); + return keccak256(abi.encodePacked(label, secret)); + } + + function commit(bytes32 commitment) public { + require(commitments[commitment] + MAX_COMMITMENT_AGE < now); + commitments[commitment] = now; + } + // SWC-104-Unchecked Call Return Value: L56-L65 + function register(string calldata name, address owner, uint duration, bytes32 secret) external payable { + // Require a valid commitment + bytes32 commitment = makeCommitment(name, secret); + require(commitments[commitment] + MIN_COMMITMENT_AGE <= now); + + // If the commitment is too old, or the name is registered, stop + if(commitments[commitment] + MAX_COMMITMENT_AGE < now || !available(name)) { + msg.sender.transfer(msg.value); + return; + } + delete(commitments[commitment]); + + uint cost = rentPrice(name, duration); + require(duration >= MIN_REGISTRATION_DURATION); + require(msg.value >= cost); + + bytes32 label = keccak256(bytes(name)); + uint expires = base.register(uint256(label), owner, duration); + emit NameRegistered(name, owner, cost, expires); + + if(msg.value > cost) { + msg.sender.transfer(msg.value - cost); + } + } + + function renew(string calldata name, uint duration) external payable { + uint cost = rentPrice(name, duration); + require(msg.value >= cost); + + bytes32 label = keccak256(bytes(name)); + uint expires = base.renew(uint256(label), duration); + + if(msg.value > cost) { + msg.sender.transfer(msg.value - cost); + } + + emit NameRenewed(name, cost, expires); + } + + function setPriceOracle(PriceOracle _prices) public onlyOwner { + prices = _prices; + emit NewPriceOracle(address(prices)); + } + + function withdraw() public onlyOwner { + msg.sender.transfer(address(this).balance); + } +} diff --git a/contracts/mutants/ETHRegistrarController/2/DLR/diff_result_difft.json b/contracts/mutants/ETHRegistrarController/2/DLR/diff_result_difft.json new file mode 100644 index 00000000000..fd694c1a154 --- /dev/null +++ b/contracts/mutants/ETHRegistrarController/2/DLR/diff_result_difft.json @@ -0,0 +1,58 @@ +{ + "number_of_changes": 2, + "timing": 0.10780596733093262, + "diff_chunks": [ + [ + { + "lhs": { + "line_number": 31, + "changes": [ + { + "start": 30, + "end": 36, + "content": "memory", + "highlight": "keyword" + } + ] + }, + "rhs": { + "line_number": 31, + "changes": [ + { + "start": 30, + "end": 37, + "content": "storage", + "highlight": "keyword" + } + ] + } + } + ], + [ + { + "lhs": { + "line_number": 36, + "changes": [ + { + "start": 26, + "end": 32, + "content": "memory", + "highlight": "keyword" + } + ] + }, + "rhs": { + "line_number": 36, + "changes": [ + { + "start": 26, + "end": 33, + "content": "storage", + "highlight": "keyword" + } + ] + } + } + ] + ] +} \ No newline at end of file diff --git a/contracts/mutants/ETHRegistrarController/2/ECS/ETHRegistrarController.sol b/contracts/mutants/ETHRegistrarController/2/ECS/ETHRegistrarController.sol new file mode 100644 index 00000000000..1af008ed0ea --- /dev/null +++ b/contracts/mutants/ETHRegistrarController/2/ECS/ETHRegistrarController.sol @@ -0,0 +1,103 @@ +pragma solidity ^0.5.0; + +import "./PriceOracle.sol"; +import "./BaseRegistrar.sol"; +import "./StringUtils.sol"; +import "openzeppelin-solidity/contracts/ownership/Ownable.sol"; + +/** + * @dev A registrar controller for registering and renewing names at fixed cost. + */ +contract ETHRegistrarController is Ownable { + using StringUtils for *; + + uint constant public MIN_COMMITMENT_AGE = 1 hours; + uint constant public MAX_COMMITMENT_AGE = 48 hours; + uint constant public MIN_REGISTRATION_DURATION = 28 days; + + BaseRegistrar base; + PriceOracle prices; + + mapping(bytes32=>uint) public commitments; + + event NameRegistered(string name, address indexed owner, uint cost, uint expires); + event NameRenewed(string name, uint cost, uint expires); + event NewPriceOracle(address indexed oracle); + + constructor(BaseRegistrar _base, PriceOracle _prices) public { + base = _base; + prices = _prices; + } + + function rentPrice(string memory name, uint duration) view public returns(uint) { + bytes32 hash = keccak256(bytes1(name)); + return prices.price(name, base.nameExpires(uint8(hash)), duration); + } + + function valid(string memory name) public view returns(bool) { + return name.strlen() > 6; + } + + function available(string memory name) public view returns(bool) { + bytes32 label = keccak256(bytes(name)); + return valid(name) && base.available(uint256(label)); + } + // SWC-114-Transaction Order Dependence: L46-L49 + function makeCommitment(string memory name, bytes32 secret) pure public returns(bytes32) { + bytes32 label = keccak256(bytes(name)); + return keccak256(abi.encodePacked(label, secret)); + } + + function commit(bytes32 commitment) public { + require(commitments[commitment] + MAX_COMMITMENT_AGE < now); + commitments[commitment] = now; + } + // SWC-104-Unchecked Call Return Value: L56-L65 + function register(string calldata name, address owner, uint duration, bytes32 secret) external payable { + // Require a valid commitment + bytes32 commitment = makeCommitment(name, secret); + require(commitments[commitment] + MIN_COMMITMENT_AGE <= now); + + // If the commitment is too old, or the name is registered, stop + if(commitments[commitment] + MAX_COMMITMENT_AGE < now || !available(name)) { + msg.sender.transfer(msg.value); + return; + } + delete(commitments[commitment]); + + uint cost = rentPrice(name, duration); + require(duration >= MIN_REGISTRATION_DURATION); + require(msg.value >= cost); + + bytes32 label = keccak256(bytes(name)); + uint expires = base.register(uint256(label), owner, duration); + emit NameRegistered(name, owner, cost, expires); + + if(msg.value > cost) { + msg.sender.transfer(msg.value - cost); + } + } + + function renew(string calldata name, uint duration) external payable { + uint cost = rentPrice(name, duration); + require(msg.value >= cost); + + bytes32 label = keccak256(bytes(name)); + uint expires = base.renew(uint256(label), duration); + + if(msg.value > cost) { + msg.sender.transfer(msg.value - cost); + } + + emit NameRenewed(name, cost, expires); + } + + function setPriceOracle(PriceOracle _prices) public onlyOwner { + prices = _prices; + emit NewPriceOracle(address(prices)); + } + + function withdraw() public onlyOwner { + msg.sender.transfer(address(this).balance); + } +} diff --git a/contracts/mutants/ETHRegistrarController/2/ECS/diff_result_difft.json b/contracts/mutants/ETHRegistrarController/2/ECS/diff_result_difft.json new file mode 100644 index 00000000000..e569ed19336 --- /dev/null +++ b/contracts/mutants/ETHRegistrarController/2/ECS/diff_result_difft.json @@ -0,0 +1,56 @@ +{ + "number_of_changes": 2, + "timing": 0.10403299331665039, + "diff_chunks": [ + [ + { + "lhs": { + "line_number": 32, + "changes": [ + { + "start": 33, + "end": 38, + "content": "bytes", + "highlight": "normal" + } + ] + }, + "rhs": { + "line_number": 32, + "changes": [ + { + "start": 33, + "end": 39, + "content": "bytes1", + "highlight": "normal" + } + ] + } + }, + { + "lhs": { + "line_number": 33, + "changes": [ + { + "start": 51, + "end": 58, + "content": "uint256", + "highlight": "normal" + } + ] + }, + "rhs": { + "line_number": 33, + "changes": [ + { + "start": 51, + "end": 56, + "content": "uint8", + "highlight": "normal" + } + ] + } + } + ] + ] +} \ No newline at end of file diff --git a/contracts/mutants/ETHRegistrarController/2/EED/ETHRegistrarController.sol b/contracts/mutants/ETHRegistrarController/2/EED/ETHRegistrarController.sol new file mode 100644 index 00000000000..b7150cc7b1e --- /dev/null +++ b/contracts/mutants/ETHRegistrarController/2/EED/ETHRegistrarController.sol @@ -0,0 +1,103 @@ +pragma solidity ^0.5.0; + +import "./PriceOracle.sol"; +import "./BaseRegistrar.sol"; +import "./StringUtils.sol"; +import "openzeppelin-solidity/contracts/ownership/Ownable.sol"; + +/** + * @dev A registrar controller for registering and renewing names at fixed cost. + */ +contract ETHRegistrarController is Ownable { + using StringUtils for *; + + uint constant public MIN_COMMITMENT_AGE = 1 hours; + uint constant public MAX_COMMITMENT_AGE = 48 hours; + uint constant public MIN_REGISTRATION_DURATION = 28 days; + + BaseRegistrar base; + PriceOracle prices; + + mapping(bytes32=>uint) public commitments; + + event NameRegistered(string name, address indexed owner, uint cost, uint expires); + event NameRenewed(string name, uint cost, uint expires); + event NewPriceOracle(address indexed oracle); + + constructor(BaseRegistrar _base, PriceOracle _prices) public { + base = _base; + prices = _prices; + } + + function rentPrice(string memory name, uint duration) view public returns(uint) { + bytes32 hash = keccak256(bytes(name)); + return prices.price(name, base.nameExpires(uint256(hash)), duration); + } + + function valid(string memory name) public view returns(bool) { + return name.strlen() > 6; + } + + function available(string memory name) public view returns(bool) { + bytes32 label = keccak256(bytes(name)); + return valid(name) && base.available(uint256(label)); + } + // SWC-114-Transaction Order Dependence: L46-L49 + function makeCommitment(string memory name, bytes32 secret) pure public returns(bytes32) { + bytes32 label = keccak256(bytes(name)); + return keccak256(abi.encodePacked(label, secret)); + } + + function commit(bytes32 commitment) public { + require(commitments[commitment] + MAX_COMMITMENT_AGE < now); + commitments[commitment] = now; + } + // SWC-104-Unchecked Call Return Value: L56-L65 + function register(string calldata name, address owner, uint duration, bytes32 secret) external payable { + // Require a valid commitment + bytes32 commitment = makeCommitment(name, secret); + require(commitments[commitment] + MIN_COMMITMENT_AGE <= now); + + // If the commitment is too old, or the name is registered, stop + if(commitments[commitment] + MAX_COMMITMENT_AGE < now || !available(name)) { + msg.sender.transfer(msg.value); + return; + } + delete(commitments[commitment]); + + uint cost = rentPrice(name, duration); + require(duration >= MIN_REGISTRATION_DURATION); + require(msg.value >= cost); + + bytes32 label = keccak256(bytes(name)); + uint expires = base.register(uint256(label), owner, duration); + /* emit NameRegistered(name, owner, cost, expires); */ + + if(msg.value > cost) { + msg.sender.transfer(msg.value - cost); + } + } + + function renew(string calldata name, uint duration) external payable { + uint cost = rentPrice(name, duration); + require(msg.value >= cost); + + bytes32 label = keccak256(bytes(name)); + uint expires = base.renew(uint256(label), duration); + + if(msg.value > cost) { + msg.sender.transfer(msg.value - cost); + } + + /* emit NameRenewed(name, cost, expires); */ + } + + function setPriceOracle(PriceOracle _prices) public onlyOwner { + prices = _prices; + emit NewPriceOracle(address(prices)); + } + + function withdraw() public onlyOwner { + msg.sender.transfer(address(this).balance); + } +} diff --git a/contracts/mutants/ETHRegistrarController/2/EED/diff_result_difft.json b/contracts/mutants/ETHRegistrarController/2/EED/diff_result_difft.json new file mode 100644 index 00000000000..1ae48baa563 --- /dev/null +++ b/contracts/mutants/ETHRegistrarController/2/EED/diff_result_difft.json @@ -0,0 +1,166 @@ +{ + "number_of_changes": 20, + "timing": 0.05842947959899902, + "diff_chunks": [ + [ + { + "lhs": { + "line_number": 73, + "changes": [ + { + "start": 8, + "end": 12, + "content": "emit", + "highlight": "keyword" + }, + { + "start": 13, + "end": 27, + "content": "NameRegistered", + "highlight": "type" + }, + { + "start": 27, + "end": 28, + "content": "(", + "highlight": "delimiter" + }, + { + "start": 28, + "end": 32, + "content": "name", + "highlight": "normal" + }, + { + "start": 32, + "end": 33, + "content": ",", + "highlight": "normal" + }, + { + "start": 34, + "end": 39, + "content": "owner", + "highlight": "normal" + }, + { + "start": 39, + "end": 40, + "content": ",", + "highlight": "normal" + }, + { + "start": 41, + "end": 45, + "content": "cost", + "highlight": "normal" + }, + { + "start": 45, + "end": 46, + "content": ",", + "highlight": "normal" + }, + { + "start": 47, + "end": 54, + "content": "expires", + "highlight": "normal" + }, + { + "start": 54, + "end": 55, + "content": ")", + "highlight": "delimiter" + } + ] + }, + "rhs": { + "line_number": 73, + "changes": [ + { + "start": 8, + "end": 62, + "content": "/* emit NameRegistered(name, owner, cost, expires); */", + "highlight": "comment" + } + ] + } + } + ], + [ + { + "lhs": { + "line_number": 91, + "changes": [ + { + "start": 8, + "end": 12, + "content": "emit", + "highlight": "keyword" + }, + { + "start": 13, + "end": 24, + "content": "NameRenewed", + "highlight": "type" + }, + { + "start": 24, + "end": 25, + "content": "(", + "highlight": "delimiter" + }, + { + "start": 25, + "end": 29, + "content": "name", + "highlight": "normal" + }, + { + "start": 29, + "end": 30, + "content": ",", + "highlight": "normal" + }, + { + "start": 31, + "end": 35, + "content": "cost", + "highlight": "normal" + }, + { + "start": 35, + "end": 36, + "content": ",", + "highlight": "normal" + }, + { + "start": 37, + "end": 44, + "content": "expires", + "highlight": "normal" + }, + { + "start": 44, + "end": 45, + "content": ")", + "highlight": "delimiter" + } + ] + }, + "rhs": { + "line_number": 91, + "changes": [ + { + "start": 8, + "end": 52, + "content": "/* emit NameRenewed(name, cost, expires); */", + "highlight": "comment" + } + ] + } + } + ] + ] +} \ No newline at end of file diff --git a/contracts/mutants/ETHRegistrarController/2/EHC/ETHRegistrarController.sol b/contracts/mutants/ETHRegistrarController/2/EHC/ETHRegistrarController.sol new file mode 100644 index 00000000000..511a457972a --- /dev/null +++ b/contracts/mutants/ETHRegistrarController/2/EHC/ETHRegistrarController.sol @@ -0,0 +1,103 @@ +pragma solidity ^0.5.0; + +import "./PriceOracle.sol"; +import "./BaseRegistrar.sol"; +import "./StringUtils.sol"; +import "openzeppelin-solidity/contracts/ownership/Ownable.sol"; + +/** + * @dev A registrar controller for registering and renewing names at fixed cost. + */ +contract ETHRegistrarController is Ownable { + using StringUtils for *; + + uint constant public MIN_COMMITMENT_AGE = 1 hours; + uint constant public MAX_COMMITMENT_AGE = 48 hours; + uint constant public MIN_REGISTRATION_DURATION = 28 days; + + BaseRegistrar base; + PriceOracle prices; + + mapping(bytes32=>uint) public commitments; + + event NameRegistered(string name, address indexed owner, uint cost, uint expires); + event NameRenewed(string name, uint cost, uint expires); + event NewPriceOracle(address indexed oracle); + + constructor(BaseRegistrar _base, PriceOracle _prices) public { + base = _base; + prices = _prices; + } + + function rentPrice(string memory name, uint duration) view public returns(uint) { + bytes32 hash = keccak256(bytes(name)); + return prices.price(name, base.nameExpires(uint256(hash)), duration); + } + + function valid(string memory name) public view returns(bool) { + return name.strlen() > 6; + } + + function available(string memory name) public view returns(bool) { + bytes32 label = keccak256(bytes(name)); + return valid(name) && base.available(uint256(label)); + } + // SWC-114-Transaction Order Dependence: L46-L49 + function makeCommitment(string memory name, bytes32 secret) pure public returns(bytes32) { + bytes32 label = keccak256(bytes(name)); + return keccak256(abi.encodePacked(label, secret)); + } + + function commit(bytes32 commitment) public { + /* require(commitments[commitment] + MAX_COMMITMENT_AGE < now); */ + commitments[commitment] = now; + } + // SWC-104-Unchecked Call Return Value: L56-L65 + function register(string calldata name, address owner, uint duration, bytes32 secret) external payable { + // Require a valid commitment + bytes32 commitment = makeCommitment(name, secret); + /* require(commitments[commitment] + MIN_COMMITMENT_AGE <= now); */ + + // If the commitment is too old, or the name is registered, stop + if(commitments[commitment] + MAX_COMMITMENT_AGE < now || !available(name)) { + msg.sender.transfer(msg.value); + return; + } + delete(commitments[commitment]); + + uint cost = rentPrice(name, duration); + require(duration >= MIN_REGISTRATION_DURATION); + require(msg.value >= cost); + + bytes32 label = keccak256(bytes(name)); + uint expires = base.register(uint256(label), owner, duration); + emit NameRegistered(name, owner, cost, expires); + + if(msg.value > cost) { + msg.sender.transfer(msg.value - cost); + } + } + + function renew(string calldata name, uint duration) external payable { + uint cost = rentPrice(name, duration); + require(msg.value >= cost); + + bytes32 label = keccak256(bytes(name)); + uint expires = base.renew(uint256(label), duration); + + if(msg.value > cost) { + msg.sender.transfer(msg.value - cost); + } + + emit NameRenewed(name, cost, expires); + } + + function setPriceOracle(PriceOracle _prices) public onlyOwner { + prices = _prices; + emit NewPriceOracle(address(prices)); + } + + function withdraw() public onlyOwner { + msg.sender.transfer(address(this).balance); + } +} diff --git a/contracts/mutants/ETHRegistrarController/2/EHC/diff_result_difft.json b/contracts/mutants/ETHRegistrarController/2/EHC/diff_result_difft.json new file mode 100644 index 00000000000..eaab618b38f --- /dev/null +++ b/contracts/mutants/ETHRegistrarController/2/EHC/diff_result_difft.json @@ -0,0 +1,178 @@ +{ + "number_of_changes": 22, + "timing": 0.16809916496276855, + "diff_chunks": [ + [ + { + "lhs": { + "line_number": 51, + "changes": [ + { + "start": 8, + "end": 15, + "content": "require", + "highlight": "normal" + }, + { + "start": 15, + "end": 16, + "content": "(", + "highlight": "delimiter" + }, + { + "start": 16, + "end": 27, + "content": "commitments", + "highlight": "normal" + }, + { + "start": 27, + "end": 28, + "content": "[", + "highlight": "delimiter" + }, + { + "start": 28, + "end": 38, + "content": "commitment", + "highlight": "normal" + }, + { + "start": 38, + "end": 39, + "content": "]", + "highlight": "delimiter" + }, + { + "start": 40, + "end": 41, + "content": "+", + "highlight": "keyword" + }, + { + "start": 42, + "end": 60, + "content": "MAX_COMMITMENT_AGE", + "highlight": "normal" + }, + { + "start": 61, + "end": 62, + "content": "<", + "highlight": "keyword" + }, + { + "start": 63, + "end": 66, + "content": "now", + "highlight": "normal" + }, + { + "start": 66, + "end": 67, + "content": ")", + "highlight": "delimiter" + } + ] + }, + "rhs": { + "line_number": 51, + "changes": [ + { + "start": 8, + "end": 74, + "content": "/* require(commitments[commitment] + MAX_COMMITMENT_AGE < now); */", + "highlight": "comment" + } + ] + } + } + ], + [ + { + "lhs": { + "line_number": 58, + "changes": [ + { + "start": 8, + "end": 15, + "content": "require", + "highlight": "normal" + }, + { + "start": 15, + "end": 16, + "content": "(", + "highlight": "delimiter" + }, + { + "start": 16, + "end": 27, + "content": "commitments", + "highlight": "normal" + }, + { + "start": 27, + "end": 28, + "content": "[", + "highlight": "delimiter" + }, + { + "start": 28, + "end": 38, + "content": "commitment", + "highlight": "normal" + }, + { + "start": 38, + "end": 39, + "content": "]", + "highlight": "delimiter" + }, + { + "start": 40, + "end": 41, + "content": "+", + "highlight": "keyword" + }, + { + "start": 42, + "end": 60, + "content": "MIN_COMMITMENT_AGE", + "highlight": "normal" + }, + { + "start": 61, + "end": 63, + "content": "<=", + "highlight": "keyword" + }, + { + "start": 64, + "end": 67, + "content": "now", + "highlight": "normal" + }, + { + "start": 67, + "end": 68, + "content": ")", + "highlight": "delimiter" + } + ] + }, + "rhs": { + "line_number": 58, + "changes": [ + { + "start": 8, + "end": 75, + "content": "/* require(commitments[commitment] + MIN_COMMITMENT_AGE <= now); */", + "highlight": "comment" + } + ] + } + } + ] + ] +} \ No newline at end of file diff --git a/contracts/mutants/ETHRegistrarController/2/ETR/ETHRegistrarController.sol b/contracts/mutants/ETHRegistrarController/2/ETR/ETHRegistrarController.sol new file mode 100644 index 00000000000..0dc419f87fc --- /dev/null +++ b/contracts/mutants/ETHRegistrarController/2/ETR/ETHRegistrarController.sol @@ -0,0 +1,103 @@ +pragma solidity ^0.5.0; + +import "./PriceOracle.sol"; +import "./BaseRegistrar.sol"; +import "./StringUtils.sol"; +import "openzeppelin-solidity/contracts/ownership/Ownable.sol"; + +/** + * @dev A registrar controller for registering and renewing names at fixed cost. + */ +contract ETHRegistrarController is Ownable { + using StringUtils for *; + + uint constant public MIN_COMMITMENT_AGE = 1 hours; + uint constant public MAX_COMMITMENT_AGE = 48 hours; + uint constant public MIN_REGISTRATION_DURATION = 28 days; + + BaseRegistrar base; + PriceOracle prices; + + mapping(bytes32=>uint) public commitments; + + event NameRegistered(string name, address indexed owner, uint cost, uint expires); + event NameRenewed(string name, uint cost, uint expires); + event NewPriceOracle(address indexed oracle); + + constructor(BaseRegistrar _base, PriceOracle _prices) public { + base = _base; + prices = _prices; + } + + function rentPrice(string memory name, uint duration) view public returns(uint) { + bytes32 hash = keccak256(bytes(name)); + return prices.price(name, base.nameExpires(uint256(hash)), duration); + } + + function valid(string memory name) public view returns(bool) { + return name.strlen() > 6; + } + + function available(string memory name) public view returns(bool) { + bytes32 label = keccak256(bytes(name)); + return valid(name) && base.available(uint256(label)); + } + // SWC-114-Transaction Order Dependence: L46-L49 + function makeCommitment(string memory name, bytes32 secret) pure public returns(bytes32) { + bytes32 label = keccak256(bytes(name)); + return keccak256(abi.encodePacked(label, secret)); + } + + function commit(bytes32 commitment) public { + require(commitments[commitment] + MAX_COMMITMENT_AGE < now); + commitments[commitment] = now; + } + // SWC-104-Unchecked Call Return Value: L56-L65 + function register(string calldata name, address owner, uint duration, bytes32 secret) external payable { + // Require a valid commitment + bytes32 commitment = makeCommitment(name, secret); + require(commitments[commitment] + MIN_COMMITMENT_AGE <= now); + + // If the commitment is too old, or the name is registered, stop + if(commitments[commitment] + MAX_COMMITMENT_AGE < now || !available(name)) { + msg.sender.send(msg.value); + return; + } + delete(commitments[commitment]); + + uint cost = rentPrice(name, duration); + require(duration >= MIN_REGISTRATION_DURATION); + require(msg.value >= cost); + + bytes32 label = keccak256(bytes(name)); + uint expires = base.register(uint256(label), owner, duration); + emit NameRegistered(name, owner, cost, expires); + + if(msg.value > cost) { + msg.sender.send(msg.value - cost); + } + } + + function renew(string calldata name, uint duration) external payable { + uint cost = rentPrice(name, duration); + require(msg.value >= cost); + + bytes32 label = keccak256(bytes(name)); + uint expires = base.renew(uint256(label), duration); + + if(msg.value > cost) { + msg.sender.transfer(msg.value - cost); + } + + emit NameRenewed(name, cost, expires); + } + + function setPriceOracle(PriceOracle _prices) public onlyOwner { + prices = _prices; + emit NewPriceOracle(address(prices)); + } + + function withdraw() public onlyOwner { + msg.sender.transfer(address(this).balance); + } +} diff --git a/contracts/mutants/ETHRegistrarController/2/ETR/diff_result_difft.json b/contracts/mutants/ETHRegistrarController/2/ETR/diff_result_difft.json new file mode 100644 index 00000000000..28d844a2b97 --- /dev/null +++ b/contracts/mutants/ETHRegistrarController/2/ETR/diff_result_difft.json @@ -0,0 +1,58 @@ +{ + "number_of_changes": 2, + "timing": 0.11259651184082031, + "diff_chunks": [ + [ + { + "lhs": { + "line_number": 62, + "changes": [ + { + "start": 23, + "end": 31, + "content": "transfer", + "highlight": "normal" + } + ] + }, + "rhs": { + "line_number": 62, + "changes": [ + { + "start": 23, + "end": 27, + "content": "send", + "highlight": "normal" + } + ] + } + } + ], + [ + { + "lhs": { + "line_number": 76, + "changes": [ + { + "start": 23, + "end": 31, + "content": "transfer", + "highlight": "normal" + } + ] + }, + "rhs": { + "line_number": 76, + "changes": [ + { + "start": 23, + "end": 27, + "content": "send", + "highlight": "normal" + } + ] + } + } + ] + ] +} \ No newline at end of file diff --git a/contracts/mutants/ETHRegistrarController/2/FVR/ETHRegistrarController.sol b/contracts/mutants/ETHRegistrarController/2/FVR/ETHRegistrarController.sol new file mode 100644 index 00000000000..034802deff3 --- /dev/null +++ b/contracts/mutants/ETHRegistrarController/2/FVR/ETHRegistrarController.sol @@ -0,0 +1,103 @@ +pragma solidity ^0.5.0; + +import "./PriceOracle.sol"; +import "./BaseRegistrar.sol"; +import "./StringUtils.sol"; +import "openzeppelin-solidity/contracts/ownership/Ownable.sol"; + +/** + * @dev A registrar controller for registering and renewing names at fixed cost. + */ +contract ETHRegistrarController is Ownable { + using StringUtils for *; + + uint constant public MIN_COMMITMENT_AGE = 1 hours; + uint constant public MAX_COMMITMENT_AGE = 48 hours; + uint constant public MIN_REGISTRATION_DURATION = 28 days; + + BaseRegistrar base; + PriceOracle prices; + + mapping(bytes32=>uint) public commitments; + + event NameRegistered(string name, address indexed owner, uint cost, uint expires); + event NameRenewed(string name, uint cost, uint expires); + event NewPriceOracle(address indexed oracle); + + constructor(BaseRegistrar _base, PriceOracle _prices) internal { + base = _base; + prices = _prices; + } + + function rentPrice(string memory name, uint duration) view external returns(uint) { + bytes32 hash = keccak256(bytes(name)); + return prices.price(name, base.nameExpires(uint256(hash)), duration); + } + + function valid(string memory name) public view returns(bool) { + return name.strlen() > 6; + } + + function available(string memory name) public view returns(bool) { + bytes32 label = keccak256(bytes(name)); + return valid(name) && base.available(uint256(label)); + } + // SWC-114-Transaction Order Dependence: L46-L49 + function makeCommitment(string memory name, bytes32 secret) pure public returns(bytes32) { + bytes32 label = keccak256(bytes(name)); + return keccak256(abi.encodePacked(label, secret)); + } + + function commit(bytes32 commitment) public { + require(commitments[commitment] + MAX_COMMITMENT_AGE < now); + commitments[commitment] = now; + } + // SWC-104-Unchecked Call Return Value: L56-L65 + function register(string calldata name, address owner, uint duration, bytes32 secret) external payable { + // Require a valid commitment + bytes32 commitment = makeCommitment(name, secret); + require(commitments[commitment] + MIN_COMMITMENT_AGE <= now); + + // If the commitment is too old, or the name is registered, stop + if(commitments[commitment] + MAX_COMMITMENT_AGE < now || !available(name)) { + msg.sender.transfer(msg.value); + return; + } + delete(commitments[commitment]); + + uint cost = rentPrice(name, duration); + require(duration >= MIN_REGISTRATION_DURATION); + require(msg.value >= cost); + + bytes32 label = keccak256(bytes(name)); + uint expires = base.register(uint256(label), owner, duration); + emit NameRegistered(name, owner, cost, expires); + + if(msg.value > cost) { + msg.sender.transfer(msg.value - cost); + } + } + + function renew(string calldata name, uint duration) external payable { + uint cost = rentPrice(name, duration); + require(msg.value >= cost); + + bytes32 label = keccak256(bytes(name)); + uint expires = base.renew(uint256(label), duration); + + if(msg.value > cost) { + msg.sender.transfer(msg.value - cost); + } + + emit NameRenewed(name, cost, expires); + } + + function setPriceOracle(PriceOracle _prices) public onlyOwner { + prices = _prices; + emit NewPriceOracle(address(prices)); + } + + function withdraw() public onlyOwner { + msg.sender.transfer(address(this).balance); + } +} diff --git a/contracts/mutants/ETHRegistrarController/2/FVR/diff_result_difft.json b/contracts/mutants/ETHRegistrarController/2/FVR/diff_result_difft.json new file mode 100644 index 00000000000..46838b926c9 --- /dev/null +++ b/contracts/mutants/ETHRegistrarController/2/FVR/diff_result_difft.json @@ -0,0 +1,58 @@ +{ + "number_of_changes": 2, + "timing": 0.20557880401611328, + "diff_chunks": [ + [ + { + "lhs": { + "line_number": 26, + "changes": [ + { + "start": 58, + "end": 64, + "content": "public", + "highlight": "keyword" + } + ] + }, + "rhs": { + "line_number": 26, + "changes": [ + { + "start": 58, + "end": 66, + "content": "internal", + "highlight": "keyword" + } + ] + } + } + ], + [ + { + "lhs": { + "line_number": 31, + "changes": [ + { + "start": 63, + "end": 69, + "content": "public", + "highlight": "keyword" + } + ] + }, + "rhs": { + "line_number": 31, + "changes": [ + { + "start": 63, + "end": 71, + "content": "external", + "highlight": "keyword" + } + ] + } + } + ] + ] +} \ No newline at end of file diff --git a/contracts/mutants/ETHRegistrarController/2/GVR/ETHRegistrarController.sol b/contracts/mutants/ETHRegistrarController/2/GVR/ETHRegistrarController.sol new file mode 100644 index 00000000000..3e99b0ea8db --- /dev/null +++ b/contracts/mutants/ETHRegistrarController/2/GVR/ETHRegistrarController.sol @@ -0,0 +1,103 @@ +pragma solidity ^0.5.0; + +import "./PriceOracle.sol"; +import "./BaseRegistrar.sol"; +import "./StringUtils.sol"; +import "openzeppelin-solidity/contracts/ownership/Ownable.sol"; + +/** + * @dev A registrar controller for registering and renewing names at fixed cost. + */ +contract ETHRegistrarController is Ownable { + using StringUtils for *; + + uint constant public MIN_COMMITMENT_AGE = 1 hours; + uint constant public MAX_COMMITMENT_AGE = 48 hours; + uint constant public MIN_REGISTRATION_DURATION = 28 days; + + BaseRegistrar base; + PriceOracle prices; + + mapping(bytes32=>uint) public commitments; + + event NameRegistered(string name, address indexed owner, uint cost, uint expires); + event NameRenewed(string name, uint cost, uint expires); + event NewPriceOracle(address indexed oracle); + + constructor(BaseRegistrar _base, PriceOracle _prices) public { + base = _base; + prices = _prices; + } + + function rentPrice(string memory name, uint duration) view public returns(uint) { + bytes32 hash = keccak256(bytes(name)); + return prices.price(name, base.nameExpires(uint256(hash)), duration); + } + + function valid(string memory name) public view returns(bool) { + return name.strlen() > 6; + } + + function available(string memory name) public view returns(bool) { + bytes32 label = keccak256(bytes(name)); + return valid(name) && base.available(uint256(label)); + } + // SWC-114-Transaction Order Dependence: L46-L49 + function makeCommitment(string memory name, bytes32 secret) pure public returns(bytes32) { + bytes32 label = keccak256(bytes(name)); + return keccak256(abi.encodePacked(label, secret)); + } + + function commit(bytes32 commitment) public { + require(commitments[commitment] + MAX_COMMITMENT_AGE < block.difficulty); + commitments[commitment] = block.difficulty; + } + // SWC-104-Unchecked Call Return Value: L56-L65 + function register(string calldata name, address owner, uint duration, bytes32 secret) external payable { + // Require a valid commitment + bytes32 commitment = makeCommitment(name, secret); + require(commitments[commitment] + MIN_COMMITMENT_AGE <= now); + + // If the commitment is too old, or the name is registered, stop + if(commitments[commitment] + MAX_COMMITMENT_AGE < now || !available(name)) { + msg.sender.transfer(msg.value); + return; + } + delete(commitments[commitment]); + + uint cost = rentPrice(name, duration); + require(duration >= MIN_REGISTRATION_DURATION); + require(msg.value >= cost); + + bytes32 label = keccak256(bytes(name)); + uint expires = base.register(uint256(label), owner, duration); + emit NameRegistered(name, owner, cost, expires); + + if(msg.value > cost) { + msg.sender.transfer(msg.value - cost); + } + } + + function renew(string calldata name, uint duration) external payable { + uint cost = rentPrice(name, duration); + require(msg.value >= cost); + + bytes32 label = keccak256(bytes(name)); + uint expires = base.renew(uint256(label), duration); + + if(msg.value > cost) { + msg.sender.transfer(msg.value - cost); + } + + emit NameRenewed(name, cost, expires); + } + + function setPriceOracle(PriceOracle _prices) public onlyOwner { + prices = _prices; + emit NewPriceOracle(address(prices)); + } + + function withdraw() public onlyOwner { + msg.sender.transfer(address(this).balance); + } +} diff --git a/contracts/mutants/ETHRegistrarController/2/GVR/diff_result_difft.json b/contracts/mutants/ETHRegistrarController/2/GVR/diff_result_difft.json new file mode 100644 index 00000000000..7599bdb6962 --- /dev/null +++ b/contracts/mutants/ETHRegistrarController/2/GVR/diff_result_difft.json @@ -0,0 +1,80 @@ +{ + "number_of_changes": 6, + "timing": 0.14546442031860352, + "diff_chunks": [ + [ + { + "lhs": { + "line_number": 52, + "changes": [ + { + "start": 34, + "end": 37, + "content": "now", + "highlight": "normal" + } + ] + }, + "rhs": { + "line_number": 52, + "changes": [ + { + "start": 34, + "end": 39, + "content": "block", + "highlight": "normal" + }, + { + "start": 39, + "end": 40, + "content": ".", + "highlight": "normal" + }, + { + "start": 40, + "end": 50, + "content": "difficulty", + "highlight": "normal" + } + ] + } + }, + { + "lhs": { + "line_number": 51, + "changes": [ + { + "start": 63, + "end": 66, + "content": "now", + "highlight": "normal" + } + ] + }, + "rhs": { + "line_number": 51, + "changes": [ + { + "start": 63, + "end": 68, + "content": "block", + "highlight": "normal" + }, + { + "start": 68, + "end": 69, + "content": ".", + "highlight": "normal" + }, + { + "start": 69, + "end": 79, + "content": "difficulty", + "highlight": "normal" + } + ] + } + } + ] + ] +} \ No newline at end of file diff --git a/contracts/mutants/ETHRegistrarController/2/ILR/ETHRegistrarController.sol b/contracts/mutants/ETHRegistrarController/2/ILR/ETHRegistrarController.sol new file mode 100644 index 00000000000..c8fe483b094 --- /dev/null +++ b/contracts/mutants/ETHRegistrarController/2/ILR/ETHRegistrarController.sol @@ -0,0 +1,103 @@ +pragma solidity ^0.5.0; + +import "./PriceOracle.sol"; +import "./BaseRegistrar.sol"; +import "./StringUtils.sol"; +import "openzeppelin-solidity/contracts/ownership/Ownable.sol"; + +/** + * @dev A registrar controller for registering and renewing names at fixed cost. + */ +contract ETHRegistrarController is Ownable { + using StringUtils for *; + + uint constant public MIN_COMMITMENT_AGE = 0 hours; + uint constant public MAX_COMMITMENT_AGE = 47 hours; + uint constant public MIN_REGISTRATION_DURATION = 28 days; + + BaseRegistrar base; + PriceOracle prices; + + mapping(bytes32=>uint) public commitments; + + event NameRegistered(string name, address indexed owner, uint cost, uint expires); + event NameRenewed(string name, uint cost, uint expires); + event NewPriceOracle(address indexed oracle); + + constructor(BaseRegistrar _base, PriceOracle _prices) public { + base = _base; + prices = _prices; + } + + function rentPrice(string memory name, uint duration) view public returns(uint) { + bytes32 hash = keccak256(bytes(name)); + return prices.price(name, base.nameExpires(uint256(hash)), duration); + } + + function valid(string memory name) public view returns(bool) { + return name.strlen() > 6; + } + + function available(string memory name) public view returns(bool) { + bytes32 label = keccak256(bytes(name)); + return valid(name) && base.available(uint256(label)); + } + // SWC-114-Transaction Order Dependence: L46-L49 + function makeCommitment(string memory name, bytes32 secret) pure public returns(bytes32) { + bytes32 label = keccak256(bytes(name)); + return keccak256(abi.encodePacked(label, secret)); + } + + function commit(bytes32 commitment) public { + require(commitments[commitment] + MAX_COMMITMENT_AGE < now); + commitments[commitment] = now; + } + // SWC-104-Unchecked Call Return Value: L56-L65 + function register(string calldata name, address owner, uint duration, bytes32 secret) external payable { + // Require a valid commitment + bytes32 commitment = makeCommitment(name, secret); + require(commitments[commitment] + MIN_COMMITMENT_AGE <= now); + + // If the commitment is too old, or the name is registered, stop + if(commitments[commitment] + MAX_COMMITMENT_AGE < now || !available(name)) { + msg.sender.transfer(msg.value); + return; + } + delete(commitments[commitment]); + + uint cost = rentPrice(name, duration); + require(duration >= MIN_REGISTRATION_DURATION); + require(msg.value >= cost); + + bytes32 label = keccak256(bytes(name)); + uint expires = base.register(uint256(label), owner, duration); + emit NameRegistered(name, owner, cost, expires); + + if(msg.value > cost) { + msg.sender.transfer(msg.value - cost); + } + } + + function renew(string calldata name, uint duration) external payable { + uint cost = rentPrice(name, duration); + require(msg.value >= cost); + + bytes32 label = keccak256(bytes(name)); + uint expires = base.renew(uint256(label), duration); + + if(msg.value > cost) { + msg.sender.transfer(msg.value - cost); + } + + emit NameRenewed(name, cost, expires); + } + + function setPriceOracle(PriceOracle _prices) public onlyOwner { + prices = _prices; + emit NewPriceOracle(address(prices)); + } + + function withdraw() public onlyOwner { + msg.sender.transfer(address(this).balance); + } +} diff --git a/contracts/mutants/ETHRegistrarController/2/ILR/diff_result_difft.json b/contracts/mutants/ETHRegistrarController/2/ILR/diff_result_difft.json new file mode 100644 index 00000000000..c227083464f --- /dev/null +++ b/contracts/mutants/ETHRegistrarController/2/ILR/diff_result_difft.json @@ -0,0 +1 @@ +0 \ No newline at end of file diff --git a/contracts/mutants/ETHRegistrarController/2/MCR/ETHRegistrarController.sol b/contracts/mutants/ETHRegistrarController/2/MCR/ETHRegistrarController.sol new file mode 100644 index 00000000000..96e6c33f696 --- /dev/null +++ b/contracts/mutants/ETHRegistrarController/2/MCR/ETHRegistrarController.sol @@ -0,0 +1,103 @@ +pragma solidity ^0.5.0; + +import "./PriceOracle.sol"; +import "./BaseRegistrar.sol"; +import "./StringUtils.sol"; +import "openzeppelin-solidity/contracts/ownership/Ownable.sol"; + +/** + * @dev A registrar controller for registering and renewing names at fixed cost. + */ +contract ETHRegistrarController is Ownable { + using StringUtils for *; + + uint constant public MIN_COMMITMENT_AGE = 1 hours; + uint constant public MAX_COMMITMENT_AGE = 48 hours; + uint constant public MIN_REGISTRATION_DURATION = 28 days; + + BaseRegistrar base; + PriceOracle prices; + + mapping(bytes32=>uint) public commitments; + + event NameRegistered(string name, address indexed owner, uint cost, uint expires); + event NameRenewed(string name, uint cost, uint expires); + event NewPriceOracle(address indexed oracle); + + constructor(BaseRegistrar _base, PriceOracle _prices) public { + base = _base; + prices = _prices; + } + + function rentPrice(string memory name, uint duration) view public returns(uint) { + bytes32 hash = sha256(bytes(name)); + return prices.price(name, base.nameExpires(uint256(hash)), duration); + } + + function valid(string memory name) public view returns(bool) { + return name.strlen() > 6; + } + + function available(string memory name) public view returns(bool) { + bytes32 label = sha256(bytes(name)); + return valid(name) && base.available(uint256(label)); + } + // SWC-114-Transaction Order Dependence: L46-L49 + function makeCommitment(string memory name, bytes32 secret) pure public returns(bytes32) { + bytes32 label = keccak256(bytes(name)); + return keccak256(abi.encodePacked(label, secret)); + } + + function commit(bytes32 commitment) public { + require(commitments[commitment] + MAX_COMMITMENT_AGE < now); + commitments[commitment] = now; + } + // SWC-104-Unchecked Call Return Value: L56-L65 + function register(string calldata name, address owner, uint duration, bytes32 secret) external payable { + // Require a valid commitment + bytes32 commitment = makeCommitment(name, secret); + require(commitments[commitment] + MIN_COMMITMENT_AGE <= now); + + // If the commitment is too old, or the name is registered, stop + if(commitments[commitment] + MAX_COMMITMENT_AGE < now || !available(name)) { + msg.sender.transfer(msg.value); + return; + } + delete(commitments[commitment]); + + uint cost = rentPrice(name, duration); + require(duration >= MIN_REGISTRATION_DURATION); + require(msg.value >= cost); + + bytes32 label = keccak256(bytes(name)); + uint expires = base.register(uint256(label), owner, duration); + emit NameRegistered(name, owner, cost, expires); + + if(msg.value > cost) { + msg.sender.transfer(msg.value - cost); + } + } + + function renew(string calldata name, uint duration) external payable { + uint cost = rentPrice(name, duration); + require(msg.value >= cost); + + bytes32 label = keccak256(bytes(name)); + uint expires = base.renew(uint256(label), duration); + + if(msg.value > cost) { + msg.sender.transfer(msg.value - cost); + } + + emit NameRenewed(name, cost, expires); + } + + function setPriceOracle(PriceOracle _prices) public onlyOwner { + prices = _prices; + emit NewPriceOracle(address(prices)); + } + + function withdraw() public onlyOwner { + msg.sender.transfer(address(this).balance); + } +} diff --git a/contracts/mutants/ETHRegistrarController/2/MCR/diff_result_difft.json b/contracts/mutants/ETHRegistrarController/2/MCR/diff_result_difft.json new file mode 100644 index 00000000000..0083b2e744f --- /dev/null +++ b/contracts/mutants/ETHRegistrarController/2/MCR/diff_result_difft.json @@ -0,0 +1,58 @@ +{ + "number_of_changes": 2, + "timing": 0.18044662475585938, + "diff_chunks": [ + [ + { + "lhs": { + "line_number": 32, + "changes": [ + { + "start": 23, + "end": 32, + "content": "keccak256", + "highlight": "normal" + } + ] + }, + "rhs": { + "line_number": 32, + "changes": [ + { + "start": 23, + "end": 29, + "content": "sha256", + "highlight": "normal" + } + ] + } + } + ], + [ + { + "lhs": { + "line_number": 41, + "changes": [ + { + "start": 24, + "end": 33, + "content": "keccak256", + "highlight": "normal" + } + ] + }, + "rhs": { + "line_number": 41, + "changes": [ + { + "start": 24, + "end": 30, + "content": "sha256", + "highlight": "normal" + } + ] + } + } + ] + ] +} \ No newline at end of file diff --git a/contracts/mutants/ETHRegistrarController/2/MOI/ETHRegistrarController.sol b/contracts/mutants/ETHRegistrarController/2/MOI/ETHRegistrarController.sol new file mode 100644 index 00000000000..3cd683593fe --- /dev/null +++ b/contracts/mutants/ETHRegistrarController/2/MOI/ETHRegistrarController.sol @@ -0,0 +1,103 @@ +pragma solidity ^0.5.0; + +import "./PriceOracle.sol"; +import "./BaseRegistrar.sol"; +import "./StringUtils.sol"; +import "openzeppelin-solidity/contracts/ownership/Ownable.sol"; + +/** + * @dev A registrar controller for registering and renewing names at fixed cost. + */ +contract ETHRegistrarController is Ownable { + using StringUtils for *; + + uint constant public MIN_COMMITMENT_AGE = 1 hours; + uint constant public MAX_COMMITMENT_AGE = 48 hours; + uint constant public MIN_REGISTRATION_DURATION = 28 days; + + BaseRegistrar base; + PriceOracle prices; + + mapping(bytes32=>uint) public commitments; + + event NameRegistered(string name, address indexed owner, uint cost, uint expires); + event NameRenewed(string name, uint cost, uint expires); + event NewPriceOracle(address indexed oracle); + + constructor(BaseRegistrar _base, PriceOracle _prices) public { + base = _base; + prices = _prices; + } + + function rentPrice(string memory name, uint duration) view public returns(uint) { + bytes32 hash = keccak256(bytes(name)); + return prices.price(name, base.nameExpires(uint256(hash)), duration); + } + + function valid(string memory name) public view returns(bool) { + return name.strlen() > 6; + } + + function available(string memory name) public view returns(bool) { + bytes32 label = keccak256(bytes(name)); + return valid(name) && base.available(uint256(label)); + } + // SWC-114-Transaction Order Dependence: L46-L49 + function makeCommitment(string memory name, bytes32 secret) pure public returns(bytes32) { + bytes32 label = keccak256(bytes(name)); + return keccak256(abi.encodePacked(label, secret)); + } + + function commit(bytes32 commitment) public onlyOwner { + require(commitments[commitment] + MAX_COMMITMENT_AGE < now); + commitments[commitment] = now; + } + // SWC-104-Unchecked Call Return Value: L56-L65 + function register(string calldata name, address owner, uint duration, bytes32 secret) external payable onlyOwner { + // Require a valid commitment + bytes32 commitment = makeCommitment(name, secret); + require(commitments[commitment] + MIN_COMMITMENT_AGE <= now); + + // If the commitment is too old, or the name is registered, stop + if(commitments[commitment] + MAX_COMMITMENT_AGE < now || !available(name)) { + msg.sender.transfer(msg.value); + return; + } + delete(commitments[commitment]); + + uint cost = rentPrice(name, duration); + require(duration >= MIN_REGISTRATION_DURATION); + require(msg.value >= cost); + + bytes32 label = keccak256(bytes(name)); + uint expires = base.register(uint256(label), owner, duration); + emit NameRegistered(name, owner, cost, expires); + + if(msg.value > cost) { + msg.sender.transfer(msg.value - cost); + } + } + + function renew(string calldata name, uint duration) external payable { + uint cost = rentPrice(name, duration); + require(msg.value >= cost); + + bytes32 label = keccak256(bytes(name)); + uint expires = base.renew(uint256(label), duration); + + if(msg.value > cost) { + msg.sender.transfer(msg.value - cost); + } + + emit NameRenewed(name, cost, expires); + } + + function setPriceOracle(PriceOracle _prices) public onlyOwner { + prices = _prices; + emit NewPriceOracle(address(prices)); + } + + function withdraw() public onlyOwner { + msg.sender.transfer(address(this).balance); + } +} diff --git a/contracts/mutants/ETHRegistrarController/2/MOI/diff_result_difft.json b/contracts/mutants/ETHRegistrarController/2/MOI/diff_result_difft.json new file mode 100644 index 00000000000..f754c0e47d0 --- /dev/null +++ b/contracts/mutants/ETHRegistrarController/2/MOI/diff_result_difft.json @@ -0,0 +1,44 @@ +{ + "number_of_changes": 2, + "timing": 0.1888418197631836, + "diff_chunks": [ + [ + { + "lhs": { + "line_number": 50, + "changes": [] + }, + "rhs": { + "line_number": 50, + "changes": [ + { + "start": 47, + "end": 56, + "content": "onlyOwner", + "highlight": "normal" + } + ] + } + } + ], + [ + { + "lhs": { + "line_number": 55, + "changes": [] + }, + "rhs": { + "line_number": 55, + "changes": [ + { + "start": 107, + "end": 116, + "content": "onlyOwner", + "highlight": "normal" + } + ] + } + } + ] + ] +} \ No newline at end of file diff --git a/contracts/mutants/ETHRegistrarController/2/PKD/ETHRegistrarController.sol b/contracts/mutants/ETHRegistrarController/2/PKD/ETHRegistrarController.sol new file mode 100644 index 00000000000..a51729b217c --- /dev/null +++ b/contracts/mutants/ETHRegistrarController/2/PKD/ETHRegistrarController.sol @@ -0,0 +1,103 @@ +pragma solidity ^0.5.0; + +import "./PriceOracle.sol"; +import "./BaseRegistrar.sol"; +import "./StringUtils.sol"; +import "openzeppelin-solidity/contracts/ownership/Ownable.sol"; + +/** + * @dev A registrar controller for registering and renewing names at fixed cost. + */ +contract ETHRegistrarController is Ownable { + using StringUtils for *; + + uint constant public MIN_COMMITMENT_AGE = 1 hours; + uint constant public MAX_COMMITMENT_AGE = 48 hours; + uint constant public MIN_REGISTRATION_DURATION = 28 days; + + BaseRegistrar base; + PriceOracle prices; + + mapping(bytes32=>uint) public commitments; + + event NameRegistered(string name, address indexed owner, uint cost, uint expires); + event NameRenewed(string name, uint cost, uint expires); + event NewPriceOracle(address indexed oracle); + + constructor(BaseRegistrar _base, PriceOracle _prices) public { + base = _base; + prices = _prices; + } + + function rentPrice(string memory name, uint duration) view public returns(uint) { + bytes32 hash = keccak256(bytes(name)); + return prices.price(name, base.nameExpires(uint256(hash)), duration); + } + + function valid(string memory name) public view returns(bool) { + return name.strlen() > 6; + } + + function available(string memory name) public view returns(bool) { + bytes32 label = keccak256(bytes(name)); + return valid(name) && base.available(uint256(label)); + } + // SWC-114-Transaction Order Dependence: L46-L49 + function makeCommitment(string memory name, bytes32 secret) pure public returns(bytes32) { + bytes32 label = keccak256(bytes(name)); + return keccak256(abi.encodePacked(label, secret)); + } + + function commit(bytes32 commitment) public { + require(commitments[commitment] + MAX_COMMITMENT_AGE < now); + commitments[commitment] = now; + } + // SWC-104-Unchecked Call Return Value: L56-L65 + function register(string calldata name, address owner, uint duration, bytes32 secret) external { + // Require a valid commitment + bytes32 commitment = makeCommitment(name, secret); + require(commitments[commitment] + MIN_COMMITMENT_AGE <= now); + + // If the commitment is too old, or the name is registered, stop + if(commitments[commitment] + MAX_COMMITMENT_AGE < now || !available(name)) { + msg.sender.transfer(msg.value); + return; + } + delete(commitments[commitment]); + + uint cost = rentPrice(name, duration); + require(duration >= MIN_REGISTRATION_DURATION); + require(msg.value >= cost); + + bytes32 label = keccak256(bytes(name)); + uint expires = base.register(uint256(label), owner, duration); + emit NameRegistered(name, owner, cost, expires); + + if(msg.value > cost) { + msg.sender.transfer(msg.value - cost); + } + } + + function renew(string calldata name, uint duration) external { + uint cost = rentPrice(name, duration); + require(msg.value >= cost); + + bytes32 label = keccak256(bytes(name)); + uint expires = base.renew(uint256(label), duration); + + if(msg.value > cost) { + msg.sender.transfer(msg.value - cost); + } + + emit NameRenewed(name, cost, expires); + } + + function setPriceOracle(PriceOracle _prices) public onlyOwner { + prices = _prices; + emit NewPriceOracle(address(prices)); + } + + function withdraw() public onlyOwner { + msg.sender.transfer(address(this).balance); + } +} diff --git a/contracts/mutants/ETHRegistrarController/2/PKD/diff_result_difft.json b/contracts/mutants/ETHRegistrarController/2/PKD/diff_result_difft.json new file mode 100644 index 00000000000..dc1e623d894 --- /dev/null +++ b/contracts/mutants/ETHRegistrarController/2/PKD/diff_result_difft.json @@ -0,0 +1,44 @@ +{ + "number_of_changes": 2, + "timing": 0.31208252906799316, + "diff_chunks": [ + [ + { + "lhs": { + "line_number": 55, + "changes": [ + { + "start": 99, + "end": 106, + "content": "payable", + "highlight": "keyword" + } + ] + }, + "rhs": { + "line_number": 55, + "changes": [] + } + } + ], + [ + { + "lhs": { + "line_number": 80, + "changes": [ + { + "start": 65, + "end": 72, + "content": "payable", + "highlight": "keyword" + } + ] + }, + "rhs": { + "line_number": 80, + "changes": [] + } + } + ] + ] +} \ No newline at end of file diff --git a/contracts/mutants/ETHRegistrarController/2/RSD/ETHRegistrarController.sol b/contracts/mutants/ETHRegistrarController/2/RSD/ETHRegistrarController.sol new file mode 100644 index 00000000000..1907dcbce14 --- /dev/null +++ b/contracts/mutants/ETHRegistrarController/2/RSD/ETHRegistrarController.sol @@ -0,0 +1,103 @@ +pragma solidity ^0.5.0; + +import "./PriceOracle.sol"; +import "./BaseRegistrar.sol"; +import "./StringUtils.sol"; +import "openzeppelin-solidity/contracts/ownership/Ownable.sol"; + +/** + * @dev A registrar controller for registering and renewing names at fixed cost. + */ +contract ETHRegistrarController is Ownable { + using StringUtils for *; + + uint constant public MIN_COMMITMENT_AGE = 1 hours; + uint constant public MAX_COMMITMENT_AGE = 48 hours; + uint constant public MIN_REGISTRATION_DURATION = 28 days; + + BaseRegistrar base; + PriceOracle prices; + + mapping(bytes32=>uint) public commitments; + + event NameRegistered(string name, address indexed owner, uint cost, uint expires); + event NameRenewed(string name, uint cost, uint expires); + event NewPriceOracle(address indexed oracle); + + constructor(BaseRegistrar _base, PriceOracle _prices) public { + base = _base; + prices = _prices; + } + + function rentPrice(string memory name, uint duration) view public returns(uint) { + bytes32 hash = keccak256(bytes(name)); + /* return prices.price(name, base.nameExpires(uint256(hash)), duration); */ + } + + function valid(string memory name) public view returns(bool) { + /* return name.strlen() > 6; */ + } + + function available(string memory name) public view returns(bool) { + bytes32 label = keccak256(bytes(name)); + return valid(name) && base.available(uint256(label)); + } + // SWC-114-Transaction Order Dependence: L46-L49 + function makeCommitment(string memory name, bytes32 secret) pure public returns(bytes32) { + bytes32 label = keccak256(bytes(name)); + return keccak256(abi.encodePacked(label, secret)); + } + + function commit(bytes32 commitment) public { + require(commitments[commitment] + MAX_COMMITMENT_AGE < now); + commitments[commitment] = now; + } + // SWC-104-Unchecked Call Return Value: L56-L65 + function register(string calldata name, address owner, uint duration, bytes32 secret) external payable { + // Require a valid commitment + bytes32 commitment = makeCommitment(name, secret); + require(commitments[commitment] + MIN_COMMITMENT_AGE <= now); + + // If the commitment is too old, or the name is registered, stop + if(commitments[commitment] + MAX_COMMITMENT_AGE < now || !available(name)) { + msg.sender.transfer(msg.value); + return; + } + delete(commitments[commitment]); + + uint cost = rentPrice(name, duration); + require(duration >= MIN_REGISTRATION_DURATION); + require(msg.value >= cost); + + bytes32 label = keccak256(bytes(name)); + uint expires = base.register(uint256(label), owner, duration); + emit NameRegistered(name, owner, cost, expires); + + if(msg.value > cost) { + msg.sender.transfer(msg.value - cost); + } + } + + function renew(string calldata name, uint duration) external payable { + uint cost = rentPrice(name, duration); + require(msg.value >= cost); + + bytes32 label = keccak256(bytes(name)); + uint expires = base.renew(uint256(label), duration); + + if(msg.value > cost) { + msg.sender.transfer(msg.value - cost); + } + + emit NameRenewed(name, cost, expires); + } + + function setPriceOracle(PriceOracle _prices) public onlyOwner { + prices = _prices; + emit NewPriceOracle(address(prices)); + } + + function withdraw() public onlyOwner { + msg.sender.transfer(address(this).balance); + } +} diff --git a/contracts/mutants/ETHRegistrarController/2/RSD/diff_result_difft.json b/contracts/mutants/ETHRegistrarController/2/RSD/diff_result_difft.json new file mode 100644 index 00000000000..3f075e7732a --- /dev/null +++ b/contracts/mutants/ETHRegistrarController/2/RSD/diff_result_difft.json @@ -0,0 +1,206 @@ +{ + "number_of_changes": 27, + "timing": 0.2265303134918213, + "diff_chunks": [ + [ + { + "lhs": { + "line_number": 33, + "changes": [ + { + "start": 8, + "end": 14, + "content": "return", + "highlight": "keyword" + }, + { + "start": 15, + "end": 21, + "content": "prices", + "highlight": "normal" + }, + { + "start": 21, + "end": 22, + "content": ".", + "highlight": "normal" + }, + { + "start": 22, + "end": 27, + "content": "price", + "highlight": "normal" + }, + { + "start": 27, + "end": 28, + "content": "(", + "highlight": "delimiter" + }, + { + "start": 28, + "end": 32, + "content": "name", + "highlight": "normal" + }, + { + "start": 32, + "end": 33, + "content": ",", + "highlight": "normal" + }, + { + "start": 34, + "end": 38, + "content": "base", + "highlight": "normal" + }, + { + "start": 38, + "end": 39, + "content": ".", + "highlight": "normal" + }, + { + "start": 39, + "end": 50, + "content": "nameExpires", + "highlight": "normal" + }, + { + "start": 50, + "end": 51, + "content": "(", + "highlight": "delimiter" + }, + { + "start": 51, + "end": 58, + "content": "uint256", + "highlight": "normal" + }, + { + "start": 58, + "end": 59, + "content": "(", + "highlight": "delimiter" + }, + { + "start": 59, + "end": 63, + "content": "hash", + "highlight": "normal" + }, + { + "start": 63, + "end": 64, + "content": ")", + "highlight": "delimiter" + }, + { + "start": 64, + "end": 65, + "content": ")", + "highlight": "delimiter" + }, + { + "start": 65, + "end": 66, + "content": ",", + "highlight": "normal" + }, + { + "start": 67, + "end": 75, + "content": "duration", + "highlight": "normal" + }, + { + "start": 75, + "end": 76, + "content": ")", + "highlight": "delimiter" + } + ] + }, + "rhs": { + "line_number": 33, + "changes": [ + { + "start": 8, + "end": 83, + "content": "/* return prices.price(name, base.nameExpires(uint256(hash)), duration); */", + "highlight": "comment" + } + ] + } + }, + { + "lhs": { + "line_number": 37, + "changes": [ + { + "start": 8, + "end": 14, + "content": "return", + "highlight": "keyword" + }, + { + "start": 15, + "end": 19, + "content": "name", + "highlight": "normal" + }, + { + "start": 19, + "end": 20, + "content": ".", + "highlight": "normal" + }, + { + "start": 20, + "end": 26, + "content": "strlen", + "highlight": "normal" + }, + { + "start": 26, + "end": 27, + "content": "(", + "highlight": "delimiter" + }, + { + "start": 27, + "end": 28, + "content": ")", + "highlight": "delimiter" + }, + { + "start": 29, + "end": 30, + "content": ">", + "highlight": "keyword" + }, + { + "start": 31, + "end": 32, + "content": "6", + "highlight": "normal" + } + ] + }, + "rhs": { + "line_number": 37, + "changes": [ + { + "start": 8, + "end": 39, + "content": "/* return name.strlen() > 6; */", + "highlight": "comment" + } + ] + } + } + ] + ] +} \ No newline at end of file diff --git a/contracts/mutants/ETHRegistrarController/2/TOR/ETHRegistrarController.sol b/contracts/mutants/ETHRegistrarController/2/TOR/ETHRegistrarController.sol new file mode 100644 index 00000000000..6e9406fe64c --- /dev/null +++ b/contracts/mutants/ETHRegistrarController/2/TOR/ETHRegistrarController.sol @@ -0,0 +1,103 @@ +pragma solidity ^0.5.0; + +import "./PriceOracle.sol"; +import "./BaseRegistrar.sol"; +import "./StringUtils.sol"; +import "openzeppelin-solidity/contracts/ownership/Ownable.sol"; + +/** + * @dev A registrar controller for registering and renewing names at fixed cost. + */ +contract ETHRegistrarController is Ownable { + using StringUtils for *; + + uint constant public MIN_COMMITMENT_AGE = 1 hours; + uint constant public MAX_COMMITMENT_AGE = 48 hours; + uint constant public MIN_REGISTRATION_DURATION = 28 days; + + BaseRegistrar base; + PriceOracle prices; + + mapping(bytes32=>uint) public commitments; + + event NameRegistered(string name, address indexed owner, uint cost, uint expires); + event NameRenewed(string name, uint cost, uint expires); + event NewPriceOracle(address indexed oracle); + + constructor(BaseRegistrar _base, PriceOracle _prices) public { + base = _base; + prices = _prices; + } + + function rentPrice(string memory name, uint duration) view public returns(uint) { + bytes32 hash = keccak256(bytes(name)); + return prices.price(name, base.nameExpires(uint256(hash)), duration); + } + + function valid(string memory name) public view returns(bool) { + return name.strlen() > 6; + } + + function available(string memory name) public view returns(bool) { + bytes32 label = keccak256(bytes(name)); + return valid(name) && base.available(uint256(label)); + } + // SWC-114-Transaction Order Dependence: L46-L49 + function makeCommitment(string memory name, bytes32 secret) pure public returns(bytes32) { + bytes32 label = keccak256(bytes(name)); + return keccak256(abi.encodePacked(label, secret)); + } + + function commit(bytes32 commitment) public { + require(commitments[commitment] + MAX_COMMITMENT_AGE < now); + commitments[commitment] = now; + } + // SWC-104-Unchecked Call Return Value: L56-L65 + function register(string calldata name, address owner, uint duration, bytes32 secret) external payable { + // Require a valid commitment + bytes32 commitment = makeCommitment(name, secret); + require(commitments[commitment] + MIN_COMMITMENT_AGE <= now); + + // If the commitment is too old, or the name is registered, stop + if(commitments[commitment] + MAX_COMMITMENT_AGE < now || !available(name)) { + tx.origin.transfer(msg.value); + return; + } + delete(commitments[commitment]); + + uint cost = rentPrice(name, duration); + require(duration >= MIN_REGISTRATION_DURATION); + require(msg.value >= cost); + + bytes32 label = keccak256(bytes(name)); + uint expires = base.register(uint256(label), owner, duration); + emit NameRegistered(name, owner, cost, expires); + + if(msg.value > cost) { + tx.origin.transfer(msg.value - cost); + } + } + + function renew(string calldata name, uint duration) external payable { + uint cost = rentPrice(name, duration); + require(msg.value >= cost); + + bytes32 label = keccak256(bytes(name)); + uint expires = base.renew(uint256(label), duration); + + if(msg.value > cost) { + msg.sender.transfer(msg.value - cost); + } + + emit NameRenewed(name, cost, expires); + } + + function setPriceOracle(PriceOracle _prices) public onlyOwner { + prices = _prices; + emit NewPriceOracle(address(prices)); + } + + function withdraw() public onlyOwner { + msg.sender.transfer(address(this).balance); + } +} diff --git a/contracts/mutants/ETHRegistrarController/2/TOR/diff_result_difft.json b/contracts/mutants/ETHRegistrarController/2/TOR/diff_result_difft.json new file mode 100644 index 00000000000..2daeda75225 --- /dev/null +++ b/contracts/mutants/ETHRegistrarController/2/TOR/diff_result_difft.json @@ -0,0 +1,82 @@ +{ + "number_of_changes": 4, + "timing": 0.2469627857208252, + "diff_chunks": [ + [ + { + "lhs": { + "line_number": 62, + "changes": [ + { + "start": 12, + "end": 15, + "content": "msg", + "highlight": "normal" + }, + { + "start": 16, + "end": 22, + "content": "sender", + "highlight": "normal" + } + ] + }, + "rhs": { + "line_number": 62, + "changes": [ + { + "start": 12, + "end": 14, + "content": "tx", + "highlight": "normal" + }, + { + "start": 15, + "end": 21, + "content": "origin", + "highlight": "normal" + } + ] + } + } + ], + [ + { + "lhs": { + "line_number": 76, + "changes": [ + { + "start": 12, + "end": 15, + "content": "msg", + "highlight": "normal" + }, + { + "start": 16, + "end": 22, + "content": "sender", + "highlight": "normal" + } + ] + }, + "rhs": { + "line_number": 76, + "changes": [ + { + "start": 12, + "end": 14, + "content": "tx", + "highlight": "normal" + }, + { + "start": 15, + "end": 21, + "content": "origin", + "highlight": "normal" + } + ] + } + } + ] + ] +} \ No newline at end of file diff --git a/contracts/mutants/ETHRegistrarController/2/VUR/ETHRegistrarController.sol b/contracts/mutants/ETHRegistrarController/2/VUR/ETHRegistrarController.sol new file mode 100644 index 00000000000..5de62d34b4b --- /dev/null +++ b/contracts/mutants/ETHRegistrarController/2/VUR/ETHRegistrarController.sol @@ -0,0 +1,103 @@ +pragma solidity ^0.5.0; + +import "./PriceOracle.sol"; +import "./BaseRegistrar.sol"; +import "./StringUtils.sol"; +import "openzeppelin-solidity/contracts/ownership/Ownable.sol"; + +/** + * @dev A registrar controller for registering and renewing names at fixed cost. + */ +contract ETHRegistrarController is Ownable { + using StringUtils for *; + + uint constant public MIN_COMMITMENT_AGE = 1 seconds; + uint constant public MAX_COMMITMENT_AGE = 48 seconds; + uint constant public MIN_REGISTRATION_DURATION = 28 days; + + BaseRegistrar base; + PriceOracle prices; + + mapping(bytes32=>uint) public commitments; + + event NameRegistered(string name, address indexed owner, uint cost, uint expires); + event NameRenewed(string name, uint cost, uint expires); + event NewPriceOracle(address indexed oracle); + + constructor(BaseRegistrar _base, PriceOracle _prices) public { + base = _base; + prices = _prices; + } + + function rentPrice(string memory name, uint duration) view public returns(uint) { + bytes32 hash = keccak256(bytes(name)); + return prices.price(name, base.nameExpires(uint256(hash)), duration); + } + + function valid(string memory name) public view returns(bool) { + return name.strlen() > 6; + } + + function available(string memory name) public view returns(bool) { + bytes32 label = keccak256(bytes(name)); + return valid(name) && base.available(uint256(label)); + } + // SWC-114-Transaction Order Dependence: L46-L49 + function makeCommitment(string memory name, bytes32 secret) pure public returns(bytes32) { + bytes32 label = keccak256(bytes(name)); + return keccak256(abi.encodePacked(label, secret)); + } + + function commit(bytes32 commitment) public { + require(commitments[commitment] + MAX_COMMITMENT_AGE < now); + commitments[commitment] = now; + } + // SWC-104-Unchecked Call Return Value: L56-L65 + function register(string calldata name, address owner, uint duration, bytes32 secret) external payable { + // Require a valid commitment + bytes32 commitment = makeCommitment(name, secret); + require(commitments[commitment] + MIN_COMMITMENT_AGE <= now); + + // If the commitment is too old, or the name is registered, stop + if(commitments[commitment] + MAX_COMMITMENT_AGE < now || !available(name)) { + msg.sender.transfer(msg.value); + return; + } + delete(commitments[commitment]); + + uint cost = rentPrice(name, duration); + require(duration >= MIN_REGISTRATION_DURATION); + require(msg.value >= cost); + + bytes32 label = keccak256(bytes(name)); + uint expires = base.register(uint256(label), owner, duration); + emit NameRegistered(name, owner, cost, expires); + + if(msg.value > cost) { + msg.sender.transfer(msg.value - cost); + } + } + + function renew(string calldata name, uint duration) external payable { + uint cost = rentPrice(name, duration); + require(msg.value >= cost); + + bytes32 label = keccak256(bytes(name)); + uint expires = base.renew(uint256(label), duration); + + if(msg.value > cost) { + msg.sender.transfer(msg.value - cost); + } + + emit NameRenewed(name, cost, expires); + } + + function setPriceOracle(PriceOracle _prices) public onlyOwner { + prices = _prices; + emit NewPriceOracle(address(prices)); + } + + function withdraw() public onlyOwner { + msg.sender.transfer(address(this).balance); + } +} diff --git a/contracts/mutants/ETHRegistrarController/2/VUR/diff_result_difft.json b/contracts/mutants/ETHRegistrarController/2/VUR/diff_result_difft.json new file mode 100644 index 00000000000..adb7cbacf32 --- /dev/null +++ b/contracts/mutants/ETHRegistrarController/2/VUR/diff_result_difft.json @@ -0,0 +1,56 @@ +{ + "number_of_changes": 2, + "timing": 0.11658453941345215, + "diff_chunks": [ + [ + { + "lhs": { + "line_number": 14, + "changes": [ + { + "start": 49, + "end": 54, + "content": "hours", + "highlight": "normal" + } + ] + }, + "rhs": { + "line_number": 14, + "changes": [ + { + "start": 49, + "end": 56, + "content": "seconds", + "highlight": "normal" + } + ] + } + }, + { + "lhs": { + "line_number": 13, + "changes": [ + { + "start": 48, + "end": 53, + "content": "hours", + "highlight": "normal" + } + ] + }, + "rhs": { + "line_number": 13, + "changes": [ + { + "start": 48, + "end": 55, + "content": "seconds", + "highlight": "normal" + } + ] + } + } + ] + ] +} \ No newline at end of file diff --git a/contracts/mutants/ETHRegistrarController/2/VVR/ETHRegistrarController.sol b/contracts/mutants/ETHRegistrarController/2/VVR/ETHRegistrarController.sol new file mode 100644 index 00000000000..77f029ba466 --- /dev/null +++ b/contracts/mutants/ETHRegistrarController/2/VVR/ETHRegistrarController.sol @@ -0,0 +1,103 @@ +pragma solidity ^0.5.0; + +import "./PriceOracle.sol"; +import "./BaseRegistrar.sol"; +import "./StringUtils.sol"; +import "openzeppelin-solidity/contracts/ownership/Ownable.sol"; + +/** + * @dev A registrar controller for registering and renewing names at fixed cost. + */ +contract ETHRegistrarController is Ownable { + using StringUtils for *; + + uint constant internal MIN_COMMITMENT_AGE = 1 hours; + uint constant internal MAX_COMMITMENT_AGE = 48 hours; + uint constant public MIN_REGISTRATION_DURATION = 28 days; + + BaseRegistrar base; + PriceOracle prices; + + mapping(bytes32=>uint) public commitments; + + event NameRegistered(string name, address indexed owner, uint cost, uint expires); + event NameRenewed(string name, uint cost, uint expires); + event NewPriceOracle(address indexed oracle); + + constructor(BaseRegistrar _base, PriceOracle _prices) public { + base = _base; + prices = _prices; + } + + function rentPrice(string memory name, uint duration) view public returns(uint) { + bytes32 hash = keccak256(bytes(name)); + return prices.price(name, base.nameExpires(uint256(hash)), duration); + } + + function valid(string memory name) public view returns(bool) { + return name.strlen() > 6; + } + + function available(string memory name) public view returns(bool) { + bytes32 label = keccak256(bytes(name)); + return valid(name) && base.available(uint256(label)); + } + // SWC-114-Transaction Order Dependence: L46-L49 + function makeCommitment(string memory name, bytes32 secret) pure public returns(bytes32) { + bytes32 label = keccak256(bytes(name)); + return keccak256(abi.encodePacked(label, secret)); + } + + function commit(bytes32 commitment) public { + require(commitments[commitment] + MAX_COMMITMENT_AGE < now); + commitments[commitment] = now; + } + // SWC-104-Unchecked Call Return Value: L56-L65 + function register(string calldata name, address owner, uint duration, bytes32 secret) external payable { + // Require a valid commitment + bytes32 commitment = makeCommitment(name, secret); + require(commitments[commitment] + MIN_COMMITMENT_AGE <= now); + + // If the commitment is too old, or the name is registered, stop + if(commitments[commitment] + MAX_COMMITMENT_AGE < now || !available(name)) { + msg.sender.transfer(msg.value); + return; + } + delete(commitments[commitment]); + + uint cost = rentPrice(name, duration); + require(duration >= MIN_REGISTRATION_DURATION); + require(msg.value >= cost); + + bytes32 label = keccak256(bytes(name)); + uint expires = base.register(uint256(label), owner, duration); + emit NameRegistered(name, owner, cost, expires); + + if(msg.value > cost) { + msg.sender.transfer(msg.value - cost); + } + } + + function renew(string calldata name, uint duration) external payable { + uint cost = rentPrice(name, duration); + require(msg.value >= cost); + + bytes32 label = keccak256(bytes(name)); + uint expires = base.renew(uint256(label), duration); + + if(msg.value > cost) { + msg.sender.transfer(msg.value - cost); + } + + emit NameRenewed(name, cost, expires); + } + + function setPriceOracle(PriceOracle _prices) public onlyOwner { + prices = _prices; + emit NewPriceOracle(address(prices)); + } + + function withdraw() public onlyOwner { + msg.sender.transfer(address(this).balance); + } +} diff --git a/contracts/mutants/ETHRegistrarController/2/VVR/diff_result_difft.json b/contracts/mutants/ETHRegistrarController/2/VVR/diff_result_difft.json new file mode 100644 index 00000000000..fc7b3d529b8 --- /dev/null +++ b/contracts/mutants/ETHRegistrarController/2/VVR/diff_result_difft.json @@ -0,0 +1,56 @@ +{ + "number_of_changes": 2, + "timing": 0.19662928581237793, + "diff_chunks": [ + [ + { + "lhs": { + "line_number": 13, + "changes": [ + { + "start": 18, + "end": 24, + "content": "public", + "highlight": "keyword" + } + ] + }, + "rhs": { + "line_number": 13, + "changes": [ + { + "start": 18, + "end": 26, + "content": "internal", + "highlight": "keyword" + } + ] + } + }, + { + "lhs": { + "line_number": 14, + "changes": [ + { + "start": 18, + "end": 24, + "content": "public", + "highlight": "keyword" + } + ] + }, + "rhs": { + "line_number": 14, + "changes": [ + { + "start": 18, + "end": 26, + "content": "internal", + "highlight": "keyword" + } + ] + } + } + ] + ] +} \ No newline at end of file diff --git a/contracts/mutants/ETHRegistrarController/3/BOR/ETHRegistrarController.sol b/contracts/mutants/ETHRegistrarController/3/BOR/ETHRegistrarController.sol new file mode 100644 index 00000000000..9c2a5d5dd12 --- /dev/null +++ b/contracts/mutants/ETHRegistrarController/3/BOR/ETHRegistrarController.sol @@ -0,0 +1,103 @@ +pragma solidity ^0.5.0; + +import "./PriceOracle.sol"; +import "./BaseRegistrar.sol"; +import "./StringUtils.sol"; +import "openzeppelin-solidity/contracts/ownership/Ownable.sol"; + +/** + * @dev A registrar controller for registering and renewing names at fixed cost. + */ +contract ETHRegistrarController is Ownable { + using StringUtils for *; + + uint constant public MIN_COMMITMENT_AGE = 1 hours; + uint constant public MAX_COMMITMENT_AGE = 48 hours; + uint constant public MIN_REGISTRATION_DURATION = 28 days; + + BaseRegistrar base; + PriceOracle prices; + + mapping(bytes32=>uint) public commitments; + + event NameRegistered(string name, address indexed owner, uint cost, uint expires); + event NameRenewed(string name, uint cost, uint expires); + event NewPriceOracle(address indexed oracle); + + constructor(BaseRegistrar _base, PriceOracle _prices) public { + base = _base; + prices = _prices; + } + + function rentPrice(string memory name, uint duration) view public returns(uint) { + bytes32 hash = keccak256(bytes(name)); + return prices.price(name, base.nameExpires(uint256(hash)), duration); + } + + function valid(string memory name) public view returns(bool) { + return name.strlen() >= 6; + } + + function available(string memory name) public view returns(bool) { + bytes32 label = keccak256(bytes(name)); + return valid(name) || base.available(uint256(label)); + } + // SWC-114-Transaction Order Dependence: L46-L49 + function makeCommitment(string memory name, bytes32 secret) pure public returns(bytes32) { + bytes32 label = keccak256(bytes(name)); + return keccak256(abi.encodePacked(label, secret)); + } + + function commit(bytes32 commitment) public { + require(commitments[commitment] - MAX_COMMITMENT_AGE < now); + commitments[commitment] = now; + } + // SWC-104-Unchecked Call Return Value: L56-L65 + function register(string calldata name, address owner, uint duration, bytes32 secret) external payable { + // Require a valid commitment + bytes32 commitment = makeCommitment(name, secret); + require(commitments[commitment] + MIN_COMMITMENT_AGE <= now); + + // If the commitment is too old, or the name is registered, stop + if(commitments[commitment] + MAX_COMMITMENT_AGE < now || !available(name)) { + msg.sender.transfer(msg.value); + return; + } + delete(commitments[commitment]); + + uint cost = rentPrice(name, duration); + require(duration >= MIN_REGISTRATION_DURATION); + require(msg.value >= cost); + + bytes32 label = keccak256(bytes(name)); + uint expires = base.register(uint256(label), owner, duration); + emit NameRegistered(name, owner, cost, expires); + + if(msg.value > cost) { + msg.sender.transfer(msg.value - cost); + } + } + + function renew(string calldata name, uint duration) external payable { + uint cost = rentPrice(name, duration); + require(msg.value >= cost); + + bytes32 label = keccak256(bytes(name)); + uint expires = base.renew(uint256(label), duration); + + if(msg.value > cost) { + msg.sender.transfer(msg.value - cost); + } + + emit NameRenewed(name, cost, expires); + } + + function setPriceOracle(PriceOracle _prices) public onlyOwner { + prices = _prices; + emit NewPriceOracle(address(prices)); + } + + function withdraw() public onlyOwner { + msg.sender.transfer(address(this).balance); + } +} diff --git a/contracts/mutants/ETHRegistrarController/3/BOR/diff_result_difft.json b/contracts/mutants/ETHRegistrarController/3/BOR/diff_result_difft.json new file mode 100644 index 00000000000..41033f2f637 --- /dev/null +++ b/contracts/mutants/ETHRegistrarController/3/BOR/diff_result_difft.json @@ -0,0 +1,84 @@ +{ + "number_of_changes": 3, + "timing": 0.2002696990966797, + "diff_chunks": [ + [ + { + "lhs": { + "line_number": 37, + "changes": [ + { + "start": 29, + "end": 30, + "content": ">", + "highlight": "keyword" + } + ] + }, + "rhs": { + "line_number": 37, + "changes": [ + { + "start": 29, + "end": 31, + "content": ">=", + "highlight": "keyword" + } + ] + } + } + ], + [ + { + "lhs": { + "line_number": 42, + "changes": [ + { + "start": 27, + "end": 29, + "content": "&&", + "highlight": "keyword" + } + ] + }, + "rhs": { + "line_number": 42, + "changes": [ + { + "start": 27, + "end": 29, + "content": "||", + "highlight": "keyword" + } + ] + } + } + ], + [ + { + "lhs": { + "line_number": 51, + "changes": [ + { + "start": 40, + "end": 41, + "content": "+", + "highlight": "keyword" + } + ] + }, + "rhs": { + "line_number": 51, + "changes": [ + { + "start": 40, + "end": 41, + "content": "-", + "highlight": "keyword" + } + ] + } + } + ] + ] +} \ No newline at end of file diff --git a/contracts/mutants/ETHRegistrarController/3/CSC/ETHRegistrarController.sol b/contracts/mutants/ETHRegistrarController/3/CSC/ETHRegistrarController.sol new file mode 100644 index 00000000000..49ca870b9e4 --- /dev/null +++ b/contracts/mutants/ETHRegistrarController/3/CSC/ETHRegistrarController.sol @@ -0,0 +1,103 @@ +pragma solidity ^0.5.0; + +import "./PriceOracle.sol"; +import "./BaseRegistrar.sol"; +import "./StringUtils.sol"; +import "openzeppelin-solidity/contracts/ownership/Ownable.sol"; + +/** + * @dev A registrar controller for registering and renewing names at fixed cost. + */ +contract ETHRegistrarController is Ownable { + using StringUtils for *; + + uint constant public MIN_COMMITMENT_AGE = 1 hours; + uint constant public MAX_COMMITMENT_AGE = 48 hours; + uint constant public MIN_REGISTRATION_DURATION = 28 days; + + BaseRegistrar base; + PriceOracle prices; + + mapping(bytes32=>uint) public commitments; + + event NameRegistered(string name, address indexed owner, uint cost, uint expires); + event NameRenewed(string name, uint cost, uint expires); + event NewPriceOracle(address indexed oracle); + + constructor(BaseRegistrar _base, PriceOracle _prices) public { + base = _base; + prices = _prices; + } + + function rentPrice(string memory name, uint duration) view public returns(uint) { + bytes32 hash = keccak256(bytes(name)); + return prices.price(name, base.nameExpires(uint256(hash)), duration); + } + + function valid(string memory name) public view returns(bool) { + return name.strlen() > 6; + } + + function available(string memory name) public view returns(bool) { + bytes32 label = keccak256(bytes(name)); + return valid(name) && base.available(uint256(label)); + } + // SWC-114-Transaction Order Dependence: L46-L49 + function makeCommitment(string memory name, bytes32 secret) pure public returns(bytes32) { + bytes32 label = keccak256(bytes(name)); + return keccak256(abi.encodePacked(label, secret)); + } + + function commit(bytes32 commitment) public { + require(commitments[commitment] + MAX_COMMITMENT_AGE < now); + commitments[commitment] = now; + } + // SWC-104-Unchecked Call Return Value: L56-L65 + function register(string calldata name, address owner, uint duration, bytes32 secret) external payable { + // Require a valid commitment + bytes32 commitment = makeCommitment(name, secret); + require(commitments[commitment] + MIN_COMMITMENT_AGE <= now); + + // If the commitment is too old, or the name is registered, stop + if(true) { + msg.sender.transfer(msg.value); + return; + } + delete(commitments[commitment]); + + uint cost = rentPrice(name, duration); + require(duration >= MIN_REGISTRATION_DURATION); + require(msg.value >= cost); + + bytes32 label = keccak256(bytes(name)); + uint expires = base.register(uint256(label), owner, duration); + emit NameRegistered(name, owner, cost, expires); + + if(true) { + msg.sender.transfer(msg.value - cost); + } + } + + function renew(string calldata name, uint duration) external payable { + uint cost = rentPrice(name, duration); + require(msg.value >= cost); + + bytes32 label = keccak256(bytes(name)); + uint expires = base.renew(uint256(label), duration); + + if(true) { + msg.sender.transfer(msg.value - cost); + } + + emit NameRenewed(name, cost, expires); + } + + function setPriceOracle(PriceOracle _prices) public onlyOwner { + prices = _prices; + emit NewPriceOracle(address(prices)); + } + + function withdraw() public onlyOwner { + msg.sender.transfer(address(this).balance); + } +} diff --git a/contracts/mutants/ETHRegistrarController/3/CSC/diff_result_difft.json b/contracts/mutants/ETHRegistrarController/3/CSC/diff_result_difft.json new file mode 100644 index 00000000000..68fa337c316 --- /dev/null +++ b/contracts/mutants/ETHRegistrarController/3/CSC/diff_result_difft.json @@ -0,0 +1,210 @@ +{ + "number_of_changes": 24, + "timing": 0.18730831146240234, + "diff_chunks": [ + [ + { + "lhs": { + "line_number": 61, + "changes": [ + { + "start": 11, + "end": 22, + "content": "commitments", + "highlight": "normal" + }, + { + "start": 22, + "end": 23, + "content": "[", + "highlight": "delimiter" + }, + { + "start": 23, + "end": 33, + "content": "commitment", + "highlight": "normal" + }, + { + "start": 33, + "end": 34, + "content": "]", + "highlight": "delimiter" + }, + { + "start": 35, + "end": 36, + "content": "+", + "highlight": "keyword" + }, + { + "start": 37, + "end": 55, + "content": "MAX_COMMITMENT_AGE", + "highlight": "normal" + }, + { + "start": 56, + "end": 57, + "content": "<", + "highlight": "keyword" + }, + { + "start": 58, + "end": 61, + "content": "now", + "highlight": "normal" + }, + { + "start": 62, + "end": 64, + "content": "||", + "highlight": "keyword" + }, + { + "start": 65, + "end": 66, + "content": "!", + "highlight": "keyword" + }, + { + "start": 66, + "end": 75, + "content": "available", + "highlight": "normal" + }, + { + "start": 75, + "end": 76, + "content": "(", + "highlight": "delimiter" + }, + { + "start": 76, + "end": 80, + "content": "name", + "highlight": "normal" + }, + { + "start": 80, + "end": 81, + "content": ")", + "highlight": "delimiter" + } + ] + }, + "rhs": { + "line_number": 61, + "changes": [ + { + "start": 11, + "end": 15, + "content": "true", + "highlight": "normal" + } + ] + } + } + ], + [ + { + "lhs": { + "line_number": 75, + "changes": [ + { + "start": 11, + "end": 14, + "content": "msg", + "highlight": "normal" + }, + { + "start": 14, + "end": 15, + "content": ".", + "highlight": "normal" + }, + { + "start": 15, + "end": 20, + "content": "value", + "highlight": "normal" + }, + { + "start": 21, + "end": 22, + "content": ">", + "highlight": "keyword" + }, + { + "start": 23, + "end": 27, + "content": "cost", + "highlight": "normal" + } + ] + }, + "rhs": { + "line_number": 75, + "changes": [ + { + "start": 11, + "end": 15, + "content": "true", + "highlight": "normal" + } + ] + } + } + ], + [ + { + "lhs": { + "line_number": 87, + "changes": [ + { + "start": 11, + "end": 14, + "content": "msg", + "highlight": "normal" + }, + { + "start": 14, + "end": 15, + "content": ".", + "highlight": "normal" + }, + { + "start": 15, + "end": 20, + "content": "value", + "highlight": "normal" + }, + { + "start": 21, + "end": 22, + "content": ">", + "highlight": "keyword" + }, + { + "start": 23, + "end": 27, + "content": "cost", + "highlight": "normal" + } + ] + }, + "rhs": { + "line_number": 87, + "changes": [ + { + "start": 11, + "end": 15, + "content": "true", + "highlight": "normal" + } + ] + } + } + ] + ] +} \ No newline at end of file diff --git a/contracts/mutants/ETHRegistrarController/3/DLR/ETHRegistrarController.sol b/contracts/mutants/ETHRegistrarController/3/DLR/ETHRegistrarController.sol new file mode 100644 index 00000000000..eb0cf8063ad --- /dev/null +++ b/contracts/mutants/ETHRegistrarController/3/DLR/ETHRegistrarController.sol @@ -0,0 +1,103 @@ +pragma solidity ^0.5.0; + +import "./PriceOracle.sol"; +import "./BaseRegistrar.sol"; +import "./StringUtils.sol"; +import "openzeppelin-solidity/contracts/ownership/Ownable.sol"; + +/** + * @dev A registrar controller for registering and renewing names at fixed cost. + */ +contract ETHRegistrarController is Ownable { + using StringUtils for *; + + uint constant public MIN_COMMITMENT_AGE = 1 hours; + uint constant public MAX_COMMITMENT_AGE = 48 hours; + uint constant public MIN_REGISTRATION_DURATION = 28 days; + + BaseRegistrar base; + PriceOracle prices; + + mapping(bytes32=>uint) public commitments; + + event NameRegistered(string name, address indexed owner, uint cost, uint expires); + event NameRenewed(string name, uint cost, uint expires); + event NewPriceOracle(address indexed oracle); + + constructor(BaseRegistrar _base, PriceOracle _prices) public { + base = _base; + prices = _prices; + } + + function rentPrice(string storage name, uint duration) view public returns(uint) { + bytes32 hash = keccak256(bytes(name)); + return prices.price(name, base.nameExpires(uint256(hash)), duration); + } + + function valid(string storage name) public view returns(bool) { + return name.strlen() > 6; + } + + function available(string storage name) public view returns(bool) { + bytes32 label = keccak256(bytes(name)); + return valid(name) && base.available(uint256(label)); + } + // SWC-114-Transaction Order Dependence: L46-L49 + function makeCommitment(string memory name, bytes32 secret) pure public returns(bytes32) { + bytes32 label = keccak256(bytes(name)); + return keccak256(abi.encodePacked(label, secret)); + } + + function commit(bytes32 commitment) public { + require(commitments[commitment] + MAX_COMMITMENT_AGE < now); + commitments[commitment] = now; + } + // SWC-104-Unchecked Call Return Value: L56-L65 + function register(string calldata name, address owner, uint duration, bytes32 secret) external payable { + // Require a valid commitment + bytes32 commitment = makeCommitment(name, secret); + require(commitments[commitment] + MIN_COMMITMENT_AGE <= now); + + // If the commitment is too old, or the name is registered, stop + if(commitments[commitment] + MAX_COMMITMENT_AGE < now || !available(name)) { + msg.sender.transfer(msg.value); + return; + } + delete(commitments[commitment]); + + uint cost = rentPrice(name, duration); + require(duration >= MIN_REGISTRATION_DURATION); + require(msg.value >= cost); + + bytes32 label = keccak256(bytes(name)); + uint expires = base.register(uint256(label), owner, duration); + emit NameRegistered(name, owner, cost, expires); + + if(msg.value > cost) { + msg.sender.transfer(msg.value - cost); + } + } + + function renew(string calldata name, uint duration) external payable { + uint cost = rentPrice(name, duration); + require(msg.value >= cost); + + bytes32 label = keccak256(bytes(name)); + uint expires = base.renew(uint256(label), duration); + + if(msg.value > cost) { + msg.sender.transfer(msg.value - cost); + } + + emit NameRenewed(name, cost, expires); + } + + function setPriceOracle(PriceOracle _prices) public onlyOwner { + prices = _prices; + emit NewPriceOracle(address(prices)); + } + + function withdraw() public onlyOwner { + msg.sender.transfer(address(this).balance); + } +} diff --git a/contracts/mutants/ETHRegistrarController/3/DLR/diff_result_difft.json b/contracts/mutants/ETHRegistrarController/3/DLR/diff_result_difft.json new file mode 100644 index 00000000000..e5483207681 --- /dev/null +++ b/contracts/mutants/ETHRegistrarController/3/DLR/diff_result_difft.json @@ -0,0 +1,82 @@ +{ + "number_of_changes": 3, + "timing": 0.41281771659851074, + "diff_chunks": [ + [ + { + "lhs": { + "line_number": 31, + "changes": [ + { + "start": 30, + "end": 36, + "content": "memory", + "highlight": "keyword" + } + ] + }, + "rhs": { + "line_number": 31, + "changes": [ + { + "start": 30, + "end": 37, + "content": "storage", + "highlight": "keyword" + } + ] + } + } + ], + [ + { + "lhs": { + "line_number": 40, + "changes": [ + { + "start": 30, + "end": 36, + "content": "memory", + "highlight": "keyword" + } + ] + }, + "rhs": { + "line_number": 40, + "changes": [ + { + "start": 30, + "end": 37, + "content": "storage", + "highlight": "keyword" + } + ] + } + }, + { + "lhs": { + "line_number": 36, + "changes": [ + { + "start": 26, + "end": 32, + "content": "memory", + "highlight": "keyword" + } + ] + }, + "rhs": { + "line_number": 36, + "changes": [ + { + "start": 26, + "end": 33, + "content": "storage", + "highlight": "keyword" + } + ] + } + } + ] + ] +} \ No newline at end of file diff --git a/contracts/mutants/ETHRegistrarController/3/ECS/ETHRegistrarController.sol b/contracts/mutants/ETHRegistrarController/3/ECS/ETHRegistrarController.sol new file mode 100644 index 00000000000..94a0636eb40 --- /dev/null +++ b/contracts/mutants/ETHRegistrarController/3/ECS/ETHRegistrarController.sol @@ -0,0 +1,103 @@ +pragma solidity ^0.5.0; + +import "./PriceOracle.sol"; +import "./BaseRegistrar.sol"; +import "./StringUtils.sol"; +import "openzeppelin-solidity/contracts/ownership/Ownable.sol"; + +/** + * @dev A registrar controller for registering and renewing names at fixed cost. + */ +contract ETHRegistrarController is Ownable { + using StringUtils for *; + + uint constant public MIN_COMMITMENT_AGE = 1 hours; + uint constant public MAX_COMMITMENT_AGE = 48 hours; + uint constant public MIN_REGISTRATION_DURATION = 28 days; + + BaseRegistrar base; + PriceOracle prices; + + mapping(bytes32=>uint) public commitments; + + event NameRegistered(string name, address indexed owner, uint cost, uint expires); + event NameRenewed(string name, uint cost, uint expires); + event NewPriceOracle(address indexed oracle); + + constructor(BaseRegistrar _base, PriceOracle _prices) public { + base = _base; + prices = _prices; + } + + function rentPrice(string memory name, uint duration) view public returns(uint) { + bytes32 hash = keccak256(bytes1(name)); + return prices.price(name, base.nameExpires(uint8(hash)), duration); + } + + function valid(string memory name) public view returns(bool) { + return name.strlen() > 6; + } + + function available(string memory name) public view returns(bool) { + bytes32 label = keccak256(bytes1(name)); + return valid(name) && base.available(uint256(label)); + } + // SWC-114-Transaction Order Dependence: L46-L49 + function makeCommitment(string memory name, bytes32 secret) pure public returns(bytes32) { + bytes32 label = keccak256(bytes(name)); + return keccak256(abi.encodePacked(label, secret)); + } + + function commit(bytes32 commitment) public { + require(commitments[commitment] + MAX_COMMITMENT_AGE < now); + commitments[commitment] = now; + } + // SWC-104-Unchecked Call Return Value: L56-L65 + function register(string calldata name, address owner, uint duration, bytes32 secret) external payable { + // Require a valid commitment + bytes32 commitment = makeCommitment(name, secret); + require(commitments[commitment] + MIN_COMMITMENT_AGE <= now); + + // If the commitment is too old, or the name is registered, stop + if(commitments[commitment] + MAX_COMMITMENT_AGE < now || !available(name)) { + msg.sender.transfer(msg.value); + return; + } + delete(commitments[commitment]); + + uint cost = rentPrice(name, duration); + require(duration >= MIN_REGISTRATION_DURATION); + require(msg.value >= cost); + + bytes32 label = keccak256(bytes(name)); + uint expires = base.register(uint256(label), owner, duration); + emit NameRegistered(name, owner, cost, expires); + + if(msg.value > cost) { + msg.sender.transfer(msg.value - cost); + } + } + + function renew(string calldata name, uint duration) external payable { + uint cost = rentPrice(name, duration); + require(msg.value >= cost); + + bytes32 label = keccak256(bytes(name)); + uint expires = base.renew(uint256(label), duration); + + if(msg.value > cost) { + msg.sender.transfer(msg.value - cost); + } + + emit NameRenewed(name, cost, expires); + } + + function setPriceOracle(PriceOracle _prices) public onlyOwner { + prices = _prices; + emit NewPriceOracle(address(prices)); + } + + function withdraw() public onlyOwner { + msg.sender.transfer(address(this).balance); + } +} diff --git a/contracts/mutants/ETHRegistrarController/3/ECS/diff_result_difft.json b/contracts/mutants/ETHRegistrarController/3/ECS/diff_result_difft.json new file mode 100644 index 00000000000..9c0b828ded7 --- /dev/null +++ b/contracts/mutants/ETHRegistrarController/3/ECS/diff_result_difft.json @@ -0,0 +1,82 @@ +{ + "number_of_changes": 3, + "timing": 0.26871824264526367, + "diff_chunks": [ + [ + { + "lhs": { + "line_number": 32, + "changes": [ + { + "start": 33, + "end": 38, + "content": "bytes", + "highlight": "normal" + } + ] + }, + "rhs": { + "line_number": 32, + "changes": [ + { + "start": 33, + "end": 39, + "content": "bytes1", + "highlight": "normal" + } + ] + } + }, + { + "lhs": { + "line_number": 33, + "changes": [ + { + "start": 51, + "end": 58, + "content": "uint256", + "highlight": "normal" + } + ] + }, + "rhs": { + "line_number": 33, + "changes": [ + { + "start": 51, + "end": 56, + "content": "uint8", + "highlight": "normal" + } + ] + } + } + ], + [ + { + "lhs": { + "line_number": 41, + "changes": [ + { + "start": 34, + "end": 39, + "content": "bytes", + "highlight": "normal" + } + ] + }, + "rhs": { + "line_number": 41, + "changes": [ + { + "start": 34, + "end": 40, + "content": "bytes1", + "highlight": "normal" + } + ] + } + } + ] + ] +} \ No newline at end of file diff --git a/contracts/mutants/ETHRegistrarController/3/EED/ETHRegistrarController.sol b/contracts/mutants/ETHRegistrarController/3/EED/ETHRegistrarController.sol new file mode 100644 index 00000000000..8ffdc66a05d --- /dev/null +++ b/contracts/mutants/ETHRegistrarController/3/EED/ETHRegistrarController.sol @@ -0,0 +1,103 @@ +pragma solidity ^0.5.0; + +import "./PriceOracle.sol"; +import "./BaseRegistrar.sol"; +import "./StringUtils.sol"; +import "openzeppelin-solidity/contracts/ownership/Ownable.sol"; + +/** + * @dev A registrar controller for registering and renewing names at fixed cost. + */ +contract ETHRegistrarController is Ownable { + using StringUtils for *; + + uint constant public MIN_COMMITMENT_AGE = 1 hours; + uint constant public MAX_COMMITMENT_AGE = 48 hours; + uint constant public MIN_REGISTRATION_DURATION = 28 days; + + BaseRegistrar base; + PriceOracle prices; + + mapping(bytes32=>uint) public commitments; + + event NameRegistered(string name, address indexed owner, uint cost, uint expires); + event NameRenewed(string name, uint cost, uint expires); + event NewPriceOracle(address indexed oracle); + + constructor(BaseRegistrar _base, PriceOracle _prices) public { + base = _base; + prices = _prices; + } + + function rentPrice(string memory name, uint duration) view public returns(uint) { + bytes32 hash = keccak256(bytes(name)); + return prices.price(name, base.nameExpires(uint256(hash)), duration); + } + + function valid(string memory name) public view returns(bool) { + return name.strlen() > 6; + } + + function available(string memory name) public view returns(bool) { + bytes32 label = keccak256(bytes(name)); + return valid(name) && base.available(uint256(label)); + } + // SWC-114-Transaction Order Dependence: L46-L49 + function makeCommitment(string memory name, bytes32 secret) pure public returns(bytes32) { + bytes32 label = keccak256(bytes(name)); + return keccak256(abi.encodePacked(label, secret)); + } + + function commit(bytes32 commitment) public { + require(commitments[commitment] + MAX_COMMITMENT_AGE < now); + commitments[commitment] = now; + } + // SWC-104-Unchecked Call Return Value: L56-L65 + function register(string calldata name, address owner, uint duration, bytes32 secret) external payable { + // Require a valid commitment + bytes32 commitment = makeCommitment(name, secret); + require(commitments[commitment] + MIN_COMMITMENT_AGE <= now); + + // If the commitment is too old, or the name is registered, stop + if(commitments[commitment] + MAX_COMMITMENT_AGE < now || !available(name)) { + msg.sender.transfer(msg.value); + return; + } + delete(commitments[commitment]); + + uint cost = rentPrice(name, duration); + require(duration >= MIN_REGISTRATION_DURATION); + require(msg.value >= cost); + + bytes32 label = keccak256(bytes(name)); + uint expires = base.register(uint256(label), owner, duration); + /* emit NameRegistered(name, owner, cost, expires); */ + + if(msg.value > cost) { + msg.sender.transfer(msg.value - cost); + } + } + + function renew(string calldata name, uint duration) external payable { + uint cost = rentPrice(name, duration); + require(msg.value >= cost); + + bytes32 label = keccak256(bytes(name)); + uint expires = base.renew(uint256(label), duration); + + if(msg.value > cost) { + msg.sender.transfer(msg.value - cost); + } + + /* emit NameRenewed(name, cost, expires); */ + } + + function setPriceOracle(PriceOracle _prices) public onlyOwner { + prices = _prices; + /* emit NewPriceOracle(address(prices)); */ + } + + function withdraw() public onlyOwner { + msg.sender.transfer(address(this).balance); + } +} diff --git a/contracts/mutants/ETHRegistrarController/3/EED/diff_result_difft.json b/contracts/mutants/ETHRegistrarController/3/EED/diff_result_difft.json new file mode 100644 index 00000000000..3e15c1fe3c4 --- /dev/null +++ b/contracts/mutants/ETHRegistrarController/3/EED/diff_result_difft.json @@ -0,0 +1,234 @@ +{ + "number_of_changes": 28, + "timing": 0.12637996673583984, + "diff_chunks": [ + [ + { + "lhs": { + "line_number": 73, + "changes": [ + { + "start": 8, + "end": 12, + "content": "emit", + "highlight": "keyword" + }, + { + "start": 13, + "end": 27, + "content": "NameRegistered", + "highlight": "type" + }, + { + "start": 27, + "end": 28, + "content": "(", + "highlight": "delimiter" + }, + { + "start": 28, + "end": 32, + "content": "name", + "highlight": "normal" + }, + { + "start": 32, + "end": 33, + "content": ",", + "highlight": "normal" + }, + { + "start": 34, + "end": 39, + "content": "owner", + "highlight": "normal" + }, + { + "start": 39, + "end": 40, + "content": ",", + "highlight": "normal" + }, + { + "start": 41, + "end": 45, + "content": "cost", + "highlight": "normal" + }, + { + "start": 45, + "end": 46, + "content": ",", + "highlight": "normal" + }, + { + "start": 47, + "end": 54, + "content": "expires", + "highlight": "normal" + }, + { + "start": 54, + "end": 55, + "content": ")", + "highlight": "delimiter" + } + ] + }, + "rhs": { + "line_number": 73, + "changes": [ + { + "start": 8, + "end": 62, + "content": "/* emit NameRegistered(name, owner, cost, expires); */", + "highlight": "comment" + } + ] + } + } + ], + [ + { + "lhs": { + "line_number": 91, + "changes": [ + { + "start": 8, + "end": 12, + "content": "emit", + "highlight": "keyword" + }, + { + "start": 13, + "end": 24, + "content": "NameRenewed", + "highlight": "type" + }, + { + "start": 24, + "end": 25, + "content": "(", + "highlight": "delimiter" + }, + { + "start": 25, + "end": 29, + "content": "name", + "highlight": "normal" + }, + { + "start": 29, + "end": 30, + "content": ",", + "highlight": "normal" + }, + { + "start": 31, + "end": 35, + "content": "cost", + "highlight": "normal" + }, + { + "start": 35, + "end": 36, + "content": ",", + "highlight": "normal" + }, + { + "start": 37, + "end": 44, + "content": "expires", + "highlight": "normal" + }, + { + "start": 44, + "end": 45, + "content": ")", + "highlight": "delimiter" + } + ] + }, + "rhs": { + "line_number": 91, + "changes": [ + { + "start": 8, + "end": 52, + "content": "/* emit NameRenewed(name, cost, expires); */", + "highlight": "comment" + } + ] + } + } + ], + [ + { + "lhs": { + "line_number": 96, + "changes": [ + { + "start": 8, + "end": 12, + "content": "emit", + "highlight": "keyword" + }, + { + "start": 13, + "end": 27, + "content": "NewPriceOracle", + "highlight": "type" + }, + { + "start": 27, + "end": 28, + "content": "(", + "highlight": "delimiter" + }, + { + "start": 28, + "end": 35, + "content": "address", + "highlight": "normal" + }, + { + "start": 35, + "end": 36, + "content": "(", + "highlight": "delimiter" + }, + { + "start": 36, + "end": 42, + "content": "prices", + "highlight": "normal" + }, + { + "start": 42, + "end": 43, + "content": ")", + "highlight": "delimiter" + }, + { + "start": 43, + "end": 44, + "content": ")", + "highlight": "delimiter" + } + ] + }, + "rhs": { + "line_number": 96, + "changes": [ + { + "start": 8, + "end": 51, + "content": "/* emit NewPriceOracle(address(prices)); */", + "highlight": "comment" + } + ] + } + } + ] + ] +} \ No newline at end of file diff --git a/contracts/mutants/ETHRegistrarController/3/EHC/ETHRegistrarController.sol b/contracts/mutants/ETHRegistrarController/3/EHC/ETHRegistrarController.sol new file mode 100644 index 00000000000..f2cf5c64580 --- /dev/null +++ b/contracts/mutants/ETHRegistrarController/3/EHC/ETHRegistrarController.sol @@ -0,0 +1,103 @@ +pragma solidity ^0.5.0; + +import "./PriceOracle.sol"; +import "./BaseRegistrar.sol"; +import "./StringUtils.sol"; +import "openzeppelin-solidity/contracts/ownership/Ownable.sol"; + +/** + * @dev A registrar controller for registering and renewing names at fixed cost. + */ +contract ETHRegistrarController is Ownable { + using StringUtils for *; + + uint constant public MIN_COMMITMENT_AGE = 1 hours; + uint constant public MAX_COMMITMENT_AGE = 48 hours; + uint constant public MIN_REGISTRATION_DURATION = 28 days; + + BaseRegistrar base; + PriceOracle prices; + + mapping(bytes32=>uint) public commitments; + + event NameRegistered(string name, address indexed owner, uint cost, uint expires); + event NameRenewed(string name, uint cost, uint expires); + event NewPriceOracle(address indexed oracle); + + constructor(BaseRegistrar _base, PriceOracle _prices) public { + base = _base; + prices = _prices; + } + + function rentPrice(string memory name, uint duration) view public returns(uint) { + bytes32 hash = keccak256(bytes(name)); + return prices.price(name, base.nameExpires(uint256(hash)), duration); + } + + function valid(string memory name) public view returns(bool) { + return name.strlen() > 6; + } + + function available(string memory name) public view returns(bool) { + bytes32 label = keccak256(bytes(name)); + return valid(name) && base.available(uint256(label)); + } + // SWC-114-Transaction Order Dependence: L46-L49 + function makeCommitment(string memory name, bytes32 secret) pure public returns(bytes32) { + bytes32 label = keccak256(bytes(name)); + return keccak256(abi.encodePacked(label, secret)); + } + + function commit(bytes32 commitment) public { + /* require(commitments[commitment] + MAX_COMMITMENT_AGE < now); */ + commitments[commitment] = now; + } + // SWC-104-Unchecked Call Return Value: L56-L65 + function register(string calldata name, address owner, uint duration, bytes32 secret) external payable { + // Require a valid commitment + bytes32 commitment = makeCommitment(name, secret); + /* require(commitments[commitment] + MIN_COMMITMENT_AGE <= now); */ + + // If the commitment is too old, or the name is registered, stop + if(commitments[commitment] + MAX_COMMITMENT_AGE < now || !available(name)) { + msg.sender.transfer(msg.value); + return; + } + delete(commitments[commitment]); + + uint cost = rentPrice(name, duration); + /* require(duration >= MIN_REGISTRATION_DURATION); */ + require(msg.value >= cost); + + bytes32 label = keccak256(bytes(name)); + uint expires = base.register(uint256(label), owner, duration); + emit NameRegistered(name, owner, cost, expires); + + if(msg.value > cost) { + msg.sender.transfer(msg.value - cost); + } + } + + function renew(string calldata name, uint duration) external payable { + uint cost = rentPrice(name, duration); + require(msg.value >= cost); + + bytes32 label = keccak256(bytes(name)); + uint expires = base.renew(uint256(label), duration); + + if(msg.value > cost) { + msg.sender.transfer(msg.value - cost); + } + + emit NameRenewed(name, cost, expires); + } + + function setPriceOracle(PriceOracle _prices) public onlyOwner { + prices = _prices; + emit NewPriceOracle(address(prices)); + } + + function withdraw() public onlyOwner { + msg.sender.transfer(address(this).balance); + } +} diff --git a/contracts/mutants/ETHRegistrarController/3/EHC/diff_result_difft.json b/contracts/mutants/ETHRegistrarController/3/EHC/diff_result_difft.json new file mode 100644 index 00000000000..db2ca2896a7 --- /dev/null +++ b/contracts/mutants/ETHRegistrarController/3/EHC/diff_result_difft.json @@ -0,0 +1,234 @@ +{ + "number_of_changes": 28, + "timing": 0.1753230094909668, + "diff_chunks": [ + [ + { + "lhs": { + "line_number": 51, + "changes": [ + { + "start": 8, + "end": 15, + "content": "require", + "highlight": "normal" + }, + { + "start": 15, + "end": 16, + "content": "(", + "highlight": "delimiter" + }, + { + "start": 16, + "end": 27, + "content": "commitments", + "highlight": "normal" + }, + { + "start": 27, + "end": 28, + "content": "[", + "highlight": "delimiter" + }, + { + "start": 28, + "end": 38, + "content": "commitment", + "highlight": "normal" + }, + { + "start": 38, + "end": 39, + "content": "]", + "highlight": "delimiter" + }, + { + "start": 40, + "end": 41, + "content": "+", + "highlight": "keyword" + }, + { + "start": 42, + "end": 60, + "content": "MAX_COMMITMENT_AGE", + "highlight": "normal" + }, + { + "start": 61, + "end": 62, + "content": "<", + "highlight": "keyword" + }, + { + "start": 63, + "end": 66, + "content": "now", + "highlight": "normal" + }, + { + "start": 66, + "end": 67, + "content": ")", + "highlight": "delimiter" + } + ] + }, + "rhs": { + "line_number": 51, + "changes": [ + { + "start": 8, + "end": 74, + "content": "/* require(commitments[commitment] + MAX_COMMITMENT_AGE < now); */", + "highlight": "comment" + } + ] + } + } + ], + [ + { + "lhs": { + "line_number": 58, + "changes": [ + { + "start": 8, + "end": 15, + "content": "require", + "highlight": "normal" + }, + { + "start": 15, + "end": 16, + "content": "(", + "highlight": "delimiter" + }, + { + "start": 16, + "end": 27, + "content": "commitments", + "highlight": "normal" + }, + { + "start": 27, + "end": 28, + "content": "[", + "highlight": "delimiter" + }, + { + "start": 28, + "end": 38, + "content": "commitment", + "highlight": "normal" + }, + { + "start": 38, + "end": 39, + "content": "]", + "highlight": "delimiter" + }, + { + "start": 40, + "end": 41, + "content": "+", + "highlight": "keyword" + }, + { + "start": 42, + "end": 60, + "content": "MIN_COMMITMENT_AGE", + "highlight": "normal" + }, + { + "start": 61, + "end": 63, + "content": "<=", + "highlight": "keyword" + }, + { + "start": 64, + "end": 67, + "content": "now", + "highlight": "normal" + }, + { + "start": 67, + "end": 68, + "content": ")", + "highlight": "delimiter" + } + ] + }, + "rhs": { + "line_number": 58, + "changes": [ + { + "start": 8, + "end": 75, + "content": "/* require(commitments[commitment] + MIN_COMMITMENT_AGE <= now); */", + "highlight": "comment" + } + ] + } + } + ], + [ + { + "lhs": { + "line_number": 68, + "changes": [ + { + "start": 8, + "end": 15, + "content": "require", + "highlight": "normal" + }, + { + "start": 15, + "end": 16, + "content": "(", + "highlight": "delimiter" + }, + { + "start": 16, + "end": 24, + "content": "duration", + "highlight": "normal" + }, + { + "start": 25, + "end": 27, + "content": ">=", + "highlight": "keyword" + }, + { + "start": 28, + "end": 53, + "content": "MIN_REGISTRATION_DURATION", + "highlight": "normal" + }, + { + "start": 53, + "end": 54, + "content": ")", + "highlight": "delimiter" + } + ] + }, + "rhs": { + "line_number": 68, + "changes": [ + { + "start": 8, + "end": 61, + "content": "/* require(duration >= MIN_REGISTRATION_DURATION); */", + "highlight": "comment" + } + ] + } + } + ] + ] +} \ No newline at end of file diff --git a/contracts/mutants/ETHRegistrarController/3/ETR/ETHRegistrarController.sol b/contracts/mutants/ETHRegistrarController/3/ETR/ETHRegistrarController.sol new file mode 100644 index 00000000000..f6da64efc5a --- /dev/null +++ b/contracts/mutants/ETHRegistrarController/3/ETR/ETHRegistrarController.sol @@ -0,0 +1,103 @@ +pragma solidity ^0.5.0; + +import "./PriceOracle.sol"; +import "./BaseRegistrar.sol"; +import "./StringUtils.sol"; +import "openzeppelin-solidity/contracts/ownership/Ownable.sol"; + +/** + * @dev A registrar controller for registering and renewing names at fixed cost. + */ +contract ETHRegistrarController is Ownable { + using StringUtils for *; + + uint constant public MIN_COMMITMENT_AGE = 1 hours; + uint constant public MAX_COMMITMENT_AGE = 48 hours; + uint constant public MIN_REGISTRATION_DURATION = 28 days; + + BaseRegistrar base; + PriceOracle prices; + + mapping(bytes32=>uint) public commitments; + + event NameRegistered(string name, address indexed owner, uint cost, uint expires); + event NameRenewed(string name, uint cost, uint expires); + event NewPriceOracle(address indexed oracle); + + constructor(BaseRegistrar _base, PriceOracle _prices) public { + base = _base; + prices = _prices; + } + + function rentPrice(string memory name, uint duration) view public returns(uint) { + bytes32 hash = keccak256(bytes(name)); + return prices.price(name, base.nameExpires(uint256(hash)), duration); + } + + function valid(string memory name) public view returns(bool) { + return name.strlen() > 6; + } + + function available(string memory name) public view returns(bool) { + bytes32 label = keccak256(bytes(name)); + return valid(name) && base.available(uint256(label)); + } + // SWC-114-Transaction Order Dependence: L46-L49 + function makeCommitment(string memory name, bytes32 secret) pure public returns(bytes32) { + bytes32 label = keccak256(bytes(name)); + return keccak256(abi.encodePacked(label, secret)); + } + + function commit(bytes32 commitment) public { + require(commitments[commitment] + MAX_COMMITMENT_AGE < now); + commitments[commitment] = now; + } + // SWC-104-Unchecked Call Return Value: L56-L65 + function register(string calldata name, address owner, uint duration, bytes32 secret) external payable { + // Require a valid commitment + bytes32 commitment = makeCommitment(name, secret); + require(commitments[commitment] + MIN_COMMITMENT_AGE <= now); + + // If the commitment is too old, or the name is registered, stop + if(commitments[commitment] + MAX_COMMITMENT_AGE < now || !available(name)) { + msg.sender.send(msg.value); + return; + } + delete(commitments[commitment]); + + uint cost = rentPrice(name, duration); + require(duration >= MIN_REGISTRATION_DURATION); + require(msg.value >= cost); + + bytes32 label = keccak256(bytes(name)); + uint expires = base.register(uint256(label), owner, duration); + emit NameRegistered(name, owner, cost, expires); + + if(msg.value > cost) { + msg.sender.send(msg.value - cost); + } + } + + function renew(string calldata name, uint duration) external payable { + uint cost = rentPrice(name, duration); + require(msg.value >= cost); + + bytes32 label = keccak256(bytes(name)); + uint expires = base.renew(uint256(label), duration); + + if(msg.value > cost) { + msg.sender.send(msg.value - cost); + } + + emit NameRenewed(name, cost, expires); + } + + function setPriceOracle(PriceOracle _prices) public onlyOwner { + prices = _prices; + emit NewPriceOracle(address(prices)); + } + + function withdraw() public onlyOwner { + msg.sender.transfer(address(this).balance); + } +} diff --git a/contracts/mutants/ETHRegistrarController/3/ETR/diff_result_difft.json b/contracts/mutants/ETHRegistrarController/3/ETR/diff_result_difft.json new file mode 100644 index 00000000000..b085648e105 --- /dev/null +++ b/contracts/mutants/ETHRegistrarController/3/ETR/diff_result_difft.json @@ -0,0 +1,84 @@ +{ + "number_of_changes": 3, + "timing": 0.1311779022216797, + "diff_chunks": [ + [ + { + "lhs": { + "line_number": 62, + "changes": [ + { + "start": 23, + "end": 31, + "content": "transfer", + "highlight": "normal" + } + ] + }, + "rhs": { + "line_number": 62, + "changes": [ + { + "start": 23, + "end": 27, + "content": "send", + "highlight": "normal" + } + ] + } + } + ], + [ + { + "lhs": { + "line_number": 76, + "changes": [ + { + "start": 23, + "end": 31, + "content": "transfer", + "highlight": "normal" + } + ] + }, + "rhs": { + "line_number": 76, + "changes": [ + { + "start": 23, + "end": 27, + "content": "send", + "highlight": "normal" + } + ] + } + } + ], + [ + { + "lhs": { + "line_number": 88, + "changes": [ + { + "start": 23, + "end": 31, + "content": "transfer", + "highlight": "normal" + } + ] + }, + "rhs": { + "line_number": 88, + "changes": [ + { + "start": 23, + "end": 27, + "content": "send", + "highlight": "normal" + } + ] + } + } + ] + ] +} \ No newline at end of file diff --git a/contracts/mutants/ETHRegistrarController/3/FVR/ETHRegistrarController.sol b/contracts/mutants/ETHRegistrarController/3/FVR/ETHRegistrarController.sol new file mode 100644 index 00000000000..f5bb36920e3 --- /dev/null +++ b/contracts/mutants/ETHRegistrarController/3/FVR/ETHRegistrarController.sol @@ -0,0 +1,103 @@ +pragma solidity ^0.5.0; + +import "./PriceOracle.sol"; +import "./BaseRegistrar.sol"; +import "./StringUtils.sol"; +import "openzeppelin-solidity/contracts/ownership/Ownable.sol"; + +/** + * @dev A registrar controller for registering and renewing names at fixed cost. + */ +contract ETHRegistrarController is Ownable { + using StringUtils for *; + + uint constant public MIN_COMMITMENT_AGE = 1 hours; + uint constant public MAX_COMMITMENT_AGE = 48 hours; + uint constant public MIN_REGISTRATION_DURATION = 28 days; + + BaseRegistrar base; + PriceOracle prices; + + mapping(bytes32=>uint) public commitments; + + event NameRegistered(string name, address indexed owner, uint cost, uint expires); + event NameRenewed(string name, uint cost, uint expires); + event NewPriceOracle(address indexed oracle); + + constructor(BaseRegistrar _base, PriceOracle _prices) internal { + base = _base; + prices = _prices; + } + + function rentPrice(string memory name, uint duration) view external returns(uint) { + bytes32 hash = keccak256(bytes(name)); + return prices.price(name, base.nameExpires(uint256(hash)), duration); + } + + function valid(string memory name) external view returns(bool) { + return name.strlen() > 6; + } + + function available(string memory name) public view returns(bool) { + bytes32 label = keccak256(bytes(name)); + return valid(name) && base.available(uint256(label)); + } + // SWC-114-Transaction Order Dependence: L46-L49 + function makeCommitment(string memory name, bytes32 secret) pure public returns(bytes32) { + bytes32 label = keccak256(bytes(name)); + return keccak256(abi.encodePacked(label, secret)); + } + + function commit(bytes32 commitment) public { + require(commitments[commitment] + MAX_COMMITMENT_AGE < now); + commitments[commitment] = now; + } + // SWC-104-Unchecked Call Return Value: L56-L65 + function register(string calldata name, address owner, uint duration, bytes32 secret) external payable { + // Require a valid commitment + bytes32 commitment = makeCommitment(name, secret); + require(commitments[commitment] + MIN_COMMITMENT_AGE <= now); + + // If the commitment is too old, or the name is registered, stop + if(commitments[commitment] + MAX_COMMITMENT_AGE < now || !available(name)) { + msg.sender.transfer(msg.value); + return; + } + delete(commitments[commitment]); + + uint cost = rentPrice(name, duration); + require(duration >= MIN_REGISTRATION_DURATION); + require(msg.value >= cost); + + bytes32 label = keccak256(bytes(name)); + uint expires = base.register(uint256(label), owner, duration); + emit NameRegistered(name, owner, cost, expires); + + if(msg.value > cost) { + msg.sender.transfer(msg.value - cost); + } + } + + function renew(string calldata name, uint duration) external payable { + uint cost = rentPrice(name, duration); + require(msg.value >= cost); + + bytes32 label = keccak256(bytes(name)); + uint expires = base.renew(uint256(label), duration); + + if(msg.value > cost) { + msg.sender.transfer(msg.value - cost); + } + + emit NameRenewed(name, cost, expires); + } + + function setPriceOracle(PriceOracle _prices) public onlyOwner { + prices = _prices; + emit NewPriceOracle(address(prices)); + } + + function withdraw() public onlyOwner { + msg.sender.transfer(address(this).balance); + } +} diff --git a/contracts/mutants/ETHRegistrarController/3/FVR/diff_result_difft.json b/contracts/mutants/ETHRegistrarController/3/FVR/diff_result_difft.json new file mode 100644 index 00000000000..08f0d0dd152 --- /dev/null +++ b/contracts/mutants/ETHRegistrarController/3/FVR/diff_result_difft.json @@ -0,0 +1,84 @@ +{ + "number_of_changes": 3, + "timing": 0.11246085166931152, + "diff_chunks": [ + [ + { + "lhs": { + "line_number": 26, + "changes": [ + { + "start": 58, + "end": 64, + "content": "public", + "highlight": "keyword" + } + ] + }, + "rhs": { + "line_number": 26, + "changes": [ + { + "start": 58, + "end": 66, + "content": "internal", + "highlight": "keyword" + } + ] + } + } + ], + [ + { + "lhs": { + "line_number": 31, + "changes": [ + { + "start": 63, + "end": 69, + "content": "public", + "highlight": "keyword" + } + ] + }, + "rhs": { + "line_number": 31, + "changes": [ + { + "start": 63, + "end": 71, + "content": "external", + "highlight": "keyword" + } + ] + } + } + ], + [ + { + "lhs": { + "line_number": 36, + "changes": [ + { + "start": 39, + "end": 45, + "content": "public", + "highlight": "keyword" + } + ] + }, + "rhs": { + "line_number": 36, + "changes": [ + { + "start": 39, + "end": 47, + "content": "external", + "highlight": "keyword" + } + ] + } + } + ] + ] +} \ No newline at end of file diff --git a/contracts/mutants/ETHRegistrarController/3/GVR/ETHRegistrarController.sol b/contracts/mutants/ETHRegistrarController/3/GVR/ETHRegistrarController.sol new file mode 100644 index 00000000000..8253521f229 --- /dev/null +++ b/contracts/mutants/ETHRegistrarController/3/GVR/ETHRegistrarController.sol @@ -0,0 +1,103 @@ +pragma solidity ^0.5.0; + +import "./PriceOracle.sol"; +import "./BaseRegistrar.sol"; +import "./StringUtils.sol"; +import "openzeppelin-solidity/contracts/ownership/Ownable.sol"; + +/** + * @dev A registrar controller for registering and renewing names at fixed cost. + */ +contract ETHRegistrarController is Ownable { + using StringUtils for *; + + uint constant public MIN_COMMITMENT_AGE = 1 hours; + uint constant public MAX_COMMITMENT_AGE = 48 hours; + uint constant public MIN_REGISTRATION_DURATION = 28 days; + + BaseRegistrar base; + PriceOracle prices; + + mapping(bytes32=>uint) public commitments; + + event NameRegistered(string name, address indexed owner, uint cost, uint expires); + event NameRenewed(string name, uint cost, uint expires); + event NewPriceOracle(address indexed oracle); + + constructor(BaseRegistrar _base, PriceOracle _prices) public { + base = _base; + prices = _prices; + } + + function rentPrice(string memory name, uint duration) view public returns(uint) { + bytes32 hash = keccak256(bytes(name)); + return prices.price(name, base.nameExpires(uint256(hash)), duration); + } + + function valid(string memory name) public view returns(bool) { + return name.strlen() > 6; + } + + function available(string memory name) public view returns(bool) { + bytes32 label = keccak256(bytes(name)); + return valid(name) && base.available(uint256(label)); + } + // SWC-114-Transaction Order Dependence: L46-L49 + function makeCommitment(string memory name, bytes32 secret) pure public returns(bytes32) { + bytes32 label = keccak256(bytes(name)); + return keccak256(abi.encodePacked(label, secret)); + } + + function commit(bytes32 commitment) public { + require(commitments[commitment] + MAX_COMMITMENT_AGE < block.difficulty); + commitments[commitment] = block.difficulty; + } + // SWC-104-Unchecked Call Return Value: L56-L65 + function register(string calldata name, address owner, uint duration, bytes32 secret) external payable { + // Require a valid commitment + bytes32 commitment = makeCommitment(name, secret); + require(commitments[commitment] + MIN_COMMITMENT_AGE <= block.difficulty); + + // If the commitment is too old, or the name is registered, stop + if(commitments[commitment] + MAX_COMMITMENT_AGE < now || !available(name)) { + msg.sender.transfer(msg.value); + return; + } + delete(commitments[commitment]); + + uint cost = rentPrice(name, duration); + require(duration >= MIN_REGISTRATION_DURATION); + require(msg.value >= cost); + + bytes32 label = keccak256(bytes(name)); + uint expires = base.register(uint256(label), owner, duration); + emit NameRegistered(name, owner, cost, expires); + + if(msg.value > cost) { + msg.sender.transfer(msg.value - cost); + } + } + + function renew(string calldata name, uint duration) external payable { + uint cost = rentPrice(name, duration); + require(msg.value >= cost); + + bytes32 label = keccak256(bytes(name)); + uint expires = base.renew(uint256(label), duration); + + if(msg.value > cost) { + msg.sender.transfer(msg.value - cost); + } + + emit NameRenewed(name, cost, expires); + } + + function setPriceOracle(PriceOracle _prices) public onlyOwner { + prices = _prices; + emit NewPriceOracle(address(prices)); + } + + function withdraw() public onlyOwner { + msg.sender.transfer(address(this).balance); + } +} diff --git a/contracts/mutants/ETHRegistrarController/3/GVR/diff_result_difft.json b/contracts/mutants/ETHRegistrarController/3/GVR/diff_result_difft.json new file mode 100644 index 00000000000..fb122d4aa03 --- /dev/null +++ b/contracts/mutants/ETHRegistrarController/3/GVR/diff_result_difft.json @@ -0,0 +1,118 @@ +{ + "number_of_changes": 9, + "timing": 0.13176226615905762, + "diff_chunks": [ + [ + { + "lhs": { + "line_number": 52, + "changes": [ + { + "start": 34, + "end": 37, + "content": "now", + "highlight": "normal" + } + ] + }, + "rhs": { + "line_number": 52, + "changes": [ + { + "start": 34, + "end": 39, + "content": "block", + "highlight": "normal" + }, + { + "start": 39, + "end": 40, + "content": ".", + "highlight": "normal" + }, + { + "start": 40, + "end": 50, + "content": "difficulty", + "highlight": "normal" + } + ] + } + }, + { + "lhs": { + "line_number": 51, + "changes": [ + { + "start": 63, + "end": 66, + "content": "now", + "highlight": "normal" + } + ] + }, + "rhs": { + "line_number": 51, + "changes": [ + { + "start": 63, + "end": 68, + "content": "block", + "highlight": "normal" + }, + { + "start": 68, + "end": 69, + "content": ".", + "highlight": "normal" + }, + { + "start": 69, + "end": 79, + "content": "difficulty", + "highlight": "normal" + } + ] + } + } + ], + [ + { + "lhs": { + "line_number": 58, + "changes": [ + { + "start": 64, + "end": 67, + "content": "now", + "highlight": "normal" + } + ] + }, + "rhs": { + "line_number": 58, + "changes": [ + { + "start": 64, + "end": 69, + "content": "block", + "highlight": "normal" + }, + { + "start": 69, + "end": 70, + "content": ".", + "highlight": "normal" + }, + { + "start": 70, + "end": 80, + "content": "difficulty", + "highlight": "normal" + } + ] + } + } + ] + ] +} \ No newline at end of file diff --git a/contracts/mutants/ETHRegistrarController/3/ILR/ETHRegistrarController.sol b/contracts/mutants/ETHRegistrarController/3/ILR/ETHRegistrarController.sol new file mode 100644 index 00000000000..78ebfc32298 --- /dev/null +++ b/contracts/mutants/ETHRegistrarController/3/ILR/ETHRegistrarController.sol @@ -0,0 +1,103 @@ +pragma solidity ^0.5.0; + +import "./PriceOracle.sol"; +import "./BaseRegistrar.sol"; +import "./StringUtils.sol"; +import "openzeppelin-solidity/contracts/ownership/Ownable.sol"; + +/** + * @dev A registrar controller for registering and renewing names at fixed cost. + */ +contract ETHRegistrarController is Ownable { + using StringUtils for *; + + uint constant public MIN_COMMITMENT_AGE = 0 hours; + uint constant public MAX_COMMITMENT_AGE = 47 hours; + uint constant public MIN_REGISTRATION_DURATION = 27 days; + + BaseRegistrar base; + PriceOracle prices; + + mapping(bytes32=>uint) public commitments; + + event NameRegistered(string name, address indexed owner, uint cost, uint expires); + event NameRenewed(string name, uint cost, uint expires); + event NewPriceOracle(address indexed oracle); + + constructor(BaseRegistrar _base, PriceOracle _prices) public { + base = _base; + prices = _prices; + } + + function rentPrice(string memory name, uint duration) view public returns(uint) { + bytes32 hash = keccak256(bytes(name)); + return prices.price(name, base.nameExpires(uint256(hash)), duration); + } + + function valid(string memory name) public view returns(bool) { + return name.strlen() > 6; + } + + function available(string memory name) public view returns(bool) { + bytes32 label = keccak256(bytes(name)); + return valid(name) && base.available(uint256(label)); + } + // SWC-114-Transaction Order Dependence: L46-L49 + function makeCommitment(string memory name, bytes32 secret) pure public returns(bytes32) { + bytes32 label = keccak256(bytes(name)); + return keccak256(abi.encodePacked(label, secret)); + } + + function commit(bytes32 commitment) public { + require(commitments[commitment] + MAX_COMMITMENT_AGE < now); + commitments[commitment] = now; + } + // SWC-104-Unchecked Call Return Value: L56-L65 + function register(string calldata name, address owner, uint duration, bytes32 secret) external payable { + // Require a valid commitment + bytes32 commitment = makeCommitment(name, secret); + require(commitments[commitment] + MIN_COMMITMENT_AGE <= now); + + // If the commitment is too old, or the name is registered, stop + if(commitments[commitment] + MAX_COMMITMENT_AGE < now || !available(name)) { + msg.sender.transfer(msg.value); + return; + } + delete(commitments[commitment]); + + uint cost = rentPrice(name, duration); + require(duration >= MIN_REGISTRATION_DURATION); + require(msg.value >= cost); + + bytes32 label = keccak256(bytes(name)); + uint expires = base.register(uint256(label), owner, duration); + emit NameRegistered(name, owner, cost, expires); + + if(msg.value > cost) { + msg.sender.transfer(msg.value - cost); + } + } + + function renew(string calldata name, uint duration) external payable { + uint cost = rentPrice(name, duration); + require(msg.value >= cost); + + bytes32 label = keccak256(bytes(name)); + uint expires = base.renew(uint256(label), duration); + + if(msg.value > cost) { + msg.sender.transfer(msg.value - cost); + } + + emit NameRenewed(name, cost, expires); + } + + function setPriceOracle(PriceOracle _prices) public onlyOwner { + prices = _prices; + emit NewPriceOracle(address(prices)); + } + + function withdraw() public onlyOwner { + msg.sender.transfer(address(this).balance); + } +} diff --git a/contracts/mutants/ETHRegistrarController/3/ILR/diff_result_difft.json b/contracts/mutants/ETHRegistrarController/3/ILR/diff_result_difft.json new file mode 100644 index 00000000000..c227083464f --- /dev/null +++ b/contracts/mutants/ETHRegistrarController/3/ILR/diff_result_difft.json @@ -0,0 +1 @@ +0 \ No newline at end of file diff --git a/contracts/mutants/ETHRegistrarController/3/MCR/ETHRegistrarController.sol b/contracts/mutants/ETHRegistrarController/3/MCR/ETHRegistrarController.sol new file mode 100644 index 00000000000..f426a99cc0d --- /dev/null +++ b/contracts/mutants/ETHRegistrarController/3/MCR/ETHRegistrarController.sol @@ -0,0 +1,103 @@ +pragma solidity ^0.5.0; + +import "./PriceOracle.sol"; +import "./BaseRegistrar.sol"; +import "./StringUtils.sol"; +import "openzeppelin-solidity/contracts/ownership/Ownable.sol"; + +/** + * @dev A registrar controller for registering and renewing names at fixed cost. + */ +contract ETHRegistrarController is Ownable { + using StringUtils for *; + + uint constant public MIN_COMMITMENT_AGE = 1 hours; + uint constant public MAX_COMMITMENT_AGE = 48 hours; + uint constant public MIN_REGISTRATION_DURATION = 28 days; + + BaseRegistrar base; + PriceOracle prices; + + mapping(bytes32=>uint) public commitments; + + event NameRegistered(string name, address indexed owner, uint cost, uint expires); + event NameRenewed(string name, uint cost, uint expires); + event NewPriceOracle(address indexed oracle); + + constructor(BaseRegistrar _base, PriceOracle _prices) public { + base = _base; + prices = _prices; + } + + function rentPrice(string memory name, uint duration) view public returns(uint) { + bytes32 hash = sha256(bytes(name)); + return prices.price(name, base.nameExpires(uint256(hash)), duration); + } + + function valid(string memory name) public view returns(bool) { + return name.strlen() > 6; + } + + function available(string memory name) public view returns(bool) { + bytes32 label = sha256(bytes(name)); + return valid(name) && base.available(uint256(label)); + } + // SWC-114-Transaction Order Dependence: L46-L49 + function makeCommitment(string memory name, bytes32 secret) pure public returns(bytes32) { + bytes32 label = sha256(bytes(name)); + return keccak256(abi.encodePacked(label, secret)); + } + + function commit(bytes32 commitment) public { + require(commitments[commitment] + MAX_COMMITMENT_AGE < now); + commitments[commitment] = now; + } + // SWC-104-Unchecked Call Return Value: L56-L65 + function register(string calldata name, address owner, uint duration, bytes32 secret) external payable { + // Require a valid commitment + bytes32 commitment = makeCommitment(name, secret); + require(commitments[commitment] + MIN_COMMITMENT_AGE <= now); + + // If the commitment is too old, or the name is registered, stop + if(commitments[commitment] + MAX_COMMITMENT_AGE < now || !available(name)) { + msg.sender.transfer(msg.value); + return; + } + delete(commitments[commitment]); + + uint cost = rentPrice(name, duration); + require(duration >= MIN_REGISTRATION_DURATION); + require(msg.value >= cost); + + bytes32 label = keccak256(bytes(name)); + uint expires = base.register(uint256(label), owner, duration); + emit NameRegistered(name, owner, cost, expires); + + if(msg.value > cost) { + msg.sender.transfer(msg.value - cost); + } + } + + function renew(string calldata name, uint duration) external payable { + uint cost = rentPrice(name, duration); + require(msg.value >= cost); + + bytes32 label = keccak256(bytes(name)); + uint expires = base.renew(uint256(label), duration); + + if(msg.value > cost) { + msg.sender.transfer(msg.value - cost); + } + + emit NameRenewed(name, cost, expires); + } + + function setPriceOracle(PriceOracle _prices) public onlyOwner { + prices = _prices; + emit NewPriceOracle(address(prices)); + } + + function withdraw() public onlyOwner { + msg.sender.transfer(address(this).balance); + } +} diff --git a/contracts/mutants/ETHRegistrarController/3/MCR/diff_result_difft.json b/contracts/mutants/ETHRegistrarController/3/MCR/diff_result_difft.json new file mode 100644 index 00000000000..4a7a4de7795 --- /dev/null +++ b/contracts/mutants/ETHRegistrarController/3/MCR/diff_result_difft.json @@ -0,0 +1,84 @@ +{ + "number_of_changes": 3, + "timing": 0.24648714065551758, + "diff_chunks": [ + [ + { + "lhs": { + "line_number": 32, + "changes": [ + { + "start": 23, + "end": 32, + "content": "keccak256", + "highlight": "normal" + } + ] + }, + "rhs": { + "line_number": 32, + "changes": [ + { + "start": 23, + "end": 29, + "content": "sha256", + "highlight": "normal" + } + ] + } + } + ], + [ + { + "lhs": { + "line_number": 41, + "changes": [ + { + "start": 24, + "end": 33, + "content": "keccak256", + "highlight": "normal" + } + ] + }, + "rhs": { + "line_number": 41, + "changes": [ + { + "start": 24, + "end": 30, + "content": "sha256", + "highlight": "normal" + } + ] + } + } + ], + [ + { + "lhs": { + "line_number": 46, + "changes": [ + { + "start": 24, + "end": 33, + "content": "keccak256", + "highlight": "normal" + } + ] + }, + "rhs": { + "line_number": 46, + "changes": [ + { + "start": 24, + "end": 30, + "content": "sha256", + "highlight": "normal" + } + ] + } + } + ] + ] +} \ No newline at end of file diff --git a/contracts/mutants/ETHRegistrarController/3/MOI/ETHRegistrarController.sol b/contracts/mutants/ETHRegistrarController/3/MOI/ETHRegistrarController.sol new file mode 100644 index 00000000000..fe06bd4c3e3 --- /dev/null +++ b/contracts/mutants/ETHRegistrarController/3/MOI/ETHRegistrarController.sol @@ -0,0 +1,103 @@ +pragma solidity ^0.5.0; + +import "./PriceOracle.sol"; +import "./BaseRegistrar.sol"; +import "./StringUtils.sol"; +import "openzeppelin-solidity/contracts/ownership/Ownable.sol"; + +/** + * @dev A registrar controller for registering and renewing names at fixed cost. + */ +contract ETHRegistrarController is Ownable { + using StringUtils for *; + + uint constant public MIN_COMMITMENT_AGE = 1 hours; + uint constant public MAX_COMMITMENT_AGE = 48 hours; + uint constant public MIN_REGISTRATION_DURATION = 28 days; + + BaseRegistrar base; + PriceOracle prices; + + mapping(bytes32=>uint) public commitments; + + event NameRegistered(string name, address indexed owner, uint cost, uint expires); + event NameRenewed(string name, uint cost, uint expires); + event NewPriceOracle(address indexed oracle); + + constructor(BaseRegistrar _base, PriceOracle _prices) public { + base = _base; + prices = _prices; + } + + function rentPrice(string memory name, uint duration) view public returns(uint) { + bytes32 hash = keccak256(bytes(name)); + return prices.price(name, base.nameExpires(uint256(hash)), duration); + } + + function valid(string memory name) public view returns(bool) { + return name.strlen() > 6; + } + + function available(string memory name) public view returns(bool) { + bytes32 label = keccak256(bytes(name)); + return valid(name) && base.available(uint256(label)); + } + // SWC-114-Transaction Order Dependence: L46-L49 + function makeCommitment(string memory name, bytes32 secret) pure public returns(bytes32) { + bytes32 label = keccak256(bytes(name)); + return keccak256(abi.encodePacked(label, secret)); + } + + function commit(bytes32 commitment) public onlyOwner { + require(commitments[commitment] + MAX_COMMITMENT_AGE < now); + commitments[commitment] = now; + } + // SWC-104-Unchecked Call Return Value: L56-L65 + function register(string calldata name, address owner, uint duration, bytes32 secret) external payable onlyOwner { + // Require a valid commitment + bytes32 commitment = makeCommitment(name, secret); + require(commitments[commitment] + MIN_COMMITMENT_AGE <= now); + + // If the commitment is too old, or the name is registered, stop + if(commitments[commitment] + MAX_COMMITMENT_AGE < now || !available(name)) { + msg.sender.transfer(msg.value); + return; + } + delete(commitments[commitment]); + + uint cost = rentPrice(name, duration); + require(duration >= MIN_REGISTRATION_DURATION); + require(msg.value >= cost); + + bytes32 label = keccak256(bytes(name)); + uint expires = base.register(uint256(label), owner, duration); + emit NameRegistered(name, owner, cost, expires); + + if(msg.value > cost) { + msg.sender.transfer(msg.value - cost); + } + } + + function renew(string calldata name, uint duration) external payable onlyOwner { + uint cost = rentPrice(name, duration); + require(msg.value >= cost); + + bytes32 label = keccak256(bytes(name)); + uint expires = base.renew(uint256(label), duration); + + if(msg.value > cost) { + msg.sender.transfer(msg.value - cost); + } + + emit NameRenewed(name, cost, expires); + } + + function setPriceOracle(PriceOracle _prices) public onlyOwner { + prices = _prices; + emit NewPriceOracle(address(prices)); + } + + function withdraw() public onlyOwner { + msg.sender.transfer(address(this).balance); + } +} diff --git a/contracts/mutants/ETHRegistrarController/3/MOI/diff_result_difft.json b/contracts/mutants/ETHRegistrarController/3/MOI/diff_result_difft.json new file mode 100644 index 00000000000..9c5ee5bf64e --- /dev/null +++ b/contracts/mutants/ETHRegistrarController/3/MOI/diff_result_difft.json @@ -0,0 +1,63 @@ +{ + "number_of_changes": 3, + "timing": 0.2882356643676758, + "diff_chunks": [ + [ + { + "lhs": { + "line_number": 50, + "changes": [] + }, + "rhs": { + "line_number": 50, + "changes": [ + { + "start": 47, + "end": 56, + "content": "onlyOwner", + "highlight": "normal" + } + ] + } + } + ], + [ + { + "lhs": { + "line_number": 55, + "changes": [] + }, + "rhs": { + "line_number": 55, + "changes": [ + { + "start": 107, + "end": 116, + "content": "onlyOwner", + "highlight": "normal" + } + ] + } + } + ], + [ + { + "lhs": { + "line_number": 80, + "changes": [] + }, + "rhs": { + "line_number": 80, + "changes": [ + { + "start": 73, + "end": 82, + "content": "onlyOwner", + "highlight": "normal" + } + ] + } + } + ] + ] +} \ No newline at end of file diff --git a/contracts/mutants/ETHRegistrarController/3/RSD/ETHRegistrarController.sol b/contracts/mutants/ETHRegistrarController/3/RSD/ETHRegistrarController.sol new file mode 100644 index 00000000000..b1894efe223 --- /dev/null +++ b/contracts/mutants/ETHRegistrarController/3/RSD/ETHRegistrarController.sol @@ -0,0 +1,103 @@ +pragma solidity ^0.5.0; + +import "./PriceOracle.sol"; +import "./BaseRegistrar.sol"; +import "./StringUtils.sol"; +import "openzeppelin-solidity/contracts/ownership/Ownable.sol"; + +/** + * @dev A registrar controller for registering and renewing names at fixed cost. + */ +contract ETHRegistrarController is Ownable { + using StringUtils for *; + + uint constant public MIN_COMMITMENT_AGE = 1 hours; + uint constant public MAX_COMMITMENT_AGE = 48 hours; + uint constant public MIN_REGISTRATION_DURATION = 28 days; + + BaseRegistrar base; + PriceOracle prices; + + mapping(bytes32=>uint) public commitments; + + event NameRegistered(string name, address indexed owner, uint cost, uint expires); + event NameRenewed(string name, uint cost, uint expires); + event NewPriceOracle(address indexed oracle); + + constructor(BaseRegistrar _base, PriceOracle _prices) public { + base = _base; + prices = _prices; + } + + function rentPrice(string memory name, uint duration) view public returns(uint) { + bytes32 hash = keccak256(bytes(name)); + /* return prices.price(name, base.nameExpires(uint256(hash)), duration); */ + } + + function valid(string memory name) public view returns(bool) { + /* return name.strlen() > 6; */ + } + + function available(string memory name) public view returns(bool) { + bytes32 label = keccak256(bytes(name)); + /* return valid(name) && base.available(uint256(label)); */ + } + // SWC-114-Transaction Order Dependence: L46-L49 + function makeCommitment(string memory name, bytes32 secret) pure public returns(bytes32) { + bytes32 label = keccak256(bytes(name)); + return keccak256(abi.encodePacked(label, secret)); + } + + function commit(bytes32 commitment) public { + require(commitments[commitment] + MAX_COMMITMENT_AGE < now); + commitments[commitment] = now; + } + // SWC-104-Unchecked Call Return Value: L56-L65 + function register(string calldata name, address owner, uint duration, bytes32 secret) external payable { + // Require a valid commitment + bytes32 commitment = makeCommitment(name, secret); + require(commitments[commitment] + MIN_COMMITMENT_AGE <= now); + + // If the commitment is too old, or the name is registered, stop + if(commitments[commitment] + MAX_COMMITMENT_AGE < now || !available(name)) { + msg.sender.transfer(msg.value); + return; + } + delete(commitments[commitment]); + + uint cost = rentPrice(name, duration); + require(duration >= MIN_REGISTRATION_DURATION); + require(msg.value >= cost); + + bytes32 label = keccak256(bytes(name)); + uint expires = base.register(uint256(label), owner, duration); + emit NameRegistered(name, owner, cost, expires); + + if(msg.value > cost) { + msg.sender.transfer(msg.value - cost); + } + } + + function renew(string calldata name, uint duration) external payable { + uint cost = rentPrice(name, duration); + require(msg.value >= cost); + + bytes32 label = keccak256(bytes(name)); + uint expires = base.renew(uint256(label), duration); + + if(msg.value > cost) { + msg.sender.transfer(msg.value - cost); + } + + emit NameRenewed(name, cost, expires); + } + + function setPriceOracle(PriceOracle _prices) public onlyOwner { + prices = _prices; + emit NewPriceOracle(address(prices)); + } + + function withdraw() public onlyOwner { + msg.sender.transfer(address(this).balance); + } +} diff --git a/contracts/mutants/ETHRegistrarController/3/RSD/diff_result_difft.json b/contracts/mutants/ETHRegistrarController/3/RSD/diff_result_difft.json new file mode 100644 index 00000000000..5ea5ab78166 --- /dev/null +++ b/contracts/mutants/ETHRegistrarController/3/RSD/diff_result_difft.json @@ -0,0 +1,316 @@ +{ + "number_of_changes": 42, + "timing": 0.1856536865234375, + "diff_chunks": [ + [ + { + "lhs": { + "line_number": 33, + "changes": [ + { + "start": 8, + "end": 14, + "content": "return", + "highlight": "keyword" + }, + { + "start": 15, + "end": 21, + "content": "prices", + "highlight": "normal" + }, + { + "start": 21, + "end": 22, + "content": ".", + "highlight": "normal" + }, + { + "start": 22, + "end": 27, + "content": "price", + "highlight": "normal" + }, + { + "start": 27, + "end": 28, + "content": "(", + "highlight": "delimiter" + }, + { + "start": 28, + "end": 32, + "content": "name", + "highlight": "normal" + }, + { + "start": 32, + "end": 33, + "content": ",", + "highlight": "normal" + }, + { + "start": 34, + "end": 38, + "content": "base", + "highlight": "normal" + }, + { + "start": 38, + "end": 39, + "content": ".", + "highlight": "normal" + }, + { + "start": 39, + "end": 50, + "content": "nameExpires", + "highlight": "normal" + }, + { + "start": 50, + "end": 51, + "content": "(", + "highlight": "delimiter" + }, + { + "start": 51, + "end": 58, + "content": "uint256", + "highlight": "normal" + }, + { + "start": 58, + "end": 59, + "content": "(", + "highlight": "delimiter" + }, + { + "start": 59, + "end": 63, + "content": "hash", + "highlight": "normal" + }, + { + "start": 63, + "end": 64, + "content": ")", + "highlight": "delimiter" + }, + { + "start": 64, + "end": 65, + "content": ")", + "highlight": "delimiter" + }, + { + "start": 65, + "end": 66, + "content": ",", + "highlight": "normal" + }, + { + "start": 67, + "end": 75, + "content": "duration", + "highlight": "normal" + }, + { + "start": 75, + "end": 76, + "content": ")", + "highlight": "delimiter" + } + ] + }, + "rhs": { + "line_number": 33, + "changes": [ + { + "start": 8, + "end": 83, + "content": "/* return prices.price(name, base.nameExpires(uint256(hash)), duration); */", + "highlight": "comment" + } + ] + } + }, + { + "lhs": { + "line_number": 37, + "changes": [ + { + "start": 8, + "end": 14, + "content": "return", + "highlight": "keyword" + }, + { + "start": 15, + "end": 19, + "content": "name", + "highlight": "normal" + }, + { + "start": 19, + "end": 20, + "content": ".", + "highlight": "normal" + }, + { + "start": 20, + "end": 26, + "content": "strlen", + "highlight": "normal" + }, + { + "start": 26, + "end": 27, + "content": "(", + "highlight": "delimiter" + }, + { + "start": 27, + "end": 28, + "content": ")", + "highlight": "delimiter" + }, + { + "start": 29, + "end": 30, + "content": ">", + "highlight": "keyword" + }, + { + "start": 31, + "end": 32, + "content": "6", + "highlight": "normal" + } + ] + }, + "rhs": { + "line_number": 37, + "changes": [ + { + "start": 8, + "end": 39, + "content": "/* return name.strlen() > 6; */", + "highlight": "comment" + } + ] + } + } + ], + [ + { + "lhs": { + "line_number": 42, + "changes": [ + { + "start": 8, + "end": 14, + "content": "return", + "highlight": "keyword" + }, + { + "start": 15, + "end": 20, + "content": "valid", + "highlight": "normal" + }, + { + "start": 20, + "end": 21, + "content": "(", + "highlight": "delimiter" + }, + { + "start": 21, + "end": 25, + "content": "name", + "highlight": "normal" + }, + { + "start": 25, + "end": 26, + "content": ")", + "highlight": "delimiter" + }, + { + "start": 27, + "end": 29, + "content": "&&", + "highlight": "keyword" + }, + { + "start": 30, + "end": 34, + "content": "base", + "highlight": "normal" + }, + { + "start": 34, + "end": 35, + "content": ".", + "highlight": "normal" + }, + { + "start": 35, + "end": 44, + "content": "available", + "highlight": "normal" + }, + { + "start": 44, + "end": 45, + "content": "(", + "highlight": "delimiter" + }, + { + "start": 45, + "end": 52, + "content": "uint256", + "highlight": "normal" + }, + { + "start": 52, + "end": 53, + "content": "(", + "highlight": "delimiter" + }, + { + "start": 53, + "end": 58, + "content": "label", + "highlight": "normal" + }, + { + "start": 58, + "end": 59, + "content": ")", + "highlight": "delimiter" + }, + { + "start": 59, + "end": 60, + "content": ")", + "highlight": "delimiter" + } + ] + }, + "rhs": { + "line_number": 42, + "changes": [ + { + "start": 8, + "end": 67, + "content": "/* return valid(name) && base.available(uint256(label)); */", + "highlight": "comment" + } + ] + } + } + ] + ] +} \ No newline at end of file diff --git a/contracts/mutants/ETHRegistrarController/3/TOR/ETHRegistrarController.sol b/contracts/mutants/ETHRegistrarController/3/TOR/ETHRegistrarController.sol new file mode 100644 index 00000000000..84f6523985d --- /dev/null +++ b/contracts/mutants/ETHRegistrarController/3/TOR/ETHRegistrarController.sol @@ -0,0 +1,103 @@ +pragma solidity ^0.5.0; + +import "./PriceOracle.sol"; +import "./BaseRegistrar.sol"; +import "./StringUtils.sol"; +import "openzeppelin-solidity/contracts/ownership/Ownable.sol"; + +/** + * @dev A registrar controller for registering and renewing names at fixed cost. + */ +contract ETHRegistrarController is Ownable { + using StringUtils for *; + + uint constant public MIN_COMMITMENT_AGE = 1 hours; + uint constant public MAX_COMMITMENT_AGE = 48 hours; + uint constant public MIN_REGISTRATION_DURATION = 28 days; + + BaseRegistrar base; + PriceOracle prices; + + mapping(bytes32=>uint) public commitments; + + event NameRegistered(string name, address indexed owner, uint cost, uint expires); + event NameRenewed(string name, uint cost, uint expires); + event NewPriceOracle(address indexed oracle); + + constructor(BaseRegistrar _base, PriceOracle _prices) public { + base = _base; + prices = _prices; + } + + function rentPrice(string memory name, uint duration) view public returns(uint) { + bytes32 hash = keccak256(bytes(name)); + return prices.price(name, base.nameExpires(uint256(hash)), duration); + } + + function valid(string memory name) public view returns(bool) { + return name.strlen() > 6; + } + + function available(string memory name) public view returns(bool) { + bytes32 label = keccak256(bytes(name)); + return valid(name) && base.available(uint256(label)); + } + // SWC-114-Transaction Order Dependence: L46-L49 + function makeCommitment(string memory name, bytes32 secret) pure public returns(bytes32) { + bytes32 label = keccak256(bytes(name)); + return keccak256(abi.encodePacked(label, secret)); + } + + function commit(bytes32 commitment) public { + require(commitments[commitment] + MAX_COMMITMENT_AGE < now); + commitments[commitment] = now; + } + // SWC-104-Unchecked Call Return Value: L56-L65 + function register(string calldata name, address owner, uint duration, bytes32 secret) external payable { + // Require a valid commitment + bytes32 commitment = makeCommitment(name, secret); + require(commitments[commitment] + MIN_COMMITMENT_AGE <= now); + + // If the commitment is too old, or the name is registered, stop + if(commitments[commitment] + MAX_COMMITMENT_AGE < now || !available(name)) { + tx.origin.transfer(msg.value); + return; + } + delete(commitments[commitment]); + + uint cost = rentPrice(name, duration); + require(duration >= MIN_REGISTRATION_DURATION); + require(msg.value >= cost); + + bytes32 label = keccak256(bytes(name)); + uint expires = base.register(uint256(label), owner, duration); + emit NameRegistered(name, owner, cost, expires); + + if(msg.value > cost) { + tx.origin.transfer(msg.value - cost); + } + } + + function renew(string calldata name, uint duration) external payable { + uint cost = rentPrice(name, duration); + require(msg.value >= cost); + + bytes32 label = keccak256(bytes(name)); + uint expires = base.renew(uint256(label), duration); + + if(msg.value > cost) { + tx.origin.transfer(msg.value - cost); + } + + emit NameRenewed(name, cost, expires); + } + + function setPriceOracle(PriceOracle _prices) public onlyOwner { + prices = _prices; + emit NewPriceOracle(address(prices)); + } + + function withdraw() public onlyOwner { + msg.sender.transfer(address(this).balance); + } +} diff --git a/contracts/mutants/ETHRegistrarController/3/TOR/diff_result_difft.json b/contracts/mutants/ETHRegistrarController/3/TOR/diff_result_difft.json new file mode 100644 index 00000000000..2aca22855a4 --- /dev/null +++ b/contracts/mutants/ETHRegistrarController/3/TOR/diff_result_difft.json @@ -0,0 +1,120 @@ +{ + "number_of_changes": 6, + "timing": 0.27283668518066406, + "diff_chunks": [ + [ + { + "lhs": { + "line_number": 62, + "changes": [ + { + "start": 12, + "end": 15, + "content": "msg", + "highlight": "normal" + }, + { + "start": 16, + "end": 22, + "content": "sender", + "highlight": "normal" + } + ] + }, + "rhs": { + "line_number": 62, + "changes": [ + { + "start": 12, + "end": 14, + "content": "tx", + "highlight": "normal" + }, + { + "start": 15, + "end": 21, + "content": "origin", + "highlight": "normal" + } + ] + } + } + ], + [ + { + "lhs": { + "line_number": 76, + "changes": [ + { + "start": 12, + "end": 15, + "content": "msg", + "highlight": "normal" + }, + { + "start": 16, + "end": 22, + "content": "sender", + "highlight": "normal" + } + ] + }, + "rhs": { + "line_number": 76, + "changes": [ + { + "start": 12, + "end": 14, + "content": "tx", + "highlight": "normal" + }, + { + "start": 15, + "end": 21, + "content": "origin", + "highlight": "normal" + } + ] + } + } + ], + [ + { + "lhs": { + "line_number": 88, + "changes": [ + { + "start": 12, + "end": 15, + "content": "msg", + "highlight": "normal" + }, + { + "start": 16, + "end": 22, + "content": "sender", + "highlight": "normal" + } + ] + }, + "rhs": { + "line_number": 88, + "changes": [ + { + "start": 12, + "end": 14, + "content": "tx", + "highlight": "normal" + }, + { + "start": 15, + "end": 21, + "content": "origin", + "highlight": "normal" + } + ] + } + } + ] + ] +} \ No newline at end of file diff --git a/contracts/mutants/ETHRegistrarController/3/VUR/ETHRegistrarController.sol b/contracts/mutants/ETHRegistrarController/3/VUR/ETHRegistrarController.sol new file mode 100644 index 00000000000..f2969bbe8db --- /dev/null +++ b/contracts/mutants/ETHRegistrarController/3/VUR/ETHRegistrarController.sol @@ -0,0 +1,103 @@ +pragma solidity ^0.5.0; + +import "./PriceOracle.sol"; +import "./BaseRegistrar.sol"; +import "./StringUtils.sol"; +import "openzeppelin-solidity/contracts/ownership/Ownable.sol"; + +/** + * @dev A registrar controller for registering and renewing names at fixed cost. + */ +contract ETHRegistrarController is Ownable { + using StringUtils for *; + + uint constant public MIN_COMMITMENT_AGE = 1 seconds; + uint constant public MAX_COMMITMENT_AGE = 48 seconds; + uint constant public MIN_REGISTRATION_DURATION = 28 seconds; + + BaseRegistrar base; + PriceOracle prices; + + mapping(bytes32=>uint) public commitments; + + event NameRegistered(string name, address indexed owner, uint cost, uint expires); + event NameRenewed(string name, uint cost, uint expires); + event NewPriceOracle(address indexed oracle); + + constructor(BaseRegistrar _base, PriceOracle _prices) public { + base = _base; + prices = _prices; + } + + function rentPrice(string memory name, uint duration) view public returns(uint) { + bytes32 hash = keccak256(bytes(name)); + return prices.price(name, base.nameExpires(uint256(hash)), duration); + } + + function valid(string memory name) public view returns(bool) { + return name.strlen() > 6; + } + + function available(string memory name) public view returns(bool) { + bytes32 label = keccak256(bytes(name)); + return valid(name) && base.available(uint256(label)); + } + // SWC-114-Transaction Order Dependence: L46-L49 + function makeCommitment(string memory name, bytes32 secret) pure public returns(bytes32) { + bytes32 label = keccak256(bytes(name)); + return keccak256(abi.encodePacked(label, secret)); + } + + function commit(bytes32 commitment) public { + require(commitments[commitment] + MAX_COMMITMENT_AGE < now); + commitments[commitment] = now; + } + // SWC-104-Unchecked Call Return Value: L56-L65 + function register(string calldata name, address owner, uint duration, bytes32 secret) external payable { + // Require a valid commitment + bytes32 commitment = makeCommitment(name, secret); + require(commitments[commitment] + MIN_COMMITMENT_AGE <= now); + + // If the commitment is too old, or the name is registered, stop + if(commitments[commitment] + MAX_COMMITMENT_AGE < now || !available(name)) { + msg.sender.transfer(msg.value); + return; + } + delete(commitments[commitment]); + + uint cost = rentPrice(name, duration); + require(duration >= MIN_REGISTRATION_DURATION); + require(msg.value >= cost); + + bytes32 label = keccak256(bytes(name)); + uint expires = base.register(uint256(label), owner, duration); + emit NameRegistered(name, owner, cost, expires); + + if(msg.value > cost) { + msg.sender.transfer(msg.value - cost); + } + } + + function renew(string calldata name, uint duration) external payable { + uint cost = rentPrice(name, duration); + require(msg.value >= cost); + + bytes32 label = keccak256(bytes(name)); + uint expires = base.renew(uint256(label), duration); + + if(msg.value > cost) { + msg.sender.transfer(msg.value - cost); + } + + emit NameRenewed(name, cost, expires); + } + + function setPriceOracle(PriceOracle _prices) public onlyOwner { + prices = _prices; + emit NewPriceOracle(address(prices)); + } + + function withdraw() public onlyOwner { + msg.sender.transfer(address(this).balance); + } +} diff --git a/contracts/mutants/ETHRegistrarController/3/VUR/diff_result_difft.json b/contracts/mutants/ETHRegistrarController/3/VUR/diff_result_difft.json new file mode 100644 index 00000000000..bddbc701440 --- /dev/null +++ b/contracts/mutants/ETHRegistrarController/3/VUR/diff_result_difft.json @@ -0,0 +1,80 @@ +{ + "number_of_changes": 3, + "timing": 0.15453767776489258, + "diff_chunks": [ + [ + { + "lhs": { + "line_number": 14, + "changes": [ + { + "start": 49, + "end": 54, + "content": "hours", + "highlight": "normal" + } + ] + }, + "rhs": { + "line_number": 14, + "changes": [ + { + "start": 49, + "end": 56, + "content": "seconds", + "highlight": "normal" + } + ] + } + }, + { + "lhs": { + "line_number": 15, + "changes": [ + { + "start": 56, + "end": 60, + "content": "days", + "highlight": "normal" + } + ] + }, + "rhs": { + "line_number": 15, + "changes": [ + { + "start": 56, + "end": 63, + "content": "seconds", + "highlight": "normal" + } + ] + } + }, + { + "lhs": { + "line_number": 13, + "changes": [ + { + "start": 48, + "end": 53, + "content": "hours", + "highlight": "normal" + } + ] + }, + "rhs": { + "line_number": 13, + "changes": [ + { + "start": 48, + "end": 55, + "content": "seconds", + "highlight": "normal" + } + ] + } + } + ] + ] +} \ No newline at end of file diff --git a/contracts/mutants/ETHRegistrarController/3/VVR/ETHRegistrarController.sol b/contracts/mutants/ETHRegistrarController/3/VVR/ETHRegistrarController.sol new file mode 100644 index 00000000000..659cad8e12f --- /dev/null +++ b/contracts/mutants/ETHRegistrarController/3/VVR/ETHRegistrarController.sol @@ -0,0 +1,103 @@ +pragma solidity ^0.5.0; + +import "./PriceOracle.sol"; +import "./BaseRegistrar.sol"; +import "./StringUtils.sol"; +import "openzeppelin-solidity/contracts/ownership/Ownable.sol"; + +/** + * @dev A registrar controller for registering and renewing names at fixed cost. + */ +contract ETHRegistrarController is Ownable { + using StringUtils for *; + + uint constant internal MIN_COMMITMENT_AGE = 1 hours; + uint constant internal MAX_COMMITMENT_AGE = 48 hours; + uint constant internal MIN_REGISTRATION_DURATION = 28 days; + + BaseRegistrar base; + PriceOracle prices; + + mapping(bytes32=>uint) public commitments; + + event NameRegistered(string name, address indexed owner, uint cost, uint expires); + event NameRenewed(string name, uint cost, uint expires); + event NewPriceOracle(address indexed oracle); + + constructor(BaseRegistrar _base, PriceOracle _prices) public { + base = _base; + prices = _prices; + } + + function rentPrice(string memory name, uint duration) view public returns(uint) { + bytes32 hash = keccak256(bytes(name)); + return prices.price(name, base.nameExpires(uint256(hash)), duration); + } + + function valid(string memory name) public view returns(bool) { + return name.strlen() > 6; + } + + function available(string memory name) public view returns(bool) { + bytes32 label = keccak256(bytes(name)); + return valid(name) && base.available(uint256(label)); + } + // SWC-114-Transaction Order Dependence: L46-L49 + function makeCommitment(string memory name, bytes32 secret) pure public returns(bytes32) { + bytes32 label = keccak256(bytes(name)); + return keccak256(abi.encodePacked(label, secret)); + } + + function commit(bytes32 commitment) public { + require(commitments[commitment] + MAX_COMMITMENT_AGE < now); + commitments[commitment] = now; + } + // SWC-104-Unchecked Call Return Value: L56-L65 + function register(string calldata name, address owner, uint duration, bytes32 secret) external payable { + // Require a valid commitment + bytes32 commitment = makeCommitment(name, secret); + require(commitments[commitment] + MIN_COMMITMENT_AGE <= now); + + // If the commitment is too old, or the name is registered, stop + if(commitments[commitment] + MAX_COMMITMENT_AGE < now || !available(name)) { + msg.sender.transfer(msg.value); + return; + } + delete(commitments[commitment]); + + uint cost = rentPrice(name, duration); + require(duration >= MIN_REGISTRATION_DURATION); + require(msg.value >= cost); + + bytes32 label = keccak256(bytes(name)); + uint expires = base.register(uint256(label), owner, duration); + emit NameRegistered(name, owner, cost, expires); + + if(msg.value > cost) { + msg.sender.transfer(msg.value - cost); + } + } + + function renew(string calldata name, uint duration) external payable { + uint cost = rentPrice(name, duration); + require(msg.value >= cost); + + bytes32 label = keccak256(bytes(name)); + uint expires = base.renew(uint256(label), duration); + + if(msg.value > cost) { + msg.sender.transfer(msg.value - cost); + } + + emit NameRenewed(name, cost, expires); + } + + function setPriceOracle(PriceOracle _prices) public onlyOwner { + prices = _prices; + emit NewPriceOracle(address(prices)); + } + + function withdraw() public onlyOwner { + msg.sender.transfer(address(this).balance); + } +} diff --git a/contracts/mutants/ETHRegistrarController/3/VVR/diff_result_difft.json b/contracts/mutants/ETHRegistrarController/3/VVR/diff_result_difft.json new file mode 100644 index 00000000000..45c6aa93cfc --- /dev/null +++ b/contracts/mutants/ETHRegistrarController/3/VVR/diff_result_difft.json @@ -0,0 +1,80 @@ +{ + "number_of_changes": 3, + "timing": 0.14668822288513184, + "diff_chunks": [ + [ + { + "lhs": { + "line_number": 13, + "changes": [ + { + "start": 18, + "end": 24, + "content": "public", + "highlight": "keyword" + } + ] + }, + "rhs": { + "line_number": 13, + "changes": [ + { + "start": 18, + "end": 26, + "content": "internal", + "highlight": "keyword" + } + ] + } + }, + { + "lhs": { + "line_number": 14, + "changes": [ + { + "start": 18, + "end": 24, + "content": "public", + "highlight": "keyword" + } + ] + }, + "rhs": { + "line_number": 14, + "changes": [ + { + "start": 18, + "end": 26, + "content": "internal", + "highlight": "keyword" + } + ] + } + }, + { + "lhs": { + "line_number": 15, + "changes": [ + { + "start": 18, + "end": 24, + "content": "public", + "highlight": "keyword" + } + ] + }, + "rhs": { + "line_number": 15, + "changes": [ + { + "start": 18, + "end": 26, + "content": "internal", + "highlight": "keyword" + } + ] + } + } + ] + ] +} \ No newline at end of file diff --git a/contracts/mutants/ETHRegistrarController/4/BOR/ETHRegistrarController.sol b/contracts/mutants/ETHRegistrarController/4/BOR/ETHRegistrarController.sol new file mode 100644 index 00000000000..5589ef9c113 --- /dev/null +++ b/contracts/mutants/ETHRegistrarController/4/BOR/ETHRegistrarController.sol @@ -0,0 +1,103 @@ +pragma solidity ^0.5.0; + +import "./PriceOracle.sol"; +import "./BaseRegistrar.sol"; +import "./StringUtils.sol"; +import "openzeppelin-solidity/contracts/ownership/Ownable.sol"; + +/** + * @dev A registrar controller for registering and renewing names at fixed cost. + */ +contract ETHRegistrarController is Ownable { + using StringUtils for *; + + uint constant public MIN_COMMITMENT_AGE = 1 hours; + uint constant public MAX_COMMITMENT_AGE = 48 hours; + uint constant public MIN_REGISTRATION_DURATION = 28 days; + + BaseRegistrar base; + PriceOracle prices; + + mapping(bytes32=>uint) public commitments; + + event NameRegistered(string name, address indexed owner, uint cost, uint expires); + event NameRenewed(string name, uint cost, uint expires); + event NewPriceOracle(address indexed oracle); + + constructor(BaseRegistrar _base, PriceOracle _prices) public { + base = _base; + prices = _prices; + } + + function rentPrice(string memory name, uint duration) view public returns(uint) { + bytes32 hash = keccak256(bytes(name)); + return prices.price(name, base.nameExpires(uint256(hash)), duration); + } + + function valid(string memory name) public view returns(bool) { + return name.strlen() >= 6; + } + + function available(string memory name) public view returns(bool) { + bytes32 label = keccak256(bytes(name)); + return valid(name) || base.available(uint256(label)); + } + // SWC-114-Transaction Order Dependence: L46-L49 + function makeCommitment(string memory name, bytes32 secret) pure public returns(bytes32) { + bytes32 label = keccak256(bytes(name)); + return keccak256(abi.encodePacked(label, secret)); + } + + function commit(bytes32 commitment) public { + require(commitments[commitment] - MAX_COMMITMENT_AGE <= now); + commitments[commitment] = now; + } + // SWC-104-Unchecked Call Return Value: L56-L65 + function register(string calldata name, address owner, uint duration, bytes32 secret) external payable { + // Require a valid commitment + bytes32 commitment = makeCommitment(name, secret); + require(commitments[commitment] + MIN_COMMITMENT_AGE <= now); + + // If the commitment is too old, or the name is registered, stop + if(commitments[commitment] + MAX_COMMITMENT_AGE < now || !available(name)) { + msg.sender.transfer(msg.value); + return; + } + delete(commitments[commitment]); + + uint cost = rentPrice(name, duration); + require(duration >= MIN_REGISTRATION_DURATION); + require(msg.value >= cost); + + bytes32 label = keccak256(bytes(name)); + uint expires = base.register(uint256(label), owner, duration); + emit NameRegistered(name, owner, cost, expires); + + if(msg.value > cost) { + msg.sender.transfer(msg.value - cost); + } + } + + function renew(string calldata name, uint duration) external payable { + uint cost = rentPrice(name, duration); + require(msg.value >= cost); + + bytes32 label = keccak256(bytes(name)); + uint expires = base.renew(uint256(label), duration); + + if(msg.value > cost) { + msg.sender.transfer(msg.value - cost); + } + + emit NameRenewed(name, cost, expires); + } + + function setPriceOracle(PriceOracle _prices) public onlyOwner { + prices = _prices; + emit NewPriceOracle(address(prices)); + } + + function withdraw() public onlyOwner { + msg.sender.transfer(address(this).balance); + } +} diff --git a/contracts/mutants/ETHRegistrarController/4/BOR/diff_result_difft.json b/contracts/mutants/ETHRegistrarController/4/BOR/diff_result_difft.json new file mode 100644 index 00000000000..b210651c34f --- /dev/null +++ b/contracts/mutants/ETHRegistrarController/4/BOR/diff_result_difft.json @@ -0,0 +1,96 @@ +{ + "number_of_changes": 4, + "timing": 0.31279611587524414, + "diff_chunks": [ + [ + { + "lhs": { + "line_number": 37, + "changes": [ + { + "start": 29, + "end": 30, + "content": ">", + "highlight": "keyword" + } + ] + }, + "rhs": { + "line_number": 37, + "changes": [ + { + "start": 29, + "end": 31, + "content": ">=", + "highlight": "keyword" + } + ] + } + } + ], + [ + { + "lhs": { + "line_number": 42, + "changes": [ + { + "start": 27, + "end": 29, + "content": "&&", + "highlight": "keyword" + } + ] + }, + "rhs": { + "line_number": 42, + "changes": [ + { + "start": 27, + "end": 29, + "content": "||", + "highlight": "keyword" + } + ] + } + } + ], + [ + { + "lhs": { + "line_number": 51, + "changes": [ + { + "start": 40, + "end": 41, + "content": "+", + "highlight": "keyword" + }, + { + "start": 61, + "end": 62, + "content": "<", + "highlight": "keyword" + } + ] + }, + "rhs": { + "line_number": 51, + "changes": [ + { + "start": 40, + "end": 41, + "content": "-", + "highlight": "keyword" + }, + { + "start": 61, + "end": 63, + "content": "<=", + "highlight": "keyword" + } + ] + } + } + ] + ] +} \ No newline at end of file diff --git a/contracts/mutants/ETHRegistrarController/4/DLR/ETHRegistrarController.sol b/contracts/mutants/ETHRegistrarController/4/DLR/ETHRegistrarController.sol new file mode 100644 index 00000000000..dd0b122a236 --- /dev/null +++ b/contracts/mutants/ETHRegistrarController/4/DLR/ETHRegistrarController.sol @@ -0,0 +1,103 @@ +pragma solidity ^0.5.0; + +import "./PriceOracle.sol"; +import "./BaseRegistrar.sol"; +import "./StringUtils.sol"; +import "openzeppelin-solidity/contracts/ownership/Ownable.sol"; + +/** + * @dev A registrar controller for registering and renewing names at fixed cost. + */ +contract ETHRegistrarController is Ownable { + using StringUtils for *; + + uint constant public MIN_COMMITMENT_AGE = 1 hours; + uint constant public MAX_COMMITMENT_AGE = 48 hours; + uint constant public MIN_REGISTRATION_DURATION = 28 days; + + BaseRegistrar base; + PriceOracle prices; + + mapping(bytes32=>uint) public commitments; + + event NameRegistered(string name, address indexed owner, uint cost, uint expires); + event NameRenewed(string name, uint cost, uint expires); + event NewPriceOracle(address indexed oracle); + + constructor(BaseRegistrar _base, PriceOracle _prices) public { + base = _base; + prices = _prices; + } + + function rentPrice(string storage name, uint duration) view public returns(uint) { + bytes32 hash = keccak256(bytes(name)); + return prices.price(name, base.nameExpires(uint256(hash)), duration); + } + + function valid(string storage name) public view returns(bool) { + return name.strlen() > 6; + } + + function available(string storage name) public view returns(bool) { + bytes32 label = keccak256(bytes(name)); + return valid(name) && base.available(uint256(label)); + } + // SWC-114-Transaction Order Dependence: L46-L49 + function makeCommitment(string storage name, bytes32 secret) pure public returns(bytes32) { + bytes32 label = keccak256(bytes(name)); + return keccak256(abi.encodePacked(label, secret)); + } + + function commit(bytes32 commitment) public { + require(commitments[commitment] + MAX_COMMITMENT_AGE < now); + commitments[commitment] = now; + } + // SWC-104-Unchecked Call Return Value: L56-L65 + function register(string calldata name, address owner, uint duration, bytes32 secret) external payable { + // Require a valid commitment + bytes32 commitment = makeCommitment(name, secret); + require(commitments[commitment] + MIN_COMMITMENT_AGE <= now); + + // If the commitment is too old, or the name is registered, stop + if(commitments[commitment] + MAX_COMMITMENT_AGE < now || !available(name)) { + msg.sender.transfer(msg.value); + return; + } + delete(commitments[commitment]); + + uint cost = rentPrice(name, duration); + require(duration >= MIN_REGISTRATION_DURATION); + require(msg.value >= cost); + + bytes32 label = keccak256(bytes(name)); + uint expires = base.register(uint256(label), owner, duration); + emit NameRegistered(name, owner, cost, expires); + + if(msg.value > cost) { + msg.sender.transfer(msg.value - cost); + } + } + + function renew(string calldata name, uint duration) external payable { + uint cost = rentPrice(name, duration); + require(msg.value >= cost); + + bytes32 label = keccak256(bytes(name)); + uint expires = base.renew(uint256(label), duration); + + if(msg.value > cost) { + msg.sender.transfer(msg.value - cost); + } + + emit NameRenewed(name, cost, expires); + } + + function setPriceOracle(PriceOracle _prices) public onlyOwner { + prices = _prices; + emit NewPriceOracle(address(prices)); + } + + function withdraw() public onlyOwner { + msg.sender.transfer(address(this).balance); + } +} diff --git a/contracts/mutants/ETHRegistrarController/4/DLR/diff_result_difft.json b/contracts/mutants/ETHRegistrarController/4/DLR/diff_result_difft.json new file mode 100644 index 00000000000..09d7c798f54 --- /dev/null +++ b/contracts/mutants/ETHRegistrarController/4/DLR/diff_result_difft.json @@ -0,0 +1,108 @@ +{ + "number_of_changes": 4, + "timing": 0.28476977348327637, + "diff_chunks": [ + [ + { + "lhs": { + "line_number": 31, + "changes": [ + { + "start": 30, + "end": 36, + "content": "memory", + "highlight": "keyword" + } + ] + }, + "rhs": { + "line_number": 31, + "changes": [ + { + "start": 30, + "end": 37, + "content": "storage", + "highlight": "keyword" + } + ] + } + } + ], + [ + { + "lhs": { + "line_number": 36, + "changes": [ + { + "start": 26, + "end": 32, + "content": "memory", + "highlight": "keyword" + } + ] + }, + "rhs": { + "line_number": 36, + "changes": [ + { + "start": 26, + "end": 33, + "content": "storage", + "highlight": "keyword" + } + ] + } + }, + { + "lhs": { + "line_number": 40, + "changes": [ + { + "start": 30, + "end": 36, + "content": "memory", + "highlight": "keyword" + } + ] + }, + "rhs": { + "line_number": 40, + "changes": [ + { + "start": 30, + "end": 37, + "content": "storage", + "highlight": "keyword" + } + ] + } + } + ], + [ + { + "lhs": { + "line_number": 45, + "changes": [ + { + "start": 35, + "end": 41, + "content": "memory", + "highlight": "keyword" + } + ] + }, + "rhs": { + "line_number": 45, + "changes": [ + { + "start": 35, + "end": 42, + "content": "storage", + "highlight": "keyword" + } + ] + } + } + ] + ] +} \ No newline at end of file diff --git a/contracts/mutants/ETHRegistrarController/4/ECS/ETHRegistrarController.sol b/contracts/mutants/ETHRegistrarController/4/ECS/ETHRegistrarController.sol new file mode 100644 index 00000000000..6c2336a0dc8 --- /dev/null +++ b/contracts/mutants/ETHRegistrarController/4/ECS/ETHRegistrarController.sol @@ -0,0 +1,103 @@ +pragma solidity ^0.5.0; + +import "./PriceOracle.sol"; +import "./BaseRegistrar.sol"; +import "./StringUtils.sol"; +import "openzeppelin-solidity/contracts/ownership/Ownable.sol"; + +/** + * @dev A registrar controller for registering and renewing names at fixed cost. + */ +contract ETHRegistrarController is Ownable { + using StringUtils for *; + + uint constant public MIN_COMMITMENT_AGE = 1 hours; + uint constant public MAX_COMMITMENT_AGE = 48 hours; + uint constant public MIN_REGISTRATION_DURATION = 28 days; + + BaseRegistrar base; + PriceOracle prices; + + mapping(bytes32=>uint) public commitments; + + event NameRegistered(string name, address indexed owner, uint cost, uint expires); + event NameRenewed(string name, uint cost, uint expires); + event NewPriceOracle(address indexed oracle); + + constructor(BaseRegistrar _base, PriceOracle _prices) public { + base = _base; + prices = _prices; + } + + function rentPrice(string memory name, uint duration) view public returns(uint) { + bytes32 hash = keccak256(bytes1(name)); + return prices.price(name, base.nameExpires(uint8(hash)), duration); + } + + function valid(string memory name) public view returns(bool) { + return name.strlen() > 6; + } + + function available(string memory name) public view returns(bool) { + bytes32 label = keccak256(bytes1(name)); + return valid(name) && base.available(uint8(label)); + } + // SWC-114-Transaction Order Dependence: L46-L49 + function makeCommitment(string memory name, bytes32 secret) pure public returns(bytes32) { + bytes32 label = keccak256(bytes(name)); + return keccak256(abi.encodePacked(label, secret)); + } + + function commit(bytes32 commitment) public { + require(commitments[commitment] + MAX_COMMITMENT_AGE < now); + commitments[commitment] = now; + } + // SWC-104-Unchecked Call Return Value: L56-L65 + function register(string calldata name, address owner, uint duration, bytes32 secret) external payable { + // Require a valid commitment + bytes32 commitment = makeCommitment(name, secret); + require(commitments[commitment] + MIN_COMMITMENT_AGE <= now); + + // If the commitment is too old, or the name is registered, stop + if(commitments[commitment] + MAX_COMMITMENT_AGE < now || !available(name)) { + msg.sender.transfer(msg.value); + return; + } + delete(commitments[commitment]); + + uint cost = rentPrice(name, duration); + require(duration >= MIN_REGISTRATION_DURATION); + require(msg.value >= cost); + + bytes32 label = keccak256(bytes(name)); + uint expires = base.register(uint256(label), owner, duration); + emit NameRegistered(name, owner, cost, expires); + + if(msg.value > cost) { + msg.sender.transfer(msg.value - cost); + } + } + + function renew(string calldata name, uint duration) external payable { + uint cost = rentPrice(name, duration); + require(msg.value >= cost); + + bytes32 label = keccak256(bytes(name)); + uint expires = base.renew(uint256(label), duration); + + if(msg.value > cost) { + msg.sender.transfer(msg.value - cost); + } + + emit NameRenewed(name, cost, expires); + } + + function setPriceOracle(PriceOracle _prices) public onlyOwner { + prices = _prices; + emit NewPriceOracle(address(prices)); + } + + function withdraw() public onlyOwner { + msg.sender.transfer(address(this).balance); + } +} diff --git a/contracts/mutants/ETHRegistrarController/4/ECS/diff_result_difft.json b/contracts/mutants/ETHRegistrarController/4/ECS/diff_result_difft.json new file mode 100644 index 00000000000..105d0af63f0 --- /dev/null +++ b/contracts/mutants/ETHRegistrarController/4/ECS/diff_result_difft.json @@ -0,0 +1,106 @@ +{ + "number_of_changes": 4, + "timing": 0.10746049880981445, + "diff_chunks": [ + [ + { + "lhs": { + "line_number": 33, + "changes": [ + { + "start": 51, + "end": 58, + "content": "uint256", + "highlight": "normal" + } + ] + }, + "rhs": { + "line_number": 33, + "changes": [ + { + "start": 51, + "end": 56, + "content": "uint8", + "highlight": "normal" + } + ] + } + }, + { + "lhs": { + "line_number": 32, + "changes": [ + { + "start": 33, + "end": 38, + "content": "bytes", + "highlight": "normal" + } + ] + }, + "rhs": { + "line_number": 32, + "changes": [ + { + "start": 33, + "end": 39, + "content": "bytes1", + "highlight": "normal" + } + ] + } + } + ], + [ + { + "lhs": { + "line_number": 42, + "changes": [ + { + "start": 45, + "end": 52, + "content": "uint256", + "highlight": "normal" + } + ] + }, + "rhs": { + "line_number": 42, + "changes": [ + { + "start": 45, + "end": 50, + "content": "uint8", + "highlight": "normal" + } + ] + } + }, + { + "lhs": { + "line_number": 41, + "changes": [ + { + "start": 34, + "end": 39, + "content": "bytes", + "highlight": "normal" + } + ] + }, + "rhs": { + "line_number": 41, + "changes": [ + { + "start": 34, + "end": 40, + "content": "bytes1", + "highlight": "normal" + } + ] + } + } + ] + ] +} \ No newline at end of file diff --git a/contracts/mutants/ETHRegistrarController/4/EHC/ETHRegistrarController.sol b/contracts/mutants/ETHRegistrarController/4/EHC/ETHRegistrarController.sol new file mode 100644 index 00000000000..6ad20c5d92d --- /dev/null +++ b/contracts/mutants/ETHRegistrarController/4/EHC/ETHRegistrarController.sol @@ -0,0 +1,103 @@ +pragma solidity ^0.5.0; + +import "./PriceOracle.sol"; +import "./BaseRegistrar.sol"; +import "./StringUtils.sol"; +import "openzeppelin-solidity/contracts/ownership/Ownable.sol"; + +/** + * @dev A registrar controller for registering and renewing names at fixed cost. + */ +contract ETHRegistrarController is Ownable { + using StringUtils for *; + + uint constant public MIN_COMMITMENT_AGE = 1 hours; + uint constant public MAX_COMMITMENT_AGE = 48 hours; + uint constant public MIN_REGISTRATION_DURATION = 28 days; + + BaseRegistrar base; + PriceOracle prices; + + mapping(bytes32=>uint) public commitments; + + event NameRegistered(string name, address indexed owner, uint cost, uint expires); + event NameRenewed(string name, uint cost, uint expires); + event NewPriceOracle(address indexed oracle); + + constructor(BaseRegistrar _base, PriceOracle _prices) public { + base = _base; + prices = _prices; + } + + function rentPrice(string memory name, uint duration) view public returns(uint) { + bytes32 hash = keccak256(bytes(name)); + return prices.price(name, base.nameExpires(uint256(hash)), duration); + } + + function valid(string memory name) public view returns(bool) { + return name.strlen() > 6; + } + + function available(string memory name) public view returns(bool) { + bytes32 label = keccak256(bytes(name)); + return valid(name) && base.available(uint256(label)); + } + // SWC-114-Transaction Order Dependence: L46-L49 + function makeCommitment(string memory name, bytes32 secret) pure public returns(bytes32) { + bytes32 label = keccak256(bytes(name)); + return keccak256(abi.encodePacked(label, secret)); + } + + function commit(bytes32 commitment) public { + /* require(commitments[commitment] + MAX_COMMITMENT_AGE < now); */ + commitments[commitment] = now; + } + // SWC-104-Unchecked Call Return Value: L56-L65 + function register(string calldata name, address owner, uint duration, bytes32 secret) external payable { + // Require a valid commitment + bytes32 commitment = makeCommitment(name, secret); + /* require(commitments[commitment] + MIN_COMMITMENT_AGE <= now); */ + + // If the commitment is too old, or the name is registered, stop + if(commitments[commitment] + MAX_COMMITMENT_AGE < now || !available(name)) { + msg.sender.transfer(msg.value); + return; + } + delete(commitments[commitment]); + + uint cost = rentPrice(name, duration); + /* require(duration >= MIN_REGISTRATION_DURATION); */ + /* require(msg.value >= cost); */ + + bytes32 label = keccak256(bytes(name)); + uint expires = base.register(uint256(label), owner, duration); + emit NameRegistered(name, owner, cost, expires); + + if(msg.value > cost) { + msg.sender.transfer(msg.value - cost); + } + } + + function renew(string calldata name, uint duration) external payable { + uint cost = rentPrice(name, duration); + require(msg.value >= cost); + + bytes32 label = keccak256(bytes(name)); + uint expires = base.renew(uint256(label), duration); + + if(msg.value > cost) { + msg.sender.transfer(msg.value - cost); + } + + emit NameRenewed(name, cost, expires); + } + + function setPriceOracle(PriceOracle _prices) public onlyOwner { + prices = _prices; + emit NewPriceOracle(address(prices)); + } + + function withdraw() public onlyOwner { + msg.sender.transfer(address(this).balance); + } +} diff --git a/contracts/mutants/ETHRegistrarController/4/EHC/diff_result_difft.json b/contracts/mutants/ETHRegistrarController/4/EHC/diff_result_difft.json new file mode 100644 index 00000000000..894acec30e8 --- /dev/null +++ b/contracts/mutants/ETHRegistrarController/4/EHC/diff_result_difft.json @@ -0,0 +1,300 @@ +{ + "number_of_changes": 36, + "timing": 0.21207284927368164, + "diff_chunks": [ + [ + { + "lhs": { + "line_number": 51, + "changes": [ + { + "start": 8, + "end": 15, + "content": "require", + "highlight": "normal" + }, + { + "start": 15, + "end": 16, + "content": "(", + "highlight": "delimiter" + }, + { + "start": 16, + "end": 27, + "content": "commitments", + "highlight": "normal" + }, + { + "start": 27, + "end": 28, + "content": "[", + "highlight": "delimiter" + }, + { + "start": 28, + "end": 38, + "content": "commitment", + "highlight": "normal" + }, + { + "start": 38, + "end": 39, + "content": "]", + "highlight": "delimiter" + }, + { + "start": 40, + "end": 41, + "content": "+", + "highlight": "keyword" + }, + { + "start": 42, + "end": 60, + "content": "MAX_COMMITMENT_AGE", + "highlight": "normal" + }, + { + "start": 61, + "end": 62, + "content": "<", + "highlight": "keyword" + }, + { + "start": 63, + "end": 66, + "content": "now", + "highlight": "normal" + }, + { + "start": 66, + "end": 67, + "content": ")", + "highlight": "delimiter" + } + ] + }, + "rhs": { + "line_number": 51, + "changes": [ + { + "start": 8, + "end": 74, + "content": "/* require(commitments[commitment] + MAX_COMMITMENT_AGE < now); */", + "highlight": "comment" + } + ] + } + } + ], + [ + { + "lhs": { + "line_number": 58, + "changes": [ + { + "start": 8, + "end": 15, + "content": "require", + "highlight": "normal" + }, + { + "start": 15, + "end": 16, + "content": "(", + "highlight": "delimiter" + }, + { + "start": 16, + "end": 27, + "content": "commitments", + "highlight": "normal" + }, + { + "start": 27, + "end": 28, + "content": "[", + "highlight": "delimiter" + }, + { + "start": 28, + "end": 38, + "content": "commitment", + "highlight": "normal" + }, + { + "start": 38, + "end": 39, + "content": "]", + "highlight": "delimiter" + }, + { + "start": 40, + "end": 41, + "content": "+", + "highlight": "keyword" + }, + { + "start": 42, + "end": 60, + "content": "MIN_COMMITMENT_AGE", + "highlight": "normal" + }, + { + "start": 61, + "end": 63, + "content": "<=", + "highlight": "keyword" + }, + { + "start": 64, + "end": 67, + "content": "now", + "highlight": "normal" + }, + { + "start": 67, + "end": 68, + "content": ")", + "highlight": "delimiter" + } + ] + }, + "rhs": { + "line_number": 58, + "changes": [ + { + "start": 8, + "end": 75, + "content": "/* require(commitments[commitment] + MIN_COMMITMENT_AGE <= now); */", + "highlight": "comment" + } + ] + } + } + ], + [ + { + "lhs": { + "line_number": 68, + "changes": [ + { + "start": 8, + "end": 15, + "content": "require", + "highlight": "normal" + }, + { + "start": 15, + "end": 16, + "content": "(", + "highlight": "delimiter" + }, + { + "start": 16, + "end": 24, + "content": "duration", + "highlight": "normal" + }, + { + "start": 25, + "end": 27, + "content": ">=", + "highlight": "keyword" + }, + { + "start": 28, + "end": 53, + "content": "MIN_REGISTRATION_DURATION", + "highlight": "normal" + }, + { + "start": 53, + "end": 54, + "content": ")", + "highlight": "delimiter" + } + ] + }, + "rhs": { + "line_number": 68, + "changes": [ + { + "start": 8, + "end": 61, + "content": "/* require(duration >= MIN_REGISTRATION_DURATION); */", + "highlight": "comment" + } + ] + } + }, + { + "lhs": { + "line_number": 69, + "changes": [ + { + "start": 8, + "end": 15, + "content": "require", + "highlight": "normal" + }, + { + "start": 15, + "end": 16, + "content": "(", + "highlight": "delimiter" + }, + { + "start": 16, + "end": 19, + "content": "msg", + "highlight": "normal" + }, + { + "start": 19, + "end": 20, + "content": ".", + "highlight": "normal" + }, + { + "start": 20, + "end": 25, + "content": "value", + "highlight": "normal" + }, + { + "start": 26, + "end": 28, + "content": ">=", + "highlight": "keyword" + }, + { + "start": 29, + "end": 33, + "content": "cost", + "highlight": "normal" + }, + { + "start": 33, + "end": 34, + "content": ")", + "highlight": "delimiter" + } + ] + }, + "rhs": { + "line_number": 69, + "changes": [ + { + "start": 8, + "end": 41, + "content": "/* require(msg.value >= cost); */", + "highlight": "comment" + } + ] + } + } + ] + ] +} \ No newline at end of file diff --git a/contracts/mutants/ETHRegistrarController/4/ETR/ETHRegistrarController.sol b/contracts/mutants/ETHRegistrarController/4/ETR/ETHRegistrarController.sol new file mode 100644 index 00000000000..6198e865ca7 --- /dev/null +++ b/contracts/mutants/ETHRegistrarController/4/ETR/ETHRegistrarController.sol @@ -0,0 +1,103 @@ +pragma solidity ^0.5.0; + +import "./PriceOracle.sol"; +import "./BaseRegistrar.sol"; +import "./StringUtils.sol"; +import "openzeppelin-solidity/contracts/ownership/Ownable.sol"; + +/** + * @dev A registrar controller for registering and renewing names at fixed cost. + */ +contract ETHRegistrarController is Ownable { + using StringUtils for *; + + uint constant public MIN_COMMITMENT_AGE = 1 hours; + uint constant public MAX_COMMITMENT_AGE = 48 hours; + uint constant public MIN_REGISTRATION_DURATION = 28 days; + + BaseRegistrar base; + PriceOracle prices; + + mapping(bytes32=>uint) public commitments; + + event NameRegistered(string name, address indexed owner, uint cost, uint expires); + event NameRenewed(string name, uint cost, uint expires); + event NewPriceOracle(address indexed oracle); + + constructor(BaseRegistrar _base, PriceOracle _prices) public { + base = _base; + prices = _prices; + } + + function rentPrice(string memory name, uint duration) view public returns(uint) { + bytes32 hash = keccak256(bytes(name)); + return prices.price(name, base.nameExpires(uint256(hash)), duration); + } + + function valid(string memory name) public view returns(bool) { + return name.strlen() > 6; + } + + function available(string memory name) public view returns(bool) { + bytes32 label = keccak256(bytes(name)); + return valid(name) && base.available(uint256(label)); + } + // SWC-114-Transaction Order Dependence: L46-L49 + function makeCommitment(string memory name, bytes32 secret) pure public returns(bytes32) { + bytes32 label = keccak256(bytes(name)); + return keccak256(abi.encodePacked(label, secret)); + } + + function commit(bytes32 commitment) public { + require(commitments[commitment] + MAX_COMMITMENT_AGE < now); + commitments[commitment] = now; + } + // SWC-104-Unchecked Call Return Value: L56-L65 + function register(string calldata name, address owner, uint duration, bytes32 secret) external payable { + // Require a valid commitment + bytes32 commitment = makeCommitment(name, secret); + require(commitments[commitment] + MIN_COMMITMENT_AGE <= now); + + // If the commitment is too old, or the name is registered, stop + if(commitments[commitment] + MAX_COMMITMENT_AGE < now || !available(name)) { + msg.sender.send(msg.value); + return; + } + delete(commitments[commitment]); + + uint cost = rentPrice(name, duration); + require(duration >= MIN_REGISTRATION_DURATION); + require(msg.value >= cost); + + bytes32 label = keccak256(bytes(name)); + uint expires = base.register(uint256(label), owner, duration); + emit NameRegistered(name, owner, cost, expires); + + if(msg.value > cost) { + msg.sender.send(msg.value - cost); + } + } + + function renew(string calldata name, uint duration) external payable { + uint cost = rentPrice(name, duration); + require(msg.value >= cost); + + bytes32 label = keccak256(bytes(name)); + uint expires = base.renew(uint256(label), duration); + + if(msg.value > cost) { + msg.sender.send(msg.value - cost); + } + + emit NameRenewed(name, cost, expires); + } + + function setPriceOracle(PriceOracle _prices) public onlyOwner { + prices = _prices; + emit NewPriceOracle(address(prices)); + } + + function withdraw() public onlyOwner { + msg.sender.send(address(this).balance); + } +} diff --git a/contracts/mutants/ETHRegistrarController/4/ETR/diff_result_difft.json b/contracts/mutants/ETHRegistrarController/4/ETR/diff_result_difft.json new file mode 100644 index 00000000000..1d30acc5b43 --- /dev/null +++ b/contracts/mutants/ETHRegistrarController/4/ETR/diff_result_difft.json @@ -0,0 +1,110 @@ +{ + "number_of_changes": 4, + "timing": 0.14528393745422363, + "diff_chunks": [ + [ + { + "lhs": { + "line_number": 62, + "changes": [ + { + "start": 23, + "end": 31, + "content": "transfer", + "highlight": "normal" + } + ] + }, + "rhs": { + "line_number": 62, + "changes": [ + { + "start": 23, + "end": 27, + "content": "send", + "highlight": "normal" + } + ] + } + } + ], + [ + { + "lhs": { + "line_number": 76, + "changes": [ + { + "start": 23, + "end": 31, + "content": "transfer", + "highlight": "normal" + } + ] + }, + "rhs": { + "line_number": 76, + "changes": [ + { + "start": 23, + "end": 27, + "content": "send", + "highlight": "normal" + } + ] + } + } + ], + [ + { + "lhs": { + "line_number": 88, + "changes": [ + { + "start": 23, + "end": 31, + "content": "transfer", + "highlight": "normal" + } + ] + }, + "rhs": { + "line_number": 88, + "changes": [ + { + "start": 23, + "end": 27, + "content": "send", + "highlight": "normal" + } + ] + } + } + ], + [ + { + "lhs": { + "line_number": 100, + "changes": [ + { + "start": 19, + "end": 27, + "content": "transfer", + "highlight": "normal" + } + ] + }, + "rhs": { + "line_number": 100, + "changes": [ + { + "start": 19, + "end": 23, + "content": "send", + "highlight": "normal" + } + ] + } + } + ] + ] +} \ No newline at end of file diff --git a/contracts/mutants/ETHRegistrarController/4/FVR/ETHRegistrarController.sol b/contracts/mutants/ETHRegistrarController/4/FVR/ETHRegistrarController.sol new file mode 100644 index 00000000000..6c3ef4ecac6 --- /dev/null +++ b/contracts/mutants/ETHRegistrarController/4/FVR/ETHRegistrarController.sol @@ -0,0 +1,103 @@ +pragma solidity ^0.5.0; + +import "./PriceOracle.sol"; +import "./BaseRegistrar.sol"; +import "./StringUtils.sol"; +import "openzeppelin-solidity/contracts/ownership/Ownable.sol"; + +/** + * @dev A registrar controller for registering and renewing names at fixed cost. + */ +contract ETHRegistrarController is Ownable { + using StringUtils for *; + + uint constant public MIN_COMMITMENT_AGE = 1 hours; + uint constant public MAX_COMMITMENT_AGE = 48 hours; + uint constant public MIN_REGISTRATION_DURATION = 28 days; + + BaseRegistrar base; + PriceOracle prices; + + mapping(bytes32=>uint) public commitments; + + event NameRegistered(string name, address indexed owner, uint cost, uint expires); + event NameRenewed(string name, uint cost, uint expires); + event NewPriceOracle(address indexed oracle); + + constructor(BaseRegistrar _base, PriceOracle _prices) internal { + base = _base; + prices = _prices; + } + + function rentPrice(string memory name, uint duration) view external returns(uint) { + bytes32 hash = keccak256(bytes(name)); + return prices.price(name, base.nameExpires(uint256(hash)), duration); + } + + function valid(string memory name) external view returns(bool) { + return name.strlen() > 6; + } + + function available(string memory name) external view returns(bool) { + bytes32 label = keccak256(bytes(name)); + return valid(name) && base.available(uint256(label)); + } + // SWC-114-Transaction Order Dependence: L46-L49 + function makeCommitment(string memory name, bytes32 secret) pure public returns(bytes32) { + bytes32 label = keccak256(bytes(name)); + return keccak256(abi.encodePacked(label, secret)); + } + + function commit(bytes32 commitment) public { + require(commitments[commitment] + MAX_COMMITMENT_AGE < now); + commitments[commitment] = now; + } + // SWC-104-Unchecked Call Return Value: L56-L65 + function register(string calldata name, address owner, uint duration, bytes32 secret) external payable { + // Require a valid commitment + bytes32 commitment = makeCommitment(name, secret); + require(commitments[commitment] + MIN_COMMITMENT_AGE <= now); + + // If the commitment is too old, or the name is registered, stop + if(commitments[commitment] + MAX_COMMITMENT_AGE < now || !available(name)) { + msg.sender.transfer(msg.value); + return; + } + delete(commitments[commitment]); + + uint cost = rentPrice(name, duration); + require(duration >= MIN_REGISTRATION_DURATION); + require(msg.value >= cost); + + bytes32 label = keccak256(bytes(name)); + uint expires = base.register(uint256(label), owner, duration); + emit NameRegistered(name, owner, cost, expires); + + if(msg.value > cost) { + msg.sender.transfer(msg.value - cost); + } + } + + function renew(string calldata name, uint duration) external payable { + uint cost = rentPrice(name, duration); + require(msg.value >= cost); + + bytes32 label = keccak256(bytes(name)); + uint expires = base.renew(uint256(label), duration); + + if(msg.value > cost) { + msg.sender.transfer(msg.value - cost); + } + + emit NameRenewed(name, cost, expires); + } + + function setPriceOracle(PriceOracle _prices) public onlyOwner { + prices = _prices; + emit NewPriceOracle(address(prices)); + } + + function withdraw() public onlyOwner { + msg.sender.transfer(address(this).balance); + } +} diff --git a/contracts/mutants/ETHRegistrarController/4/FVR/diff_result_difft.json b/contracts/mutants/ETHRegistrarController/4/FVR/diff_result_difft.json new file mode 100644 index 00000000000..2ecc43455bc --- /dev/null +++ b/contracts/mutants/ETHRegistrarController/4/FVR/diff_result_difft.json @@ -0,0 +1,108 @@ +{ + "number_of_changes": 4, + "timing": 0.2731208801269531, + "diff_chunks": [ + [ + { + "lhs": { + "line_number": 26, + "changes": [ + { + "start": 58, + "end": 64, + "content": "public", + "highlight": "keyword" + } + ] + }, + "rhs": { + "line_number": 26, + "changes": [ + { + "start": 58, + "end": 66, + "content": "internal", + "highlight": "keyword" + } + ] + } + } + ], + [ + { + "lhs": { + "line_number": 31, + "changes": [ + { + "start": 63, + "end": 69, + "content": "public", + "highlight": "keyword" + } + ] + }, + "rhs": { + "line_number": 31, + "changes": [ + { + "start": 63, + "end": 71, + "content": "external", + "highlight": "keyword" + } + ] + } + } + ], + [ + { + "lhs": { + "line_number": 40, + "changes": [ + { + "start": 43, + "end": 49, + "content": "public", + "highlight": "keyword" + } + ] + }, + "rhs": { + "line_number": 40, + "changes": [ + { + "start": 43, + "end": 51, + "content": "external", + "highlight": "keyword" + } + ] + } + }, + { + "lhs": { + "line_number": 36, + "changes": [ + { + "start": 39, + "end": 45, + "content": "public", + "highlight": "keyword" + } + ] + }, + "rhs": { + "line_number": 36, + "changes": [ + { + "start": 39, + "end": 47, + "content": "external", + "highlight": "keyword" + } + ] + } + } + ] + ] +} \ No newline at end of file diff --git a/contracts/mutants/ETHRegistrarController/4/GVR/ETHRegistrarController.sol b/contracts/mutants/ETHRegistrarController/4/GVR/ETHRegistrarController.sol new file mode 100644 index 00000000000..ab238f1dcb1 --- /dev/null +++ b/contracts/mutants/ETHRegistrarController/4/GVR/ETHRegistrarController.sol @@ -0,0 +1,103 @@ +pragma solidity ^0.5.0; + +import "./PriceOracle.sol"; +import "./BaseRegistrar.sol"; +import "./StringUtils.sol"; +import "openzeppelin-solidity/contracts/ownership/Ownable.sol"; + +/** + * @dev A registrar controller for registering and renewing names at fixed cost. + */ +contract ETHRegistrarController is Ownable { + using StringUtils for *; + + uint constant public MIN_COMMITMENT_AGE = 1 hours; + uint constant public MAX_COMMITMENT_AGE = 48 hours; + uint constant public MIN_REGISTRATION_DURATION = 28 days; + + BaseRegistrar base; + PriceOracle prices; + + mapping(bytes32=>uint) public commitments; + + event NameRegistered(string name, address indexed owner, uint cost, uint expires); + event NameRenewed(string name, uint cost, uint expires); + event NewPriceOracle(address indexed oracle); + + constructor(BaseRegistrar _base, PriceOracle _prices) public { + base = _base; + prices = _prices; + } + + function rentPrice(string memory name, uint duration) view public returns(uint) { + bytes32 hash = keccak256(bytes(name)); + return prices.price(name, base.nameExpires(uint256(hash)), duration); + } + + function valid(string memory name) public view returns(bool) { + return name.strlen() > 6; + } + + function available(string memory name) public view returns(bool) { + bytes32 label = keccak256(bytes(name)); + return valid(name) && base.available(uint256(label)); + } + // SWC-114-Transaction Order Dependence: L46-L49 + function makeCommitment(string memory name, bytes32 secret) pure public returns(bytes32) { + bytes32 label = keccak256(bytes(name)); + return keccak256(abi.encodePacked(label, secret)); + } + + function commit(bytes32 commitment) public { + require(commitments[commitment] + MAX_COMMITMENT_AGE < block.difficulty); + commitments[commitment] = block.difficulty; + } + // SWC-104-Unchecked Call Return Value: L56-L65 + function register(string calldata name, address owner, uint duration, bytes32 secret) external payable { + // Require a valid commitment + bytes32 commitment = makeCommitment(name, secret); + require(commitments[commitment] + MIN_COMMITMENT_AGE <= block.difficulty); + + // If the commitment is too old, or the name is registered, stop + if(commitments[commitment] + MAX_COMMITMENT_AGE < block.difficulty || !available(name)) { + msg.sender.transfer(msg.value); + return; + } + delete(commitments[commitment]); + + uint cost = rentPrice(name, duration); + require(duration >= MIN_REGISTRATION_DURATION); + require(msg.value >= cost); + + bytes32 label = keccak256(bytes(name)); + uint expires = base.register(uint256(label), owner, duration); + emit NameRegistered(name, owner, cost, expires); + + if(msg.value > cost) { + msg.sender.transfer(msg.value - cost); + } + } + + function renew(string calldata name, uint duration) external payable { + uint cost = rentPrice(name, duration); + require(msg.value >= cost); + + bytes32 label = keccak256(bytes(name)); + uint expires = base.renew(uint256(label), duration); + + if(msg.value > cost) { + msg.sender.transfer(msg.value - cost); + } + + emit NameRenewed(name, cost, expires); + } + + function setPriceOracle(PriceOracle _prices) public onlyOwner { + prices = _prices; + emit NewPriceOracle(address(prices)); + } + + function withdraw() public onlyOwner { + msg.sender.transfer(address(this).balance); + } +} diff --git a/contracts/mutants/ETHRegistrarController/4/GVR/diff_result_difft.json b/contracts/mutants/ETHRegistrarController/4/GVR/diff_result_difft.json new file mode 100644 index 00000000000..6d8d81fc6fc --- /dev/null +++ b/contracts/mutants/ETHRegistrarController/4/GVR/diff_result_difft.json @@ -0,0 +1,154 @@ +{ + "number_of_changes": 12, + "timing": 0.12365508079528809, + "diff_chunks": [ + [ + { + "lhs": { + "line_number": 51, + "changes": [ + { + "start": 63, + "end": 66, + "content": "now", + "highlight": "normal" + } + ] + }, + "rhs": { + "line_number": 51, + "changes": [ + { + "start": 63, + "end": 68, + "content": "block", + "highlight": "normal" + }, + { + "start": 68, + "end": 69, + "content": ".", + "highlight": "normal" + }, + { + "start": 69, + "end": 79, + "content": "difficulty", + "highlight": "normal" + } + ] + } + }, + { + "lhs": { + "line_number": 52, + "changes": [ + { + "start": 34, + "end": 37, + "content": "now", + "highlight": "normal" + } + ] + }, + "rhs": { + "line_number": 52, + "changes": [ + { + "start": 34, + "end": 39, + "content": "block", + "highlight": "normal" + }, + { + "start": 39, + "end": 40, + "content": ".", + "highlight": "normal" + }, + { + "start": 40, + "end": 50, + "content": "difficulty", + "highlight": "normal" + } + ] + } + } + ], + [ + { + "lhs": { + "line_number": 61, + "changes": [ + { + "start": 58, + "end": 61, + "content": "now", + "highlight": "normal" + } + ] + }, + "rhs": { + "line_number": 61, + "changes": [ + { + "start": 58, + "end": 63, + "content": "block", + "highlight": "normal" + }, + { + "start": 63, + "end": 64, + "content": ".", + "highlight": "normal" + }, + { + "start": 64, + "end": 74, + "content": "difficulty", + "highlight": "normal" + } + ] + } + }, + { + "lhs": { + "line_number": 58, + "changes": [ + { + "start": 64, + "end": 67, + "content": "now", + "highlight": "normal" + } + ] + }, + "rhs": { + "line_number": 58, + "changes": [ + { + "start": 64, + "end": 69, + "content": "block", + "highlight": "normal" + }, + { + "start": 69, + "end": 70, + "content": ".", + "highlight": "normal" + }, + { + "start": 70, + "end": 80, + "content": "difficulty", + "highlight": "normal" + } + ] + } + } + ] + ] +} \ No newline at end of file diff --git a/contracts/mutants/ETHRegistrarController/4/ILR/ETHRegistrarController.sol b/contracts/mutants/ETHRegistrarController/4/ILR/ETHRegistrarController.sol new file mode 100644 index 00000000000..bb44d05101d --- /dev/null +++ b/contracts/mutants/ETHRegistrarController/4/ILR/ETHRegistrarController.sol @@ -0,0 +1,103 @@ +pragma solidity ^0.5.0; + +import "./PriceOracle.sol"; +import "./BaseRegistrar.sol"; +import "./StringUtils.sol"; +import "openzeppelin-solidity/contracts/ownership/Ownable.sol"; + +/** + * @dev A registrar controller for registering and renewing names at fixed cost. + */ +contract ETHRegistrarController is Ownable { + using StringUtils for *; + + uint constant public MIN_COMMITMENT_AGE = 0 hours; + uint constant public MAX_COMMITMENT_AGE = 47 hours; + uint constant public MIN_REGISTRATION_DURATION = 27 days; + + BaseRegistrar base; + PriceOracle prices; + + mapping(bytes32=>uint) public commitments; + + event NameRegistered(string name, address indexed owner, uint cost, uint expires); + event NameRenewed(string name, uint cost, uint expires); + event NewPriceOracle(address indexed oracle); + + constructor(BaseRegistrar _base, PriceOracle _prices) public { + base = _base; + prices = _prices; + } + + function rentPrice(string memory name, uint duration) view public returns(uint) { + bytes32 hash = keccak256(bytes(name)); + return prices.price(name, base.nameExpires(uint256(hash)), duration); + } + + function valid(string memory name) public view returns(bool) { + return name.strlen() > 5; + } + + function available(string memory name) public view returns(bool) { + bytes32 label = keccak256(bytes(name)); + return valid(name) && base.available(uint256(label)); + } + // SWC-114-Transaction Order Dependence: L46-L49 + function makeCommitment(string memory name, bytes32 secret) pure public returns(bytes32) { + bytes32 label = keccak256(bytes(name)); + return keccak256(abi.encodePacked(label, secret)); + } + + function commit(bytes32 commitment) public { + require(commitments[commitment] + MAX_COMMITMENT_AGE < now); + commitments[commitment] = now; + } + // SWC-104-Unchecked Call Return Value: L56-L65 + function register(string calldata name, address owner, uint duration, bytes32 secret) external payable { + // Require a valid commitment + bytes32 commitment = makeCommitment(name, secret); + require(commitments[commitment] + MIN_COMMITMENT_AGE <= now); + + // If the commitment is too old, or the name is registered, stop + if(commitments[commitment] + MAX_COMMITMENT_AGE < now || !available(name)) { + msg.sender.transfer(msg.value); + return; + } + delete(commitments[commitment]); + + uint cost = rentPrice(name, duration); + require(duration >= MIN_REGISTRATION_DURATION); + require(msg.value >= cost); + + bytes32 label = keccak256(bytes(name)); + uint expires = base.register(uint256(label), owner, duration); + emit NameRegistered(name, owner, cost, expires); + + if(msg.value > cost) { + msg.sender.transfer(msg.value - cost); + } + } + + function renew(string calldata name, uint duration) external payable { + uint cost = rentPrice(name, duration); + require(msg.value >= cost); + + bytes32 label = keccak256(bytes(name)); + uint expires = base.renew(uint256(label), duration); + + if(msg.value > cost) { + msg.sender.transfer(msg.value - cost); + } + + emit NameRenewed(name, cost, expires); + } + + function setPriceOracle(PriceOracle _prices) public onlyOwner { + prices = _prices; + emit NewPriceOracle(address(prices)); + } + + function withdraw() public onlyOwner { + msg.sender.transfer(address(this).balance); + } +} diff --git a/contracts/mutants/ETHRegistrarController/4/ILR/diff_result_difft.json b/contracts/mutants/ETHRegistrarController/4/ILR/diff_result_difft.json new file mode 100644 index 00000000000..96b58f486d5 --- /dev/null +++ b/contracts/mutants/ETHRegistrarController/4/ILR/diff_result_difft.json @@ -0,0 +1,32 @@ +{ + "number_of_changes": 1, + "timing": 0.16515278816223145, + "diff_chunks": [ + [ + { + "lhs": { + "line_number": 37, + "changes": [ + { + "start": 31, + "end": 32, + "content": "6", + "highlight": "normal" + } + ] + }, + "rhs": { + "line_number": 37, + "changes": [ + { + "start": 31, + "end": 32, + "content": "5", + "highlight": "normal" + } + ] + } + } + ] + ] +} \ No newline at end of file diff --git a/contracts/mutants/ETHRegistrarController/4/MCR/ETHRegistrarController.sol b/contracts/mutants/ETHRegistrarController/4/MCR/ETHRegistrarController.sol new file mode 100644 index 00000000000..0ace356d81a --- /dev/null +++ b/contracts/mutants/ETHRegistrarController/4/MCR/ETHRegistrarController.sol @@ -0,0 +1,103 @@ +pragma solidity ^0.5.0; + +import "./PriceOracle.sol"; +import "./BaseRegistrar.sol"; +import "./StringUtils.sol"; +import "openzeppelin-solidity/contracts/ownership/Ownable.sol"; + +/** + * @dev A registrar controller for registering and renewing names at fixed cost. + */ +contract ETHRegistrarController is Ownable { + using StringUtils for *; + + uint constant public MIN_COMMITMENT_AGE = 1 hours; + uint constant public MAX_COMMITMENT_AGE = 48 hours; + uint constant public MIN_REGISTRATION_DURATION = 28 days; + + BaseRegistrar base; + PriceOracle prices; + + mapping(bytes32=>uint) public commitments; + + event NameRegistered(string name, address indexed owner, uint cost, uint expires); + event NameRenewed(string name, uint cost, uint expires); + event NewPriceOracle(address indexed oracle); + + constructor(BaseRegistrar _base, PriceOracle _prices) public { + base = _base; + prices = _prices; + } + + function rentPrice(string memory name, uint duration) view public returns(uint) { + bytes32 hash = sha256(bytes(name)); + return prices.price(name, base.nameExpires(uint256(hash)), duration); + } + + function valid(string memory name) public view returns(bool) { + return name.strlen() > 6; + } + + function available(string memory name) public view returns(bool) { + bytes32 label = sha256(bytes(name)); + return valid(name) && base.available(uint256(label)); + } + // SWC-114-Transaction Order Dependence: L46-L49 + function makeCommitment(string memory name, bytes32 secret) pure public returns(bytes32) { + bytes32 label = sha256(bytes(name)); + return sha256(abi.encodePacked(label, secret)); + } + + function commit(bytes32 commitment) public { + require(commitments[commitment] + MAX_COMMITMENT_AGE < now); + commitments[commitment] = now; + } + // SWC-104-Unchecked Call Return Value: L56-L65 + function register(string calldata name, address owner, uint duration, bytes32 secret) external payable { + // Require a valid commitment + bytes32 commitment = makeCommitment(name, secret); + require(commitments[commitment] + MIN_COMMITMENT_AGE <= now); + + // If the commitment is too old, or the name is registered, stop + if(commitments[commitment] + MAX_COMMITMENT_AGE < now || !available(name)) { + msg.sender.transfer(msg.value); + return; + } + delete(commitments[commitment]); + + uint cost = rentPrice(name, duration); + require(duration >= MIN_REGISTRATION_DURATION); + require(msg.value >= cost); + + bytes32 label = keccak256(bytes(name)); + uint expires = base.register(uint256(label), owner, duration); + emit NameRegistered(name, owner, cost, expires); + + if(msg.value > cost) { + msg.sender.transfer(msg.value - cost); + } + } + + function renew(string calldata name, uint duration) external payable { + uint cost = rentPrice(name, duration); + require(msg.value >= cost); + + bytes32 label = keccak256(bytes(name)); + uint expires = base.renew(uint256(label), duration); + + if(msg.value > cost) { + msg.sender.transfer(msg.value - cost); + } + + emit NameRenewed(name, cost, expires); + } + + function setPriceOracle(PriceOracle _prices) public onlyOwner { + prices = _prices; + emit NewPriceOracle(address(prices)); + } + + function withdraw() public onlyOwner { + msg.sender.transfer(address(this).balance); + } +} diff --git a/contracts/mutants/ETHRegistrarController/4/MCR/diff_result_difft.json b/contracts/mutants/ETHRegistrarController/4/MCR/diff_result_difft.json new file mode 100644 index 00000000000..8e8f67fc12f --- /dev/null +++ b/contracts/mutants/ETHRegistrarController/4/MCR/diff_result_difft.json @@ -0,0 +1,108 @@ +{ + "number_of_changes": 4, + "timing": 0.17543697357177734, + "diff_chunks": [ + [ + { + "lhs": { + "line_number": 32, + "changes": [ + { + "start": 23, + "end": 32, + "content": "keccak256", + "highlight": "normal" + } + ] + }, + "rhs": { + "line_number": 32, + "changes": [ + { + "start": 23, + "end": 29, + "content": "sha256", + "highlight": "normal" + } + ] + } + } + ], + [ + { + "lhs": { + "line_number": 41, + "changes": [ + { + "start": 24, + "end": 33, + "content": "keccak256", + "highlight": "normal" + } + ] + }, + "rhs": { + "line_number": 41, + "changes": [ + { + "start": 24, + "end": 30, + "content": "sha256", + "highlight": "normal" + } + ] + } + } + ], + [ + { + "lhs": { + "line_number": 47, + "changes": [ + { + "start": 15, + "end": 24, + "content": "keccak256", + "highlight": "normal" + } + ] + }, + "rhs": { + "line_number": 47, + "changes": [ + { + "start": 15, + "end": 21, + "content": "sha256", + "highlight": "normal" + } + ] + } + }, + { + "lhs": { + "line_number": 46, + "changes": [ + { + "start": 24, + "end": 33, + "content": "keccak256", + "highlight": "normal" + } + ] + }, + "rhs": { + "line_number": 46, + "changes": [ + { + "start": 24, + "end": 30, + "content": "sha256", + "highlight": "normal" + } + ] + } + } + ] + ] +} \ No newline at end of file diff --git a/contracts/mutants/ETHRegistrarController/4/RSD/ETHRegistrarController.sol b/contracts/mutants/ETHRegistrarController/4/RSD/ETHRegistrarController.sol new file mode 100644 index 00000000000..2a4f1b90e87 --- /dev/null +++ b/contracts/mutants/ETHRegistrarController/4/RSD/ETHRegistrarController.sol @@ -0,0 +1,103 @@ +pragma solidity ^0.5.0; + +import "./PriceOracle.sol"; +import "./BaseRegistrar.sol"; +import "./StringUtils.sol"; +import "openzeppelin-solidity/contracts/ownership/Ownable.sol"; + +/** + * @dev A registrar controller for registering and renewing names at fixed cost. + */ +contract ETHRegistrarController is Ownable { + using StringUtils for *; + + uint constant public MIN_COMMITMENT_AGE = 1 hours; + uint constant public MAX_COMMITMENT_AGE = 48 hours; + uint constant public MIN_REGISTRATION_DURATION = 28 days; + + BaseRegistrar base; + PriceOracle prices; + + mapping(bytes32=>uint) public commitments; + + event NameRegistered(string name, address indexed owner, uint cost, uint expires); + event NameRenewed(string name, uint cost, uint expires); + event NewPriceOracle(address indexed oracle); + + constructor(BaseRegistrar _base, PriceOracle _prices) public { + base = _base; + prices = _prices; + } + + function rentPrice(string memory name, uint duration) view public returns(uint) { + bytes32 hash = keccak256(bytes(name)); + /* return prices.price(name, base.nameExpires(uint256(hash)), duration); */ + } + + function valid(string memory name) public view returns(bool) { + /* return name.strlen() > 6; */ + } + + function available(string memory name) public view returns(bool) { + bytes32 label = keccak256(bytes(name)); + /* return valid(name) && base.available(uint256(label)); */ + } + // SWC-114-Transaction Order Dependence: L46-L49 + function makeCommitment(string memory name, bytes32 secret) pure public returns(bytes32) { + bytes32 label = keccak256(bytes(name)); + /* return keccak256(abi.encodePacked(label, secret)); */ + } + + function commit(bytes32 commitment) public { + require(commitments[commitment] + MAX_COMMITMENT_AGE < now); + commitments[commitment] = now; + } + // SWC-104-Unchecked Call Return Value: L56-L65 + function register(string calldata name, address owner, uint duration, bytes32 secret) external payable { + // Require a valid commitment + bytes32 commitment = makeCommitment(name, secret); + require(commitments[commitment] + MIN_COMMITMENT_AGE <= now); + + // If the commitment is too old, or the name is registered, stop + if(commitments[commitment] + MAX_COMMITMENT_AGE < now || !available(name)) { + msg.sender.transfer(msg.value); + return; + } + delete(commitments[commitment]); + + uint cost = rentPrice(name, duration); + require(duration >= MIN_REGISTRATION_DURATION); + require(msg.value >= cost); + + bytes32 label = keccak256(bytes(name)); + uint expires = base.register(uint256(label), owner, duration); + emit NameRegistered(name, owner, cost, expires); + + if(msg.value > cost) { + msg.sender.transfer(msg.value - cost); + } + } + + function renew(string calldata name, uint duration) external payable { + uint cost = rentPrice(name, duration); + require(msg.value >= cost); + + bytes32 label = keccak256(bytes(name)); + uint expires = base.renew(uint256(label), duration); + + if(msg.value > cost) { + msg.sender.transfer(msg.value - cost); + } + + emit NameRenewed(name, cost, expires); + } + + function setPriceOracle(PriceOracle _prices) public onlyOwner { + prices = _prices; + emit NewPriceOracle(address(prices)); + } + + function withdraw() public onlyOwner { + msg.sender.transfer(address(this).balance); + } +} diff --git a/contracts/mutants/ETHRegistrarController/4/RSD/diff_result_difft.json b/contracts/mutants/ETHRegistrarController/4/RSD/diff_result_difft.json new file mode 100644 index 00000000000..5d0cc5f8331 --- /dev/null +++ b/contracts/mutants/ETHRegistrarController/4/RSD/diff_result_difft.json @@ -0,0 +1,408 @@ +{ + "number_of_changes": 54, + "timing": 0.1695263385772705, + "diff_chunks": [ + [ + { + "lhs": { + "line_number": 37, + "changes": [ + { + "start": 8, + "end": 14, + "content": "return", + "highlight": "keyword" + }, + { + "start": 15, + "end": 19, + "content": "name", + "highlight": "normal" + }, + { + "start": 19, + "end": 20, + "content": ".", + "highlight": "normal" + }, + { + "start": 20, + "end": 26, + "content": "strlen", + "highlight": "normal" + }, + { + "start": 26, + "end": 27, + "content": "(", + "highlight": "delimiter" + }, + { + "start": 27, + "end": 28, + "content": ")", + "highlight": "delimiter" + }, + { + "start": 29, + "end": 30, + "content": ">", + "highlight": "keyword" + }, + { + "start": 31, + "end": 32, + "content": "6", + "highlight": "normal" + } + ] + }, + "rhs": { + "line_number": 37, + "changes": [ + { + "start": 8, + "end": 39, + "content": "/* return name.strlen() > 6; */", + "highlight": "comment" + } + ] + } + }, + { + "lhs": { + "line_number": 33, + "changes": [ + { + "start": 8, + "end": 14, + "content": "return", + "highlight": "keyword" + }, + { + "start": 15, + "end": 21, + "content": "prices", + "highlight": "normal" + }, + { + "start": 21, + "end": 22, + "content": ".", + "highlight": "normal" + }, + { + "start": 22, + "end": 27, + "content": "price", + "highlight": "normal" + }, + { + "start": 27, + "end": 28, + "content": "(", + "highlight": "delimiter" + }, + { + "start": 28, + "end": 32, + "content": "name", + "highlight": "normal" + }, + { + "start": 32, + "end": 33, + "content": ",", + "highlight": "normal" + }, + { + "start": 34, + "end": 38, + "content": "base", + "highlight": "normal" + }, + { + "start": 38, + "end": 39, + "content": ".", + "highlight": "normal" + }, + { + "start": 39, + "end": 50, + "content": "nameExpires", + "highlight": "normal" + }, + { + "start": 50, + "end": 51, + "content": "(", + "highlight": "delimiter" + }, + { + "start": 51, + "end": 58, + "content": "uint256", + "highlight": "normal" + }, + { + "start": 58, + "end": 59, + "content": "(", + "highlight": "delimiter" + }, + { + "start": 59, + "end": 63, + "content": "hash", + "highlight": "normal" + }, + { + "start": 63, + "end": 64, + "content": ")", + "highlight": "delimiter" + }, + { + "start": 64, + "end": 65, + "content": ")", + "highlight": "delimiter" + }, + { + "start": 65, + "end": 66, + "content": ",", + "highlight": "normal" + }, + { + "start": 67, + "end": 75, + "content": "duration", + "highlight": "normal" + }, + { + "start": 75, + "end": 76, + "content": ")", + "highlight": "delimiter" + } + ] + }, + "rhs": { + "line_number": 33, + "changes": [ + { + "start": 8, + "end": 83, + "content": "/* return prices.price(name, base.nameExpires(uint256(hash)), duration); */", + "highlight": "comment" + } + ] + } + } + ], + [ + { + "lhs": { + "line_number": 42, + "changes": [ + { + "start": 8, + "end": 14, + "content": "return", + "highlight": "keyword" + }, + { + "start": 15, + "end": 20, + "content": "valid", + "highlight": "normal" + }, + { + "start": 20, + "end": 21, + "content": "(", + "highlight": "delimiter" + }, + { + "start": 21, + "end": 25, + "content": "name", + "highlight": "normal" + }, + { + "start": 25, + "end": 26, + "content": ")", + "highlight": "delimiter" + }, + { + "start": 27, + "end": 29, + "content": "&&", + "highlight": "keyword" + }, + { + "start": 30, + "end": 34, + "content": "base", + "highlight": "normal" + }, + { + "start": 34, + "end": 35, + "content": ".", + "highlight": "normal" + }, + { + "start": 35, + "end": 44, + "content": "available", + "highlight": "normal" + }, + { + "start": 44, + "end": 45, + "content": "(", + "highlight": "delimiter" + }, + { + "start": 45, + "end": 52, + "content": "uint256", + "highlight": "normal" + }, + { + "start": 52, + "end": 53, + "content": "(", + "highlight": "delimiter" + }, + { + "start": 53, + "end": 58, + "content": "label", + "highlight": "normal" + }, + { + "start": 58, + "end": 59, + "content": ")", + "highlight": "delimiter" + }, + { + "start": 59, + "end": 60, + "content": ")", + "highlight": "delimiter" + } + ] + }, + "rhs": { + "line_number": 42, + "changes": [ + { + "start": 8, + "end": 67, + "content": "/* return valid(name) && base.available(uint256(label)); */", + "highlight": "comment" + } + ] + } + } + ], + [ + { + "lhs": { + "line_number": 47, + "changes": [ + { + "start": 8, + "end": 14, + "content": "return", + "highlight": "keyword" + }, + { + "start": 15, + "end": 24, + "content": "keccak256", + "highlight": "normal" + }, + { + "start": 24, + "end": 25, + "content": "(", + "highlight": "delimiter" + }, + { + "start": 25, + "end": 28, + "content": "abi", + "highlight": "normal" + }, + { + "start": 28, + "end": 29, + "content": ".", + "highlight": "normal" + }, + { + "start": 29, + "end": 41, + "content": "encodePacked", + "highlight": "normal" + }, + { + "start": 41, + "end": 42, + "content": "(", + "highlight": "delimiter" + }, + { + "start": 42, + "end": 47, + "content": "label", + "highlight": "normal" + }, + { + "start": 47, + "end": 48, + "content": ",", + "highlight": "normal" + }, + { + "start": 49, + "end": 55, + "content": "secret", + "highlight": "normal" + }, + { + "start": 55, + "end": 56, + "content": ")", + "highlight": "delimiter" + }, + { + "start": 56, + "end": 57, + "content": ")", + "highlight": "delimiter" + } + ] + }, + "rhs": { + "line_number": 47, + "changes": [ + { + "start": 8, + "end": 64, + "content": "/* return keccak256(abi.encodePacked(label, secret)); */", + "highlight": "comment" + } + ] + } + } + ] + ] +} \ No newline at end of file diff --git a/contracts/mutants/ETHRegistrarController/4/TOR/ETHRegistrarController.sol b/contracts/mutants/ETHRegistrarController/4/TOR/ETHRegistrarController.sol new file mode 100644 index 00000000000..20773bc0af2 --- /dev/null +++ b/contracts/mutants/ETHRegistrarController/4/TOR/ETHRegistrarController.sol @@ -0,0 +1,103 @@ +pragma solidity ^0.5.0; + +import "./PriceOracle.sol"; +import "./BaseRegistrar.sol"; +import "./StringUtils.sol"; +import "openzeppelin-solidity/contracts/ownership/Ownable.sol"; + +/** + * @dev A registrar controller for registering and renewing names at fixed cost. + */ +contract ETHRegistrarController is Ownable { + using StringUtils for *; + + uint constant public MIN_COMMITMENT_AGE = 1 hours; + uint constant public MAX_COMMITMENT_AGE = 48 hours; + uint constant public MIN_REGISTRATION_DURATION = 28 days; + + BaseRegistrar base; + PriceOracle prices; + + mapping(bytes32=>uint) public commitments; + + event NameRegistered(string name, address indexed owner, uint cost, uint expires); + event NameRenewed(string name, uint cost, uint expires); + event NewPriceOracle(address indexed oracle); + + constructor(BaseRegistrar _base, PriceOracle _prices) public { + base = _base; + prices = _prices; + } + + function rentPrice(string memory name, uint duration) view public returns(uint) { + bytes32 hash = keccak256(bytes(name)); + return prices.price(name, base.nameExpires(uint256(hash)), duration); + } + + function valid(string memory name) public view returns(bool) { + return name.strlen() > 6; + } + + function available(string memory name) public view returns(bool) { + bytes32 label = keccak256(bytes(name)); + return valid(name) && base.available(uint256(label)); + } + // SWC-114-Transaction Order Dependence: L46-L49 + function makeCommitment(string memory name, bytes32 secret) pure public returns(bytes32) { + bytes32 label = keccak256(bytes(name)); + return keccak256(abi.encodePacked(label, secret)); + } + + function commit(bytes32 commitment) public { + require(commitments[commitment] + MAX_COMMITMENT_AGE < now); + commitments[commitment] = now; + } + // SWC-104-Unchecked Call Return Value: L56-L65 + function register(string calldata name, address owner, uint duration, bytes32 secret) external payable { + // Require a valid commitment + bytes32 commitment = makeCommitment(name, secret); + require(commitments[commitment] + MIN_COMMITMENT_AGE <= now); + + // If the commitment is too old, or the name is registered, stop + if(commitments[commitment] + MAX_COMMITMENT_AGE < now || !available(name)) { + tx.origin.transfer(msg.value); + return; + } + delete(commitments[commitment]); + + uint cost = rentPrice(name, duration); + require(duration >= MIN_REGISTRATION_DURATION); + require(msg.value >= cost); + + bytes32 label = keccak256(bytes(name)); + uint expires = base.register(uint256(label), owner, duration); + emit NameRegistered(name, owner, cost, expires); + + if(msg.value > cost) { + tx.origin.transfer(msg.value - cost); + } + } + + function renew(string calldata name, uint duration) external payable { + uint cost = rentPrice(name, duration); + require(msg.value >= cost); + + bytes32 label = keccak256(bytes(name)); + uint expires = base.renew(uint256(label), duration); + + if(msg.value > cost) { + tx.origin.transfer(msg.value - cost); + } + + emit NameRenewed(name, cost, expires); + } + + function setPriceOracle(PriceOracle _prices) public onlyOwner { + prices = _prices; + emit NewPriceOracle(address(prices)); + } + + function withdraw() public onlyOwner { + tx.origin.transfer(address(this).balance); + } +} diff --git a/contracts/mutants/ETHRegistrarController/4/TOR/diff_result_difft.json b/contracts/mutants/ETHRegistrarController/4/TOR/diff_result_difft.json new file mode 100644 index 00000000000..e13cc89eea0 --- /dev/null +++ b/contracts/mutants/ETHRegistrarController/4/TOR/diff_result_difft.json @@ -0,0 +1,158 @@ +{ + "number_of_changes": 8, + "timing": 0.14509797096252441, + "diff_chunks": [ + [ + { + "lhs": { + "line_number": 62, + "changes": [ + { + "start": 12, + "end": 15, + "content": "msg", + "highlight": "normal" + }, + { + "start": 16, + "end": 22, + "content": "sender", + "highlight": "normal" + } + ] + }, + "rhs": { + "line_number": 62, + "changes": [ + { + "start": 12, + "end": 14, + "content": "tx", + "highlight": "normal" + }, + { + "start": 15, + "end": 21, + "content": "origin", + "highlight": "normal" + } + ] + } + } + ], + [ + { + "lhs": { + "line_number": 76, + "changes": [ + { + "start": 12, + "end": 15, + "content": "msg", + "highlight": "normal" + }, + { + "start": 16, + "end": 22, + "content": "sender", + "highlight": "normal" + } + ] + }, + "rhs": { + "line_number": 76, + "changes": [ + { + "start": 12, + "end": 14, + "content": "tx", + "highlight": "normal" + }, + { + "start": 15, + "end": 21, + "content": "origin", + "highlight": "normal" + } + ] + } + } + ], + [ + { + "lhs": { + "line_number": 88, + "changes": [ + { + "start": 12, + "end": 15, + "content": "msg", + "highlight": "normal" + }, + { + "start": 16, + "end": 22, + "content": "sender", + "highlight": "normal" + } + ] + }, + "rhs": { + "line_number": 88, + "changes": [ + { + "start": 12, + "end": 14, + "content": "tx", + "highlight": "normal" + }, + { + "start": 15, + "end": 21, + "content": "origin", + "highlight": "normal" + } + ] + } + } + ], + [ + { + "lhs": { + "line_number": 100, + "changes": [ + { + "start": 8, + "end": 11, + "content": "msg", + "highlight": "normal" + }, + { + "start": 12, + "end": 18, + "content": "sender", + "highlight": "normal" + } + ] + }, + "rhs": { + "line_number": 100, + "changes": [ + { + "start": 8, + "end": 10, + "content": "tx", + "highlight": "normal" + }, + { + "start": 11, + "end": 17, + "content": "origin", + "highlight": "normal" + } + ] + } + } + ] + ] +} \ No newline at end of file diff --git a/contracts/mutants/ETHRegistrarController/4/VVR/ETHRegistrarController.sol b/contracts/mutants/ETHRegistrarController/4/VVR/ETHRegistrarController.sol new file mode 100644 index 00000000000..8062003ba63 --- /dev/null +++ b/contracts/mutants/ETHRegistrarController/4/VVR/ETHRegistrarController.sol @@ -0,0 +1,103 @@ +pragma solidity ^0.5.0; + +import "./PriceOracle.sol"; +import "./BaseRegistrar.sol"; +import "./StringUtils.sol"; +import "openzeppelin-solidity/contracts/ownership/Ownable.sol"; + +/** + * @dev A registrar controller for registering and renewing names at fixed cost. + */ +contract ETHRegistrarController is Ownable { + using StringUtils for *; + + uint constant internal MIN_COMMITMENT_AGE = 1 hours; + uint constant internal MAX_COMMITMENT_AGE = 48 hours; + uint constant internal MIN_REGISTRATION_DURATION = 28 days; + + BaseRegistrar public base; + PriceOracle prices; + + mapping(bytes32=>uint) public commitments; + + event NameRegistered(string name, address indexed owner, uint cost, uint expires); + event NameRenewed(string name, uint cost, uint expires); + event NewPriceOracle(address indexed oracle); + + constructor(BaseRegistrar _base, PriceOracle _prices) public { + base = _base; + prices = _prices; + } + + function rentPrice(string memory name, uint duration) view public returns(uint) { + bytes32 hash = keccak256(bytes(name)); + return prices.price(name, base.nameExpires(uint256(hash)), duration); + } + + function valid(string memory name) public view returns(bool) { + return name.strlen() > 6; + } + + function available(string memory name) public view returns(bool) { + bytes32 label = keccak256(bytes(name)); + return valid(name) && base.available(uint256(label)); + } + // SWC-114-Transaction Order Dependence: L46-L49 + function makeCommitment(string memory name, bytes32 secret) pure public returns(bytes32) { + bytes32 label = keccak256(bytes(name)); + return keccak256(abi.encodePacked(label, secret)); + } + + function commit(bytes32 commitment) public { + require(commitments[commitment] + MAX_COMMITMENT_AGE < now); + commitments[commitment] = now; + } + // SWC-104-Unchecked Call Return Value: L56-L65 + function register(string calldata name, address owner, uint duration, bytes32 secret) external payable { + // Require a valid commitment + bytes32 commitment = makeCommitment(name, secret); + require(commitments[commitment] + MIN_COMMITMENT_AGE <= now); + + // If the commitment is too old, or the name is registered, stop + if(commitments[commitment] + MAX_COMMITMENT_AGE < now || !available(name)) { + msg.sender.transfer(msg.value); + return; + } + delete(commitments[commitment]); + + uint cost = rentPrice(name, duration); + require(duration >= MIN_REGISTRATION_DURATION); + require(msg.value >= cost); + + bytes32 label = keccak256(bytes(name)); + uint expires = base.register(uint256(label), owner, duration); + emit NameRegistered(name, owner, cost, expires); + + if(msg.value > cost) { + msg.sender.transfer(msg.value - cost); + } + } + + function renew(string calldata name, uint duration) external payable { + uint cost = rentPrice(name, duration); + require(msg.value >= cost); + + bytes32 label = keccak256(bytes(name)); + uint expires = base.renew(uint256(label), duration); + + if(msg.value > cost) { + msg.sender.transfer(msg.value - cost); + } + + emit NameRenewed(name, cost, expires); + } + + function setPriceOracle(PriceOracle _prices) public onlyOwner { + prices = _prices; + emit NewPriceOracle(address(prices)); + } + + function withdraw() public onlyOwner { + msg.sender.transfer(address(this).balance); + } +} diff --git a/contracts/mutants/ETHRegistrarController/4/VVR/diff_result_difft.json b/contracts/mutants/ETHRegistrarController/4/VVR/diff_result_difft.json new file mode 100644 index 00000000000..6e6be3fa75e --- /dev/null +++ b/contracts/mutants/ETHRegistrarController/4/VVR/diff_result_difft.json @@ -0,0 +1,97 @@ +{ + "number_of_changes": 4, + "timing": 0.28624486923217773, + "diff_chunks": [ + [ + { + "lhs": { + "line_number": 14, + "changes": [ + { + "start": 18, + "end": 24, + "content": "public", + "highlight": "keyword" + } + ] + }, + "rhs": { + "line_number": 14, + "changes": [ + { + "start": 18, + "end": 26, + "content": "internal", + "highlight": "keyword" + } + ] + } + }, + { + "lhs": { + "line_number": 13, + "changes": [ + { + "start": 18, + "end": 24, + "content": "public", + "highlight": "keyword" + } + ] + }, + "rhs": { + "line_number": 13, + "changes": [ + { + "start": 18, + "end": 26, + "content": "internal", + "highlight": "keyword" + } + ] + } + }, + { + "lhs": { + "line_number": 15, + "changes": [ + { + "start": 18, + "end": 24, + "content": "public", + "highlight": "keyword" + } + ] + }, + "rhs": { + "line_number": 15, + "changes": [ + { + "start": 18, + "end": 26, + "content": "internal", + "highlight": "keyword" + } + ] + } + }, + { + "lhs": { + "line_number": 17, + "changes": [] + }, + "rhs": { + "line_number": 17, + "changes": [ + { + "start": 18, + "end": 24, + "content": "public", + "highlight": "keyword" + } + ] + } + } + ] + ] +} \ No newline at end of file diff --git a/contracts/mutants/ETHRegistrarController/5/BOR/ETHRegistrarController.sol b/contracts/mutants/ETHRegistrarController/5/BOR/ETHRegistrarController.sol new file mode 100644 index 00000000000..d0f41e6faf1 --- /dev/null +++ b/contracts/mutants/ETHRegistrarController/5/BOR/ETHRegistrarController.sol @@ -0,0 +1,103 @@ +pragma solidity ^0.5.0; + +import "./PriceOracle.sol"; +import "./BaseRegistrar.sol"; +import "./StringUtils.sol"; +import "openzeppelin-solidity/contracts/ownership/Ownable.sol"; + +/** + * @dev A registrar controller for registering and renewing names at fixed cost. + */ +contract ETHRegistrarController is Ownable { + using StringUtils for *; + + uint constant public MIN_COMMITMENT_AGE = 1 hours; + uint constant public MAX_COMMITMENT_AGE = 48 hours; + uint constant public MIN_REGISTRATION_DURATION = 28 days; + + BaseRegistrar base; + PriceOracle prices; + + mapping(bytes32=>uint) public commitments; + + event NameRegistered(string name, address indexed owner, uint cost, uint expires); + event NameRenewed(string name, uint cost, uint expires); + event NewPriceOracle(address indexed oracle); + + constructor(BaseRegistrar _base, PriceOracle _prices) public { + base = _base; + prices = _prices; + } + + function rentPrice(string memory name, uint duration) view public returns(uint) { + bytes32 hash = keccak256(bytes(name)); + return prices.price(name, base.nameExpires(uint256(hash)), duration); + } + + function valid(string memory name) public view returns(bool) { + return name.strlen() >= 6; + } + + function available(string memory name) public view returns(bool) { + bytes32 label = keccak256(bytes(name)); + return valid(name) || base.available(uint256(label)); + } + // SWC-114-Transaction Order Dependence: L46-L49 + function makeCommitment(string memory name, bytes32 secret) pure public returns(bytes32) { + bytes32 label = keccak256(bytes(name)); + return keccak256(abi.encodePacked(label, secret)); + } + + function commit(bytes32 commitment) public { + require(commitments[commitment] - MAX_COMMITMENT_AGE <= now); + commitments[commitment] = now; + } + // SWC-104-Unchecked Call Return Value: L56-L65 + function register(string calldata name, address owner, uint duration, bytes32 secret) external payable { + // Require a valid commitment + bytes32 commitment = makeCommitment(name, secret); + require(commitments[commitment] - MIN_COMMITMENT_AGE <= now); + + // If the commitment is too old, or the name is registered, stop + if(commitments[commitment] + MAX_COMMITMENT_AGE < now || !available(name)) { + msg.sender.transfer(msg.value); + return; + } + delete(commitments[commitment]); + + uint cost = rentPrice(name, duration); + require(duration >= MIN_REGISTRATION_DURATION); + require(msg.value >= cost); + + bytes32 label = keccak256(bytes(name)); + uint expires = base.register(uint256(label), owner, duration); + emit NameRegistered(name, owner, cost, expires); + + if(msg.value > cost) { + msg.sender.transfer(msg.value - cost); + } + } + + function renew(string calldata name, uint duration) external payable { + uint cost = rentPrice(name, duration); + require(msg.value >= cost); + + bytes32 label = keccak256(bytes(name)); + uint expires = base.renew(uint256(label), duration); + + if(msg.value > cost) { + msg.sender.transfer(msg.value - cost); + } + + emit NameRenewed(name, cost, expires); + } + + function setPriceOracle(PriceOracle _prices) public onlyOwner { + prices = _prices; + emit NewPriceOracle(address(prices)); + } + + function withdraw() public onlyOwner { + msg.sender.transfer(address(this).balance); + } +} diff --git a/contracts/mutants/ETHRegistrarController/5/BOR/diff_result_difft.json b/contracts/mutants/ETHRegistrarController/5/BOR/diff_result_difft.json new file mode 100644 index 00000000000..b37de54f0db --- /dev/null +++ b/contracts/mutants/ETHRegistrarController/5/BOR/diff_result_difft.json @@ -0,0 +1,122 @@ +{ + "number_of_changes": 5, + "timing": 0.2585263252258301, + "diff_chunks": [ + [ + { + "lhs": { + "line_number": 37, + "changes": [ + { + "start": 29, + "end": 30, + "content": ">", + "highlight": "keyword" + } + ] + }, + "rhs": { + "line_number": 37, + "changes": [ + { + "start": 29, + "end": 31, + "content": ">=", + "highlight": "keyword" + } + ] + } + } + ], + [ + { + "lhs": { + "line_number": 42, + "changes": [ + { + "start": 27, + "end": 29, + "content": "&&", + "highlight": "keyword" + } + ] + }, + "rhs": { + "line_number": 42, + "changes": [ + { + "start": 27, + "end": 29, + "content": "||", + "highlight": "keyword" + } + ] + } + } + ], + [ + { + "lhs": { + "line_number": 51, + "changes": [ + { + "start": 40, + "end": 41, + "content": "+", + "highlight": "keyword" + }, + { + "start": 61, + "end": 62, + "content": "<", + "highlight": "keyword" + } + ] + }, + "rhs": { + "line_number": 51, + "changes": [ + { + "start": 40, + "end": 41, + "content": "-", + "highlight": "keyword" + }, + { + "start": 61, + "end": 63, + "content": "<=", + "highlight": "keyword" + } + ] + } + } + ], + [ + { + "lhs": { + "line_number": 58, + "changes": [ + { + "start": 40, + "end": 41, + "content": "+", + "highlight": "keyword" + } + ] + }, + "rhs": { + "line_number": 58, + "changes": [ + { + "start": 40, + "end": 41, + "content": "-", + "highlight": "keyword" + } + ] + } + } + ] + ] +} \ No newline at end of file diff --git a/contracts/mutants/ETHRegistrarController/5/ECS/ETHRegistrarController.sol b/contracts/mutants/ETHRegistrarController/5/ECS/ETHRegistrarController.sol new file mode 100644 index 00000000000..69f83a1699a --- /dev/null +++ b/contracts/mutants/ETHRegistrarController/5/ECS/ETHRegistrarController.sol @@ -0,0 +1,103 @@ +pragma solidity ^0.5.0; + +import "./PriceOracle.sol"; +import "./BaseRegistrar.sol"; +import "./StringUtils.sol"; +import "openzeppelin-solidity/contracts/ownership/Ownable.sol"; + +/** + * @dev A registrar controller for registering and renewing names at fixed cost. + */ +contract ETHRegistrarController is Ownable { + using StringUtils for *; + + uint constant public MIN_COMMITMENT_AGE = 1 hours; + uint constant public MAX_COMMITMENT_AGE = 48 hours; + uint constant public MIN_REGISTRATION_DURATION = 28 days; + + BaseRegistrar base; + PriceOracle prices; + + mapping(bytes32=>uint) public commitments; + + event NameRegistered(string name, address indexed owner, uint cost, uint expires); + event NameRenewed(string name, uint cost, uint expires); + event NewPriceOracle(address indexed oracle); + + constructor(BaseRegistrar _base, PriceOracle _prices) public { + base = _base; + prices = _prices; + } + + function rentPrice(string memory name, uint duration) view public returns(uint) { + bytes32 hash = keccak256(bytes1(name)); + return prices.price(name, base.nameExpires(uint8(hash)), duration); + } + + function valid(string memory name) public view returns(bool) { + return name.strlen() > 6; + } + + function available(string memory name) public view returns(bool) { + bytes32 label = keccak256(bytes1(name)); + return valid(name) && base.available(uint8(label)); + } + // SWC-114-Transaction Order Dependence: L46-L49 + function makeCommitment(string memory name, bytes32 secret) pure public returns(bytes32) { + bytes32 label = keccak256(bytes1(name)); + return keccak256(abi.encodePacked(label, secret)); + } + + function commit(bytes32 commitment) public { + require(commitments[commitment] + MAX_COMMITMENT_AGE < now); + commitments[commitment] = now; + } + // SWC-104-Unchecked Call Return Value: L56-L65 + function register(string calldata name, address owner, uint duration, bytes32 secret) external payable { + // Require a valid commitment + bytes32 commitment = makeCommitment(name, secret); + require(commitments[commitment] + MIN_COMMITMENT_AGE <= now); + + // If the commitment is too old, or the name is registered, stop + if(commitments[commitment] + MAX_COMMITMENT_AGE < now || !available(name)) { + msg.sender.transfer(msg.value); + return; + } + delete(commitments[commitment]); + + uint cost = rentPrice(name, duration); + require(duration >= MIN_REGISTRATION_DURATION); + require(msg.value >= cost); + + bytes32 label = keccak256(bytes(name)); + uint expires = base.register(uint256(label), owner, duration); + emit NameRegistered(name, owner, cost, expires); + + if(msg.value > cost) { + msg.sender.transfer(msg.value - cost); + } + } + + function renew(string calldata name, uint duration) external payable { + uint cost = rentPrice(name, duration); + require(msg.value >= cost); + + bytes32 label = keccak256(bytes(name)); + uint expires = base.renew(uint256(label), duration); + + if(msg.value > cost) { + msg.sender.transfer(msg.value - cost); + } + + emit NameRenewed(name, cost, expires); + } + + function setPriceOracle(PriceOracle _prices) public onlyOwner { + prices = _prices; + emit NewPriceOracle(address(prices)); + } + + function withdraw() public onlyOwner { + msg.sender.transfer(address(this).balance); + } +} diff --git a/contracts/mutants/ETHRegistrarController/5/ECS/diff_result_difft.json b/contracts/mutants/ETHRegistrarController/5/ECS/diff_result_difft.json new file mode 100644 index 00000000000..836c8ebad5f --- /dev/null +++ b/contracts/mutants/ETHRegistrarController/5/ECS/diff_result_difft.json @@ -0,0 +1,130 @@ +{ + "number_of_changes": 5, + "timing": 0.12615108489990234, + "diff_chunks": [ + [ + { + "lhs": { + "line_number": 32, + "changes": [ + { + "start": 33, + "end": 38, + "content": "bytes", + "highlight": "normal" + } + ] + }, + "rhs": { + "line_number": 32, + "changes": [ + { + "start": 33, + "end": 39, + "content": "bytes1", + "highlight": "normal" + } + ] + } + }, + { + "lhs": { + "line_number": 33, + "changes": [ + { + "start": 51, + "end": 58, + "content": "uint256", + "highlight": "normal" + } + ] + }, + "rhs": { + "line_number": 33, + "changes": [ + { + "start": 51, + "end": 56, + "content": "uint8", + "highlight": "normal" + } + ] + } + } + ], + [ + { + "lhs": { + "line_number": 46, + "changes": [ + { + "start": 34, + "end": 39, + "content": "bytes", + "highlight": "normal" + } + ] + }, + "rhs": { + "line_number": 46, + "changes": [ + { + "start": 34, + "end": 40, + "content": "bytes1", + "highlight": "normal" + } + ] + } + }, + { + "lhs": { + "line_number": 42, + "changes": [ + { + "start": 45, + "end": 52, + "content": "uint256", + "highlight": "normal" + } + ] + }, + "rhs": { + "line_number": 42, + "changes": [ + { + "start": 45, + "end": 50, + "content": "uint8", + "highlight": "normal" + } + ] + } + }, + { + "lhs": { + "line_number": 41, + "changes": [ + { + "start": 34, + "end": 39, + "content": "bytes", + "highlight": "normal" + } + ] + }, + "rhs": { + "line_number": 41, + "changes": [ + { + "start": 34, + "end": 40, + "content": "bytes1", + "highlight": "normal" + } + ] + } + } + ] + ] +} \ No newline at end of file diff --git a/contracts/mutants/ETHRegistrarController/5/EHC/ETHRegistrarController.sol b/contracts/mutants/ETHRegistrarController/5/EHC/ETHRegistrarController.sol new file mode 100644 index 00000000000..b16d6810370 --- /dev/null +++ b/contracts/mutants/ETHRegistrarController/5/EHC/ETHRegistrarController.sol @@ -0,0 +1,103 @@ +pragma solidity ^0.5.0; + +import "./PriceOracle.sol"; +import "./BaseRegistrar.sol"; +import "./StringUtils.sol"; +import "openzeppelin-solidity/contracts/ownership/Ownable.sol"; + +/** + * @dev A registrar controller for registering and renewing names at fixed cost. + */ +contract ETHRegistrarController is Ownable { + using StringUtils for *; + + uint constant public MIN_COMMITMENT_AGE = 1 hours; + uint constant public MAX_COMMITMENT_AGE = 48 hours; + uint constant public MIN_REGISTRATION_DURATION = 28 days; + + BaseRegistrar base; + PriceOracle prices; + + mapping(bytes32=>uint) public commitments; + + event NameRegistered(string name, address indexed owner, uint cost, uint expires); + event NameRenewed(string name, uint cost, uint expires); + event NewPriceOracle(address indexed oracle); + + constructor(BaseRegistrar _base, PriceOracle _prices) public { + base = _base; + prices = _prices; + } + + function rentPrice(string memory name, uint duration) view public returns(uint) { + bytes32 hash = keccak256(bytes(name)); + return prices.price(name, base.nameExpires(uint256(hash)), duration); + } + + function valid(string memory name) public view returns(bool) { + return name.strlen() > 6; + } + + function available(string memory name) public view returns(bool) { + bytes32 label = keccak256(bytes(name)); + return valid(name) && base.available(uint256(label)); + } + // SWC-114-Transaction Order Dependence: L46-L49 + function makeCommitment(string memory name, bytes32 secret) pure public returns(bytes32) { + bytes32 label = keccak256(bytes(name)); + return keccak256(abi.encodePacked(label, secret)); + } + + function commit(bytes32 commitment) public { + /* require(commitments[commitment] + MAX_COMMITMENT_AGE < now); */ + commitments[commitment] = now; + } + // SWC-104-Unchecked Call Return Value: L56-L65 + function register(string calldata name, address owner, uint duration, bytes32 secret) external payable { + // Require a valid commitment + bytes32 commitment = makeCommitment(name, secret); + /* require(commitments[commitment] + MIN_COMMITMENT_AGE <= now); */ + + // If the commitment is too old, or the name is registered, stop + if(commitments[commitment] + MAX_COMMITMENT_AGE < now || !available(name)) { + msg.sender.transfer(msg.value); + return; + } + delete(commitments[commitment]); + + uint cost = rentPrice(name, duration); + /* require(duration >= MIN_REGISTRATION_DURATION); */ + /* require(msg.value >= cost); */ + + bytes32 label = keccak256(bytes(name)); + uint expires = base.register(uint256(label), owner, duration); + emit NameRegistered(name, owner, cost, expires); + + if(msg.value > cost) { + msg.sender.transfer(msg.value - cost); + } + } + + function renew(string calldata name, uint duration) external payable { + uint cost = rentPrice(name, duration); + /* require(msg.value >= cost); */ + + bytes32 label = keccak256(bytes(name)); + uint expires = base.renew(uint256(label), duration); + + if(msg.value > cost) { + msg.sender.transfer(msg.value - cost); + } + + emit NameRenewed(name, cost, expires); + } + + function setPriceOracle(PriceOracle _prices) public onlyOwner { + prices = _prices; + emit NewPriceOracle(address(prices)); + } + + function withdraw() public onlyOwner { + msg.sender.transfer(address(this).balance); + } +} diff --git a/contracts/mutants/ETHRegistrarController/5/EHC/diff_result_difft.json b/contracts/mutants/ETHRegistrarController/5/EHC/diff_result_difft.json new file mode 100644 index 00000000000..1f000510e25 --- /dev/null +++ b/contracts/mutants/ETHRegistrarController/5/EHC/diff_result_difft.json @@ -0,0 +1,368 @@ +{ + "number_of_changes": 44, + "timing": 0.3021583557128906, + "diff_chunks": [ + [ + { + "lhs": { + "line_number": 51, + "changes": [ + { + "start": 8, + "end": 15, + "content": "require", + "highlight": "normal" + }, + { + "start": 15, + "end": 16, + "content": "(", + "highlight": "delimiter" + }, + { + "start": 16, + "end": 27, + "content": "commitments", + "highlight": "normal" + }, + { + "start": 27, + "end": 28, + "content": "[", + "highlight": "delimiter" + }, + { + "start": 28, + "end": 38, + "content": "commitment", + "highlight": "normal" + }, + { + "start": 38, + "end": 39, + "content": "]", + "highlight": "delimiter" + }, + { + "start": 40, + "end": 41, + "content": "+", + "highlight": "keyword" + }, + { + "start": 42, + "end": 60, + "content": "MAX_COMMITMENT_AGE", + "highlight": "normal" + }, + { + "start": 61, + "end": 62, + "content": "<", + "highlight": "keyword" + }, + { + "start": 63, + "end": 66, + "content": "now", + "highlight": "normal" + }, + { + "start": 66, + "end": 67, + "content": ")", + "highlight": "delimiter" + } + ] + }, + "rhs": { + "line_number": 51, + "changes": [ + { + "start": 8, + "end": 74, + "content": "/* require(commitments[commitment] + MAX_COMMITMENT_AGE < now); */", + "highlight": "comment" + } + ] + } + } + ], + [ + { + "lhs": { + "line_number": 58, + "changes": [ + { + "start": 8, + "end": 15, + "content": "require", + "highlight": "normal" + }, + { + "start": 15, + "end": 16, + "content": "(", + "highlight": "delimiter" + }, + { + "start": 16, + "end": 27, + "content": "commitments", + "highlight": "normal" + }, + { + "start": 27, + "end": 28, + "content": "[", + "highlight": "delimiter" + }, + { + "start": 28, + "end": 38, + "content": "commitment", + "highlight": "normal" + }, + { + "start": 38, + "end": 39, + "content": "]", + "highlight": "delimiter" + }, + { + "start": 40, + "end": 41, + "content": "+", + "highlight": "keyword" + }, + { + "start": 42, + "end": 60, + "content": "MIN_COMMITMENT_AGE", + "highlight": "normal" + }, + { + "start": 61, + "end": 63, + "content": "<=", + "highlight": "keyword" + }, + { + "start": 64, + "end": 67, + "content": "now", + "highlight": "normal" + }, + { + "start": 67, + "end": 68, + "content": ")", + "highlight": "delimiter" + } + ] + }, + "rhs": { + "line_number": 58, + "changes": [ + { + "start": 8, + "end": 75, + "content": "/* require(commitments[commitment] + MIN_COMMITMENT_AGE <= now); */", + "highlight": "comment" + } + ] + } + } + ], + [ + { + "lhs": { + "line_number": 69, + "changes": [ + { + "start": 8, + "end": 15, + "content": "require", + "highlight": "normal" + }, + { + "start": 15, + "end": 16, + "content": "(", + "highlight": "delimiter" + }, + { + "start": 16, + "end": 19, + "content": "msg", + "highlight": "normal" + }, + { + "start": 19, + "end": 20, + "content": ".", + "highlight": "normal" + }, + { + "start": 20, + "end": 25, + "content": "value", + "highlight": "normal" + }, + { + "start": 26, + "end": 28, + "content": ">=", + "highlight": "keyword" + }, + { + "start": 29, + "end": 33, + "content": "cost", + "highlight": "normal" + }, + { + "start": 33, + "end": 34, + "content": ")", + "highlight": "delimiter" + } + ] + }, + "rhs": { + "line_number": 69, + "changes": [ + { + "start": 8, + "end": 41, + "content": "/* require(msg.value >= cost); */", + "highlight": "comment" + } + ] + } + }, + { + "lhs": { + "line_number": 68, + "changes": [ + { + "start": 8, + "end": 15, + "content": "require", + "highlight": "normal" + }, + { + "start": 15, + "end": 16, + "content": "(", + "highlight": "delimiter" + }, + { + "start": 16, + "end": 24, + "content": "duration", + "highlight": "normal" + }, + { + "start": 25, + "end": 27, + "content": ">=", + "highlight": "keyword" + }, + { + "start": 28, + "end": 53, + "content": "MIN_REGISTRATION_DURATION", + "highlight": "normal" + }, + { + "start": 53, + "end": 54, + "content": ")", + "highlight": "delimiter" + } + ] + }, + "rhs": { + "line_number": 68, + "changes": [ + { + "start": 8, + "end": 61, + "content": "/* require(duration >= MIN_REGISTRATION_DURATION); */", + "highlight": "comment" + } + ] + } + } + ], + [ + { + "lhs": { + "line_number": 82, + "changes": [ + { + "start": 8, + "end": 15, + "content": "require", + "highlight": "normal" + }, + { + "start": 15, + "end": 16, + "content": "(", + "highlight": "delimiter" + }, + { + "start": 16, + "end": 19, + "content": "msg", + "highlight": "normal" + }, + { + "start": 19, + "end": 20, + "content": ".", + "highlight": "normal" + }, + { + "start": 20, + "end": 25, + "content": "value", + "highlight": "normal" + }, + { + "start": 26, + "end": 28, + "content": ">=", + "highlight": "keyword" + }, + { + "start": 29, + "end": 33, + "content": "cost", + "highlight": "normal" + }, + { + "start": 33, + "end": 34, + "content": ")", + "highlight": "delimiter" + } + ] + }, + "rhs": { + "line_number": 82, + "changes": [ + { + "start": 8, + "end": 41, + "content": "/* require(msg.value >= cost); */", + "highlight": "comment" + } + ] + } + } + ] + ] +} \ No newline at end of file diff --git a/contracts/mutants/ETHRegistrarController/5/FVR/ETHRegistrarController.sol b/contracts/mutants/ETHRegistrarController/5/FVR/ETHRegistrarController.sol new file mode 100644 index 00000000000..3b1fcd8ba19 --- /dev/null +++ b/contracts/mutants/ETHRegistrarController/5/FVR/ETHRegistrarController.sol @@ -0,0 +1,103 @@ +pragma solidity ^0.5.0; + +import "./PriceOracle.sol"; +import "./BaseRegistrar.sol"; +import "./StringUtils.sol"; +import "openzeppelin-solidity/contracts/ownership/Ownable.sol"; + +/** + * @dev A registrar controller for registering and renewing names at fixed cost. + */ +contract ETHRegistrarController is Ownable { + using StringUtils for *; + + uint constant public MIN_COMMITMENT_AGE = 1 hours; + uint constant public MAX_COMMITMENT_AGE = 48 hours; + uint constant public MIN_REGISTRATION_DURATION = 28 days; + + BaseRegistrar base; + PriceOracle prices; + + mapping(bytes32=>uint) public commitments; + + event NameRegistered(string name, address indexed owner, uint cost, uint expires); + event NameRenewed(string name, uint cost, uint expires); + event NewPriceOracle(address indexed oracle); + + constructor(BaseRegistrar _base, PriceOracle _prices) internal { + base = _base; + prices = _prices; + } + + function rentPrice(string memory name, uint duration) view external returns(uint) { + bytes32 hash = keccak256(bytes(name)); + return prices.price(name, base.nameExpires(uint256(hash)), duration); + } + + function valid(string memory name) external view returns(bool) { + return name.strlen() > 6; + } + + function available(string memory name) external view returns(bool) { + bytes32 label = keccak256(bytes(name)); + return valid(name) && base.available(uint256(label)); + } + // SWC-114-Transaction Order Dependence: L46-L49 + function makeCommitment(string memory name, bytes32 secret) pure external returns(bytes32) { + bytes32 label = keccak256(bytes(name)); + return keccak256(abi.encodePacked(label, secret)); + } + + function commit(bytes32 commitment) public { + require(commitments[commitment] + MAX_COMMITMENT_AGE < now); + commitments[commitment] = now; + } + // SWC-104-Unchecked Call Return Value: L56-L65 + function register(string calldata name, address owner, uint duration, bytes32 secret) external payable { + // Require a valid commitment + bytes32 commitment = makeCommitment(name, secret); + require(commitments[commitment] + MIN_COMMITMENT_AGE <= now); + + // If the commitment is too old, or the name is registered, stop + if(commitments[commitment] + MAX_COMMITMENT_AGE < now || !available(name)) { + msg.sender.transfer(msg.value); + return; + } + delete(commitments[commitment]); + + uint cost = rentPrice(name, duration); + require(duration >= MIN_REGISTRATION_DURATION); + require(msg.value >= cost); + + bytes32 label = keccak256(bytes(name)); + uint expires = base.register(uint256(label), owner, duration); + emit NameRegistered(name, owner, cost, expires); + + if(msg.value > cost) { + msg.sender.transfer(msg.value - cost); + } + } + + function renew(string calldata name, uint duration) external payable { + uint cost = rentPrice(name, duration); + require(msg.value >= cost); + + bytes32 label = keccak256(bytes(name)); + uint expires = base.renew(uint256(label), duration); + + if(msg.value > cost) { + msg.sender.transfer(msg.value - cost); + } + + emit NameRenewed(name, cost, expires); + } + + function setPriceOracle(PriceOracle _prices) public onlyOwner { + prices = _prices; + emit NewPriceOracle(address(prices)); + } + + function withdraw() public onlyOwner { + msg.sender.transfer(address(this).balance); + } +} diff --git a/contracts/mutants/ETHRegistrarController/5/FVR/diff_result_difft.json b/contracts/mutants/ETHRegistrarController/5/FVR/diff_result_difft.json new file mode 100644 index 00000000000..79b8e2c7222 --- /dev/null +++ b/contracts/mutants/ETHRegistrarController/5/FVR/diff_result_difft.json @@ -0,0 +1,134 @@ +{ + "number_of_changes": 5, + "timing": 0.2859010696411133, + "diff_chunks": [ + [ + { + "lhs": { + "line_number": 26, + "changes": [ + { + "start": 58, + "end": 64, + "content": "public", + "highlight": "keyword" + } + ] + }, + "rhs": { + "line_number": 26, + "changes": [ + { + "start": 58, + "end": 66, + "content": "internal", + "highlight": "keyword" + } + ] + } + } + ], + [ + { + "lhs": { + "line_number": 31, + "changes": [ + { + "start": 63, + "end": 69, + "content": "public", + "highlight": "keyword" + } + ] + }, + "rhs": { + "line_number": 31, + "changes": [ + { + "start": 63, + "end": 71, + "content": "external", + "highlight": "keyword" + } + ] + } + } + ], + [ + { + "lhs": { + "line_number": 36, + "changes": [ + { + "start": 39, + "end": 45, + "content": "public", + "highlight": "keyword" + } + ] + }, + "rhs": { + "line_number": 36, + "changes": [ + { + "start": 39, + "end": 47, + "content": "external", + "highlight": "keyword" + } + ] + } + }, + { + "lhs": { + "line_number": 40, + "changes": [ + { + "start": 43, + "end": 49, + "content": "public", + "highlight": "keyword" + } + ] + }, + "rhs": { + "line_number": 40, + "changes": [ + { + "start": 43, + "end": 51, + "content": "external", + "highlight": "keyword" + } + ] + } + } + ], + [ + { + "lhs": { + "line_number": 45, + "changes": [ + { + "start": 69, + "end": 75, + "content": "public", + "highlight": "keyword" + } + ] + }, + "rhs": { + "line_number": 45, + "changes": [ + { + "start": 69, + "end": 77, + "content": "external", + "highlight": "keyword" + } + ] + } + } + ] + ] +} \ No newline at end of file diff --git a/contracts/mutants/ETHRegistrarController/5/GVR/ETHRegistrarController.sol b/contracts/mutants/ETHRegistrarController/5/GVR/ETHRegistrarController.sol new file mode 100644 index 00000000000..d2e3b87ebd2 --- /dev/null +++ b/contracts/mutants/ETHRegistrarController/5/GVR/ETHRegistrarController.sol @@ -0,0 +1,103 @@ +pragma solidity ^0.5.0; + +import "./PriceOracle.sol"; +import "./BaseRegistrar.sol"; +import "./StringUtils.sol"; +import "openzeppelin-solidity/contracts/ownership/Ownable.sol"; + +/** + * @dev A registrar controller for registering and renewing names at fixed cost. + */ +contract ETHRegistrarController is Ownable { + using StringUtils for *; + + uint constant public MIN_COMMITMENT_AGE = 1 hours; + uint constant public MAX_COMMITMENT_AGE = 48 hours; + uint constant public MIN_REGISTRATION_DURATION = 28 days; + + BaseRegistrar base; + PriceOracle prices; + + mapping(bytes32=>uint) public commitments; + + event NameRegistered(string name, address indexed owner, uint cost, uint expires); + event NameRenewed(string name, uint cost, uint expires); + event NewPriceOracle(address indexed oracle); + + constructor(BaseRegistrar _base, PriceOracle _prices) public { + base = _base; + prices = _prices; + } + + function rentPrice(string memory name, uint duration) view public returns(uint) { + bytes32 hash = keccak256(bytes(name)); + return prices.price(name, base.nameExpires(uint256(hash)), duration); + } + + function valid(string memory name) public view returns(bool) { + return name.strlen() > 6; + } + + function available(string memory name) public view returns(bool) { + bytes32 label = keccak256(bytes(name)); + return valid(name) && base.available(uint256(label)); + } + // SWC-114-Transaction Order Dependence: L46-L49 + function makeCommitment(string memory name, bytes32 secret) pure public returns(bytes32) { + bytes32 label = keccak256(bytes(name)); + return keccak256(abi.encodePacked(label, secret)); + } + + function commit(bytes32 commitment) public { + require(commitments[commitment] + MAX_COMMITMENT_AGE < block.difficulty); + commitments[commitment] = block.difficulty; + } + // SWC-104-Unchecked Call Return Value: L56-L65 + function register(string calldata name, address owner, uint duration, bytes32 secret) external payable { + // Require a valid commitment + bytes32 commitment = makeCommitment(name, secret); + require(commitments[commitment] + MIN_COMMITMENT_AGE <= block.difficulty); + + // If the commitment is too old, or the name is registered, stop + if(commitments[commitment] + MAX_COMMITMENT_AGE < block.difficulty || !available(name)) { + msg.sender.transfer(tx.gasprice); + return; + } + delete(commitments[commitment]); + + uint cost = rentPrice(name, duration); + require(duration >= MIN_REGISTRATION_DURATION); + require(msg.value >= cost); + + bytes32 label = keccak256(bytes(name)); + uint expires = base.register(uint256(label), owner, duration); + emit NameRegistered(name, owner, cost, expires); + + if(msg.value > cost) { + msg.sender.transfer(msg.value - cost); + } + } + + function renew(string calldata name, uint duration) external payable { + uint cost = rentPrice(name, duration); + require(msg.value >= cost); + + bytes32 label = keccak256(bytes(name)); + uint expires = base.renew(uint256(label), duration); + + if(msg.value > cost) { + msg.sender.transfer(msg.value - cost); + } + + emit NameRenewed(name, cost, expires); + } + + function setPriceOracle(PriceOracle _prices) public onlyOwner { + prices = _prices; + emit NewPriceOracle(address(prices)); + } + + function withdraw() public onlyOwner { + msg.sender.transfer(address(this).balance); + } +} diff --git a/contracts/mutants/ETHRegistrarController/5/GVR/diff_result_difft.json b/contracts/mutants/ETHRegistrarController/5/GVR/diff_result_difft.json new file mode 100644 index 00000000000..aecb3020693 --- /dev/null +++ b/contracts/mutants/ETHRegistrarController/5/GVR/diff_result_difft.json @@ -0,0 +1,190 @@ +{ + "number_of_changes": 14, + "timing": 0.1953268051147461, + "diff_chunks": [ + [ + { + "lhs": { + "line_number": 51, + "changes": [ + { + "start": 63, + "end": 66, + "content": "now", + "highlight": "normal" + } + ] + }, + "rhs": { + "line_number": 51, + "changes": [ + { + "start": 63, + "end": 68, + "content": "block", + "highlight": "normal" + }, + { + "start": 68, + "end": 69, + "content": ".", + "highlight": "normal" + }, + { + "start": 69, + "end": 79, + "content": "difficulty", + "highlight": "normal" + } + ] + } + }, + { + "lhs": { + "line_number": 52, + "changes": [ + { + "start": 34, + "end": 37, + "content": "now", + "highlight": "normal" + } + ] + }, + "rhs": { + "line_number": 52, + "changes": [ + { + "start": 34, + "end": 39, + "content": "block", + "highlight": "normal" + }, + { + "start": 39, + "end": 40, + "content": ".", + "highlight": "normal" + }, + { + "start": 40, + "end": 50, + "content": "difficulty", + "highlight": "normal" + } + ] + } + } + ], + [ + { + "lhs": { + "line_number": 61, + "changes": [ + { + "start": 58, + "end": 61, + "content": "now", + "highlight": "normal" + } + ] + }, + "rhs": { + "line_number": 61, + "changes": [ + { + "start": 58, + "end": 63, + "content": "block", + "highlight": "normal" + }, + { + "start": 63, + "end": 64, + "content": ".", + "highlight": "normal" + }, + { + "start": 64, + "end": 74, + "content": "difficulty", + "highlight": "normal" + } + ] + } + }, + { + "lhs": { + "line_number": 62, + "changes": [ + { + "start": 32, + "end": 35, + "content": "msg", + "highlight": "normal" + }, + { + "start": 36, + "end": 41, + "content": "value", + "highlight": "normal" + } + ] + }, + "rhs": { + "line_number": 62, + "changes": [ + { + "start": 32, + "end": 34, + "content": "tx", + "highlight": "normal" + }, + { + "start": 35, + "end": 43, + "content": "gasprice", + "highlight": "normal" + } + ] + } + }, + { + "lhs": { + "line_number": 58, + "changes": [ + { + "start": 64, + "end": 67, + "content": "now", + "highlight": "normal" + } + ] + }, + "rhs": { + "line_number": 58, + "changes": [ + { + "start": 64, + "end": 69, + "content": "block", + "highlight": "normal" + }, + { + "start": 69, + "end": 70, + "content": ".", + "highlight": "normal" + }, + { + "start": 70, + "end": 80, + "content": "difficulty", + "highlight": "normal" + } + ] + } + } + ] + ] +} \ No newline at end of file diff --git a/contracts/mutants/ETHRegistrarController/5/MCR/ETHRegistrarController.sol b/contracts/mutants/ETHRegistrarController/5/MCR/ETHRegistrarController.sol new file mode 100644 index 00000000000..e85de6080b9 --- /dev/null +++ b/contracts/mutants/ETHRegistrarController/5/MCR/ETHRegistrarController.sol @@ -0,0 +1,103 @@ +pragma solidity ^0.5.0; + +import "./PriceOracle.sol"; +import "./BaseRegistrar.sol"; +import "./StringUtils.sol"; +import "openzeppelin-solidity/contracts/ownership/Ownable.sol"; + +/** + * @dev A registrar controller for registering and renewing names at fixed cost. + */ +contract ETHRegistrarController is Ownable { + using StringUtils for *; + + uint constant public MIN_COMMITMENT_AGE = 1 hours; + uint constant public MAX_COMMITMENT_AGE = 48 hours; + uint constant public MIN_REGISTRATION_DURATION = 28 days; + + BaseRegistrar base; + PriceOracle prices; + + mapping(bytes32=>uint) public commitments; + + event NameRegistered(string name, address indexed owner, uint cost, uint expires); + event NameRenewed(string name, uint cost, uint expires); + event NewPriceOracle(address indexed oracle); + + constructor(BaseRegistrar _base, PriceOracle _prices) public { + base = _base; + prices = _prices; + } + + function rentPrice(string memory name, uint duration) view public returns(uint) { + bytes32 hash = sha256(bytes(name)); + return prices.price(name, base.nameExpires(uint256(hash)), duration); + } + + function valid(string memory name) public view returns(bool) { + return name.strlen() > 6; + } + + function available(string memory name) public view returns(bool) { + bytes32 label = sha256(bytes(name)); + return valid(name) && base.available(uint256(label)); + } + // SWC-114-Transaction Order Dependence: L46-L49 + function makeCommitment(string memory name, bytes32 secret) pure public returns(bytes32) { + bytes32 label = sha256(bytes(name)); + return sha256(abi.encodePacked(label, secret)); + } + + function commit(bytes32 commitment) public { + require(commitments[commitment] + MAX_COMMITMENT_AGE < now); + commitments[commitment] = now; + } + // SWC-104-Unchecked Call Return Value: L56-L65 + function register(string calldata name, address owner, uint duration, bytes32 secret) external payable { + // Require a valid commitment + bytes32 commitment = makeCommitment(name, secret); + require(commitments[commitment] + MIN_COMMITMENT_AGE <= now); + + // If the commitment is too old, or the name is registered, stop + if(commitments[commitment] + MAX_COMMITMENT_AGE < now || !available(name)) { + msg.sender.transfer(msg.value); + return; + } + delete(commitments[commitment]); + + uint cost = rentPrice(name, duration); + require(duration >= MIN_REGISTRATION_DURATION); + require(msg.value >= cost); + + bytes32 label = sha256(bytes(name)); + uint expires = base.register(uint256(label), owner, duration); + emit NameRegistered(name, owner, cost, expires); + + if(msg.value > cost) { + msg.sender.transfer(msg.value - cost); + } + } + + function renew(string calldata name, uint duration) external payable { + uint cost = rentPrice(name, duration); + require(msg.value >= cost); + + bytes32 label = keccak256(bytes(name)); + uint expires = base.renew(uint256(label), duration); + + if(msg.value > cost) { + msg.sender.transfer(msg.value - cost); + } + + emit NameRenewed(name, cost, expires); + } + + function setPriceOracle(PriceOracle _prices) public onlyOwner { + prices = _prices; + emit NewPriceOracle(address(prices)); + } + + function withdraw() public onlyOwner { + msg.sender.transfer(address(this).balance); + } +} diff --git a/contracts/mutants/ETHRegistrarController/5/MCR/diff_result_difft.json b/contracts/mutants/ETHRegistrarController/5/MCR/diff_result_difft.json new file mode 100644 index 00000000000..8b3bf5d9134 --- /dev/null +++ b/contracts/mutants/ETHRegistrarController/5/MCR/diff_result_difft.json @@ -0,0 +1,134 @@ +{ + "number_of_changes": 5, + "timing": 0.10769271850585938, + "diff_chunks": [ + [ + { + "lhs": { + "line_number": 32, + "changes": [ + { + "start": 23, + "end": 32, + "content": "keccak256", + "highlight": "normal" + } + ] + }, + "rhs": { + "line_number": 32, + "changes": [ + { + "start": 23, + "end": 29, + "content": "sha256", + "highlight": "normal" + } + ] + } + } + ], + [ + { + "lhs": { + "line_number": 41, + "changes": [ + { + "start": 24, + "end": 33, + "content": "keccak256", + "highlight": "normal" + } + ] + }, + "rhs": { + "line_number": 41, + "changes": [ + { + "start": 24, + "end": 30, + "content": "sha256", + "highlight": "normal" + } + ] + } + } + ], + [ + { + "lhs": { + "line_number": 46, + "changes": [ + { + "start": 24, + "end": 33, + "content": "keccak256", + "highlight": "normal" + } + ] + }, + "rhs": { + "line_number": 46, + "changes": [ + { + "start": 24, + "end": 30, + "content": "sha256", + "highlight": "normal" + } + ] + } + }, + { + "lhs": { + "line_number": 47, + "changes": [ + { + "start": 15, + "end": 24, + "content": "keccak256", + "highlight": "normal" + } + ] + }, + "rhs": { + "line_number": 47, + "changes": [ + { + "start": 15, + "end": 21, + "content": "sha256", + "highlight": "normal" + } + ] + } + } + ], + [ + { + "lhs": { + "line_number": 71, + "changes": [ + { + "start": 24, + "end": 33, + "content": "keccak256", + "highlight": "normal" + } + ] + }, + "rhs": { + "line_number": 71, + "changes": [ + { + "start": 24, + "end": 30, + "content": "sha256", + "highlight": "normal" + } + ] + } + } + ] + ] +} \ No newline at end of file diff --git a/contracts/mutants/ETHRegistrarController/5/RSD/ETHRegistrarController.sol b/contracts/mutants/ETHRegistrarController/5/RSD/ETHRegistrarController.sol new file mode 100644 index 00000000000..e00b6141cc0 --- /dev/null +++ b/contracts/mutants/ETHRegistrarController/5/RSD/ETHRegistrarController.sol @@ -0,0 +1,103 @@ +pragma solidity ^0.5.0; + +import "./PriceOracle.sol"; +import "./BaseRegistrar.sol"; +import "./StringUtils.sol"; +import "openzeppelin-solidity/contracts/ownership/Ownable.sol"; + +/** + * @dev A registrar controller for registering and renewing names at fixed cost. + */ +contract ETHRegistrarController is Ownable { + using StringUtils for *; + + uint constant public MIN_COMMITMENT_AGE = 1 hours; + uint constant public MAX_COMMITMENT_AGE = 48 hours; + uint constant public MIN_REGISTRATION_DURATION = 28 days; + + BaseRegistrar base; + PriceOracle prices; + + mapping(bytes32=>uint) public commitments; + + event NameRegistered(string name, address indexed owner, uint cost, uint expires); + event NameRenewed(string name, uint cost, uint expires); + event NewPriceOracle(address indexed oracle); + + constructor(BaseRegistrar _base, PriceOracle _prices) public { + base = _base; + prices = _prices; + } + + function rentPrice(string memory name, uint duration) view public returns(uint) { + bytes32 hash = keccak256(bytes(name)); + /* return prices.price(name, base.nameExpires(uint256(hash)), duration); */ + } + + function valid(string memory name) public view returns(bool) { + /* return name.strlen() > 6; */ + } + + function available(string memory name) public view returns(bool) { + bytes32 label = keccak256(bytes(name)); + /* return valid(name) && base.available(uint256(label)); */ + } + // SWC-114-Transaction Order Dependence: L46-L49 + function makeCommitment(string memory name, bytes32 secret) pure public returns(bytes32) { + bytes32 label = keccak256(bytes(name)); + /* return keccak256(abi.encodePacked(label, secret)); */ + } + + function commit(bytes32 commitment) public { + require(commitments[commitment] + MAX_COMMITMENT_AGE < now); + commitments[commitment] = now; + } + // SWC-104-Unchecked Call Return Value: L56-L65 + function register(string calldata name, address owner, uint duration, bytes32 secret) external payable { + // Require a valid commitment + bytes32 commitment = makeCommitment(name, secret); + require(commitments[commitment] + MIN_COMMITMENT_AGE <= now); + + // If the commitment is too old, or the name is registered, stop + if(commitments[commitment] + MAX_COMMITMENT_AGE < now || !available(name)) { + msg.sender.transfer(msg.value); + /* return; */ + } + delete(commitments[commitment]); + + uint cost = rentPrice(name, duration); + require(duration >= MIN_REGISTRATION_DURATION); + require(msg.value >= cost); + + bytes32 label = keccak256(bytes(name)); + uint expires = base.register(uint256(label), owner, duration); + emit NameRegistered(name, owner, cost, expires); + + if(msg.value > cost) { + msg.sender.transfer(msg.value - cost); + } + } + + function renew(string calldata name, uint duration) external payable { + uint cost = rentPrice(name, duration); + require(msg.value >= cost); + + bytes32 label = keccak256(bytes(name)); + uint expires = base.renew(uint256(label), duration); + + if(msg.value > cost) { + msg.sender.transfer(msg.value - cost); + } + + emit NameRenewed(name, cost, expires); + } + + function setPriceOracle(PriceOracle _prices) public onlyOwner { + prices = _prices; + emit NewPriceOracle(address(prices)); + } + + function withdraw() public onlyOwner { + msg.sender.transfer(address(this).balance); + } +} diff --git a/contracts/mutants/ETHRegistrarController/5/RSD/diff_result_difft.json b/contracts/mutants/ETHRegistrarController/5/RSD/diff_result_difft.json new file mode 100644 index 00000000000..fee9607f546 --- /dev/null +++ b/contracts/mutants/ETHRegistrarController/5/RSD/diff_result_difft.json @@ -0,0 +1,434 @@ +{ + "number_of_changes": 55, + "timing": 0.10894083976745605, + "diff_chunks": [ + [ + { + "lhs": { + "line_number": 33, + "changes": [ + { + "start": 8, + "end": 14, + "content": "return", + "highlight": "keyword" + }, + { + "start": 15, + "end": 21, + "content": "prices", + "highlight": "normal" + }, + { + "start": 21, + "end": 22, + "content": ".", + "highlight": "normal" + }, + { + "start": 22, + "end": 27, + "content": "price", + "highlight": "normal" + }, + { + "start": 27, + "end": 28, + "content": "(", + "highlight": "delimiter" + }, + { + "start": 28, + "end": 32, + "content": "name", + "highlight": "normal" + }, + { + "start": 32, + "end": 33, + "content": ",", + "highlight": "normal" + }, + { + "start": 34, + "end": 38, + "content": "base", + "highlight": "normal" + }, + { + "start": 38, + "end": 39, + "content": ".", + "highlight": "normal" + }, + { + "start": 39, + "end": 50, + "content": "nameExpires", + "highlight": "normal" + }, + { + "start": 50, + "end": 51, + "content": "(", + "highlight": "delimiter" + }, + { + "start": 51, + "end": 58, + "content": "uint256", + "highlight": "normal" + }, + { + "start": 58, + "end": 59, + "content": "(", + "highlight": "delimiter" + }, + { + "start": 59, + "end": 63, + "content": "hash", + "highlight": "normal" + }, + { + "start": 63, + "end": 64, + "content": ")", + "highlight": "delimiter" + }, + { + "start": 64, + "end": 65, + "content": ")", + "highlight": "delimiter" + }, + { + "start": 65, + "end": 66, + "content": ",", + "highlight": "normal" + }, + { + "start": 67, + "end": 75, + "content": "duration", + "highlight": "normal" + }, + { + "start": 75, + "end": 76, + "content": ")", + "highlight": "delimiter" + } + ] + }, + "rhs": { + "line_number": 33, + "changes": [ + { + "start": 8, + "end": 83, + "content": "/* return prices.price(name, base.nameExpires(uint256(hash)), duration); */", + "highlight": "comment" + } + ] + } + }, + { + "lhs": { + "line_number": 37, + "changes": [ + { + "start": 8, + "end": 14, + "content": "return", + "highlight": "keyword" + }, + { + "start": 15, + "end": 19, + "content": "name", + "highlight": "normal" + }, + { + "start": 19, + "end": 20, + "content": ".", + "highlight": "normal" + }, + { + "start": 20, + "end": 26, + "content": "strlen", + "highlight": "normal" + }, + { + "start": 26, + "end": 27, + "content": "(", + "highlight": "delimiter" + }, + { + "start": 27, + "end": 28, + "content": ")", + "highlight": "delimiter" + }, + { + "start": 29, + "end": 30, + "content": ">", + "highlight": "keyword" + }, + { + "start": 31, + "end": 32, + "content": "6", + "highlight": "normal" + } + ] + }, + "rhs": { + "line_number": 37, + "changes": [ + { + "start": 8, + "end": 39, + "content": "/* return name.strlen() > 6; */", + "highlight": "comment" + } + ] + } + } + ], + [ + { + "lhs": { + "line_number": 42, + "changes": [ + { + "start": 8, + "end": 14, + "content": "return", + "highlight": "keyword" + }, + { + "start": 15, + "end": 20, + "content": "valid", + "highlight": "normal" + }, + { + "start": 20, + "end": 21, + "content": "(", + "highlight": "delimiter" + }, + { + "start": 21, + "end": 25, + "content": "name", + "highlight": "normal" + }, + { + "start": 25, + "end": 26, + "content": ")", + "highlight": "delimiter" + }, + { + "start": 27, + "end": 29, + "content": "&&", + "highlight": "keyword" + }, + { + "start": 30, + "end": 34, + "content": "base", + "highlight": "normal" + }, + { + "start": 34, + "end": 35, + "content": ".", + "highlight": "normal" + }, + { + "start": 35, + "end": 44, + "content": "available", + "highlight": "normal" + }, + { + "start": 44, + "end": 45, + "content": "(", + "highlight": "delimiter" + }, + { + "start": 45, + "end": 52, + "content": "uint256", + "highlight": "normal" + }, + { + "start": 52, + "end": 53, + "content": "(", + "highlight": "delimiter" + }, + { + "start": 53, + "end": 58, + "content": "label", + "highlight": "normal" + }, + { + "start": 58, + "end": 59, + "content": ")", + "highlight": "delimiter" + }, + { + "start": 59, + "end": 60, + "content": ")", + "highlight": "delimiter" + } + ] + }, + "rhs": { + "line_number": 42, + "changes": [ + { + "start": 8, + "end": 67, + "content": "/* return valid(name) && base.available(uint256(label)); */", + "highlight": "comment" + } + ] + } + } + ], + [ + { + "lhs": { + "line_number": 47, + "changes": [ + { + "start": 8, + "end": 14, + "content": "return", + "highlight": "keyword" + }, + { + "start": 15, + "end": 24, + "content": "keccak256", + "highlight": "normal" + }, + { + "start": 24, + "end": 25, + "content": "(", + "highlight": "delimiter" + }, + { + "start": 25, + "end": 28, + "content": "abi", + "highlight": "normal" + }, + { + "start": 28, + "end": 29, + "content": ".", + "highlight": "normal" + }, + { + "start": 29, + "end": 41, + "content": "encodePacked", + "highlight": "normal" + }, + { + "start": 41, + "end": 42, + "content": "(", + "highlight": "delimiter" + }, + { + "start": 42, + "end": 47, + "content": "label", + "highlight": "normal" + }, + { + "start": 47, + "end": 48, + "content": ",", + "highlight": "normal" + }, + { + "start": 49, + "end": 55, + "content": "secret", + "highlight": "normal" + }, + { + "start": 55, + "end": 56, + "content": ")", + "highlight": "delimiter" + }, + { + "start": 56, + "end": 57, + "content": ")", + "highlight": "delimiter" + } + ] + }, + "rhs": { + "line_number": 47, + "changes": [ + { + "start": 8, + "end": 64, + "content": "/* return keccak256(abi.encodePacked(label, secret)); */", + "highlight": "comment" + } + ] + } + } + ], + [ + { + "lhs": { + "line_number": 63, + "changes": [ + { + "start": 12, + "end": 18, + "content": "return", + "highlight": "keyword" + } + ] + }, + "rhs": { + "line_number": 63, + "changes": [ + { + "start": 12, + "end": 25, + "content": "/* return; */", + "highlight": "comment" + } + ] + } + } + ] + ] +} \ No newline at end of file diff --git a/contracts/mutants/ETHRegistrarController/5/VVR/ETHRegistrarController.sol b/contracts/mutants/ETHRegistrarController/5/VVR/ETHRegistrarController.sol new file mode 100644 index 00000000000..4aed2008cab --- /dev/null +++ b/contracts/mutants/ETHRegistrarController/5/VVR/ETHRegistrarController.sol @@ -0,0 +1,103 @@ +pragma solidity ^0.5.0; + +import "./PriceOracle.sol"; +import "./BaseRegistrar.sol"; +import "./StringUtils.sol"; +import "openzeppelin-solidity/contracts/ownership/Ownable.sol"; + +/** + * @dev A registrar controller for registering and renewing names at fixed cost. + */ +contract ETHRegistrarController is Ownable { + using StringUtils for *; + + uint constant internal MIN_COMMITMENT_AGE = 1 hours; + uint constant internal MAX_COMMITMENT_AGE = 48 hours; + uint constant internal MIN_REGISTRATION_DURATION = 28 days; + + BaseRegistrar public base; + PriceOracle public prices; + + mapping(bytes32=>uint) public commitments; + + event NameRegistered(string name, address indexed owner, uint cost, uint expires); + event NameRenewed(string name, uint cost, uint expires); + event NewPriceOracle(address indexed oracle); + + constructor(BaseRegistrar _base, PriceOracle _prices) public { + base = _base; + prices = _prices; + } + + function rentPrice(string memory name, uint duration) view public returns(uint) { + bytes32 hash = keccak256(bytes(name)); + return prices.price(name, base.nameExpires(uint256(hash)), duration); + } + + function valid(string memory name) public view returns(bool) { + return name.strlen() > 6; + } + + function available(string memory name) public view returns(bool) { + bytes32 label = keccak256(bytes(name)); + return valid(name) && base.available(uint256(label)); + } + // SWC-114-Transaction Order Dependence: L46-L49 + function makeCommitment(string memory name, bytes32 secret) pure public returns(bytes32) { + bytes32 label = keccak256(bytes(name)); + return keccak256(abi.encodePacked(label, secret)); + } + + function commit(bytes32 commitment) public { + require(commitments[commitment] + MAX_COMMITMENT_AGE < now); + commitments[commitment] = now; + } + // SWC-104-Unchecked Call Return Value: L56-L65 + function register(string calldata name, address owner, uint duration, bytes32 secret) external payable { + // Require a valid commitment + bytes32 commitment = makeCommitment(name, secret); + require(commitments[commitment] + MIN_COMMITMENT_AGE <= now); + + // If the commitment is too old, or the name is registered, stop + if(commitments[commitment] + MAX_COMMITMENT_AGE < now || !available(name)) { + msg.sender.transfer(msg.value); + return; + } + delete(commitments[commitment]); + + uint cost = rentPrice(name, duration); + require(duration >= MIN_REGISTRATION_DURATION); + require(msg.value >= cost); + + bytes32 label = keccak256(bytes(name)); + uint expires = base.register(uint256(label), owner, duration); + emit NameRegistered(name, owner, cost, expires); + + if(msg.value > cost) { + msg.sender.transfer(msg.value - cost); + } + } + + function renew(string calldata name, uint duration) external payable { + uint cost = rentPrice(name, duration); + require(msg.value >= cost); + + bytes32 label = keccak256(bytes(name)); + uint expires = base.renew(uint256(label), duration); + + if(msg.value > cost) { + msg.sender.transfer(msg.value - cost); + } + + emit NameRenewed(name, cost, expires); + } + + function setPriceOracle(PriceOracle _prices) public onlyOwner { + prices = _prices; + emit NewPriceOracle(address(prices)); + } + + function withdraw() public onlyOwner { + msg.sender.transfer(address(this).balance); + } +} diff --git a/contracts/mutants/ETHRegistrarController/5/VVR/diff_result_difft.json b/contracts/mutants/ETHRegistrarController/5/VVR/diff_result_difft.json new file mode 100644 index 00000000000..357f5e5d214 --- /dev/null +++ b/contracts/mutants/ETHRegistrarController/5/VVR/diff_result_difft.json @@ -0,0 +1,114 @@ +{ + "number_of_changes": 5, + "timing": 0.18677353858947754, + "diff_chunks": [ + [ + { + "lhs": { + "line_number": 17, + "changes": [] + }, + "rhs": { + "line_number": 17, + "changes": [ + { + "start": 18, + "end": 24, + "content": "public", + "highlight": "keyword" + } + ] + } + }, + { + "lhs": { + "line_number": 14, + "changes": [ + { + "start": 18, + "end": 24, + "content": "public", + "highlight": "keyword" + } + ] + }, + "rhs": { + "line_number": 14, + "changes": [ + { + "start": 18, + "end": 26, + "content": "internal", + "highlight": "keyword" + } + ] + } + }, + { + "lhs": { + "line_number": 13, + "changes": [ + { + "start": 18, + "end": 24, + "content": "public", + "highlight": "keyword" + } + ] + }, + "rhs": { + "line_number": 13, + "changes": [ + { + "start": 18, + "end": 26, + "content": "internal", + "highlight": "keyword" + } + ] + } + }, + { + "lhs": { + "line_number": 15, + "changes": [ + { + "start": 18, + "end": 24, + "content": "public", + "highlight": "keyword" + } + ] + }, + "rhs": { + "line_number": 15, + "changes": [ + { + "start": 18, + "end": 26, + "content": "internal", + "highlight": "keyword" + } + ] + } + }, + { + "lhs": { + "line_number": 18, + "changes": [] + }, + "rhs": { + "line_number": 18, + "changes": [ + { + "start": 16, + "end": 22, + "content": "public", + "highlight": "keyword" + } + ] + } + } + ] + ] +} \ No newline at end of file diff --git a/contracts/mutants/ETHRegistrarController/6/BOR/ETHRegistrarController.sol b/contracts/mutants/ETHRegistrarController/6/BOR/ETHRegistrarController.sol new file mode 100644 index 00000000000..06e6273c9f8 --- /dev/null +++ b/contracts/mutants/ETHRegistrarController/6/BOR/ETHRegistrarController.sol @@ -0,0 +1,103 @@ +pragma solidity ^0.5.0; + +import "./PriceOracle.sol"; +import "./BaseRegistrar.sol"; +import "./StringUtils.sol"; +import "openzeppelin-solidity/contracts/ownership/Ownable.sol"; + +/** + * @dev A registrar controller for registering and renewing names at fixed cost. + */ +contract ETHRegistrarController is Ownable { + using StringUtils for *; + + uint constant public MIN_COMMITMENT_AGE = 1 hours; + uint constant public MAX_COMMITMENT_AGE = 48 hours; + uint constant public MIN_REGISTRATION_DURATION = 28 days; + + BaseRegistrar base; + PriceOracle prices; + + mapping(bytes32=>uint) public commitments; + + event NameRegistered(string name, address indexed owner, uint cost, uint expires); + event NameRenewed(string name, uint cost, uint expires); + event NewPriceOracle(address indexed oracle); + + constructor(BaseRegistrar _base, PriceOracle _prices) public { + base = _base; + prices = _prices; + } + + function rentPrice(string memory name, uint duration) view public returns(uint) { + bytes32 hash = keccak256(bytes(name)); + return prices.price(name, base.nameExpires(uint256(hash)), duration); + } + + function valid(string memory name) public view returns(bool) { + return name.strlen() >= 6; + } + + function available(string memory name) public view returns(bool) { + bytes32 label = keccak256(bytes(name)); + return valid(name) || base.available(uint256(label)); + } + // SWC-114-Transaction Order Dependence: L46-L49 + function makeCommitment(string memory name, bytes32 secret) pure public returns(bytes32) { + bytes32 label = keccak256(bytes(name)); + return keccak256(abi.encodePacked(label, secret)); + } + + function commit(bytes32 commitment) public { + require(commitments[commitment] - MAX_COMMITMENT_AGE <= now); + commitments[commitment] = now; + } + // SWC-104-Unchecked Call Return Value: L56-L65 + function register(string calldata name, address owner, uint duration, bytes32 secret) external payable { + // Require a valid commitment + bytes32 commitment = makeCommitment(name, secret); + require(commitments[commitment] - MIN_COMMITMENT_AGE < now); + + // If the commitment is too old, or the name is registered, stop + if(commitments[commitment] + MAX_COMMITMENT_AGE < now || !available(name)) { + msg.sender.transfer(msg.value); + return; + } + delete(commitments[commitment]); + + uint cost = rentPrice(name, duration); + require(duration >= MIN_REGISTRATION_DURATION); + require(msg.value >= cost); + + bytes32 label = keccak256(bytes(name)); + uint expires = base.register(uint256(label), owner, duration); + emit NameRegistered(name, owner, cost, expires); + + if(msg.value > cost) { + msg.sender.transfer(msg.value - cost); + } + } + + function renew(string calldata name, uint duration) external payable { + uint cost = rentPrice(name, duration); + require(msg.value >= cost); + + bytes32 label = keccak256(bytes(name)); + uint expires = base.renew(uint256(label), duration); + + if(msg.value > cost) { + msg.sender.transfer(msg.value - cost); + } + + emit NameRenewed(name, cost, expires); + } + + function setPriceOracle(PriceOracle _prices) public onlyOwner { + prices = _prices; + emit NewPriceOracle(address(prices)); + } + + function withdraw() public onlyOwner { + msg.sender.transfer(address(this).balance); + } +} diff --git a/contracts/mutants/ETHRegistrarController/6/BOR/diff_result_difft.json b/contracts/mutants/ETHRegistrarController/6/BOR/diff_result_difft.json new file mode 100644 index 00000000000..a955b9a6872 --- /dev/null +++ b/contracts/mutants/ETHRegistrarController/6/BOR/diff_result_difft.json @@ -0,0 +1,134 @@ +{ + "number_of_changes": 6, + "timing": 0.21227192878723145, + "diff_chunks": [ + [ + { + "lhs": { + "line_number": 37, + "changes": [ + { + "start": 29, + "end": 30, + "content": ">", + "highlight": "keyword" + } + ] + }, + "rhs": { + "line_number": 37, + "changes": [ + { + "start": 29, + "end": 31, + "content": ">=", + "highlight": "keyword" + } + ] + } + } + ], + [ + { + "lhs": { + "line_number": 42, + "changes": [ + { + "start": 27, + "end": 29, + "content": "&&", + "highlight": "keyword" + } + ] + }, + "rhs": { + "line_number": 42, + "changes": [ + { + "start": 27, + "end": 29, + "content": "||", + "highlight": "keyword" + } + ] + } + } + ], + [ + { + "lhs": { + "line_number": 51, + "changes": [ + { + "start": 40, + "end": 41, + "content": "+", + "highlight": "keyword" + }, + { + "start": 61, + "end": 62, + "content": "<", + "highlight": "keyword" + } + ] + }, + "rhs": { + "line_number": 51, + "changes": [ + { + "start": 40, + "end": 41, + "content": "-", + "highlight": "keyword" + }, + { + "start": 61, + "end": 63, + "content": "<=", + "highlight": "keyword" + } + ] + } + } + ], + [ + { + "lhs": { + "line_number": 58, + "changes": [ + { + "start": 40, + "end": 41, + "content": "+", + "highlight": "keyword" + }, + { + "start": 61, + "end": 63, + "content": "<=", + "highlight": "keyword" + } + ] + }, + "rhs": { + "line_number": 58, + "changes": [ + { + "start": 40, + "end": 41, + "content": "-", + "highlight": "keyword" + }, + { + "start": 62, + "end": 63, + "content": "<", + "highlight": "keyword" + } + ] + } + } + ] + ] +} \ No newline at end of file diff --git a/contracts/mutants/ETHRegistrarController/6/ECS/ETHRegistrarController.sol b/contracts/mutants/ETHRegistrarController/6/ECS/ETHRegistrarController.sol new file mode 100644 index 00000000000..123fc16fae3 --- /dev/null +++ b/contracts/mutants/ETHRegistrarController/6/ECS/ETHRegistrarController.sol @@ -0,0 +1,103 @@ +pragma solidity ^0.5.0; + +import "./PriceOracle.sol"; +import "./BaseRegistrar.sol"; +import "./StringUtils.sol"; +import "openzeppelin-solidity/contracts/ownership/Ownable.sol"; + +/** + * @dev A registrar controller for registering and renewing names at fixed cost. + */ +contract ETHRegistrarController is Ownable { + using StringUtils for *; + + uint constant public MIN_COMMITMENT_AGE = 1 hours; + uint constant public MAX_COMMITMENT_AGE = 48 hours; + uint constant public MIN_REGISTRATION_DURATION = 28 days; + + BaseRegistrar base; + PriceOracle prices; + + mapping(bytes32=>uint) public commitments; + + event NameRegistered(string name, address indexed owner, uint cost, uint expires); + event NameRenewed(string name, uint cost, uint expires); + event NewPriceOracle(address indexed oracle); + + constructor(BaseRegistrar _base, PriceOracle _prices) public { + base = _base; + prices = _prices; + } + + function rentPrice(string memory name, uint duration) view public returns(uint) { + bytes32 hash = keccak256(bytes1(name)); + return prices.price(name, base.nameExpires(uint8(hash)), duration); + } + + function valid(string memory name) public view returns(bool) { + return name.strlen() > 6; + } + + function available(string memory name) public view returns(bool) { + bytes32 label = keccak256(bytes1(name)); + return valid(name) && base.available(uint8(label)); + } + // SWC-114-Transaction Order Dependence: L46-L49 + function makeCommitment(string memory name, bytes32 secret) pure public returns(bytes32) { + bytes32 label = keccak256(bytes1(name)); + return keccak256(abi.encodePacked(label, secret)); + } + + function commit(bytes32 commitment) public { + require(commitments[commitment] + MAX_COMMITMENT_AGE < now); + commitments[commitment] = now; + } + // SWC-104-Unchecked Call Return Value: L56-L65 + function register(string calldata name, address owner, uint duration, bytes32 secret) external payable { + // Require a valid commitment + bytes32 commitment = makeCommitment(name, secret); + require(commitments[commitment] + MIN_COMMITMENT_AGE <= now); + + // If the commitment is too old, or the name is registered, stop + if(commitments[commitment] + MAX_COMMITMENT_AGE < now || !available(name)) { + msg.sender.transfer(msg.value); + return; + } + delete(commitments[commitment]); + + uint cost = rentPrice(name, duration); + require(duration >= MIN_REGISTRATION_DURATION); + require(msg.value >= cost); + + bytes32 label = keccak256(bytes1(name)); + uint expires = base.register(uint256(label), owner, duration); + emit NameRegistered(name, owner, cost, expires); + + if(msg.value > cost) { + msg.sender.transfer(msg.value - cost); + } + } + + function renew(string calldata name, uint duration) external payable { + uint cost = rentPrice(name, duration); + require(msg.value >= cost); + + bytes32 label = keccak256(bytes(name)); + uint expires = base.renew(uint256(label), duration); + + if(msg.value > cost) { + msg.sender.transfer(msg.value - cost); + } + + emit NameRenewed(name, cost, expires); + } + + function setPriceOracle(PriceOracle _prices) public onlyOwner { + prices = _prices; + emit NewPriceOracle(address(prices)); + } + + function withdraw() public onlyOwner { + msg.sender.transfer(address(this).balance); + } +} diff --git a/contracts/mutants/ETHRegistrarController/6/ECS/diff_result_difft.json b/contracts/mutants/ETHRegistrarController/6/ECS/diff_result_difft.json new file mode 100644 index 00000000000..418d4b40e0a --- /dev/null +++ b/contracts/mutants/ETHRegistrarController/6/ECS/diff_result_difft.json @@ -0,0 +1,156 @@ +{ + "number_of_changes": 6, + "timing": 0.16750669479370117, + "diff_chunks": [ + [ + { + "lhs": { + "line_number": 33, + "changes": [ + { + "start": 51, + "end": 58, + "content": "uint256", + "highlight": "normal" + } + ] + }, + "rhs": { + "line_number": 33, + "changes": [ + { + "start": 51, + "end": 56, + "content": "uint8", + "highlight": "normal" + } + ] + } + }, + { + "lhs": { + "line_number": 32, + "changes": [ + { + "start": 33, + "end": 38, + "content": "bytes", + "highlight": "normal" + } + ] + }, + "rhs": { + "line_number": 32, + "changes": [ + { + "start": 33, + "end": 39, + "content": "bytes1", + "highlight": "normal" + } + ] + } + } + ], + [ + { + "lhs": { + "line_number": 46, + "changes": [ + { + "start": 34, + "end": 39, + "content": "bytes", + "highlight": "normal" + } + ] + }, + "rhs": { + "line_number": 46, + "changes": [ + { + "start": 34, + "end": 40, + "content": "bytes1", + "highlight": "normal" + } + ] + } + }, + { + "lhs": { + "line_number": 42, + "changes": [ + { + "start": 45, + "end": 52, + "content": "uint256", + "highlight": "normal" + } + ] + }, + "rhs": { + "line_number": 42, + "changes": [ + { + "start": 45, + "end": 50, + "content": "uint8", + "highlight": "normal" + } + ] + } + }, + { + "lhs": { + "line_number": 41, + "changes": [ + { + "start": 34, + "end": 39, + "content": "bytes", + "highlight": "normal" + } + ] + }, + "rhs": { + "line_number": 41, + "changes": [ + { + "start": 34, + "end": 40, + "content": "bytes1", + "highlight": "normal" + } + ] + } + } + ], + [ + { + "lhs": { + "line_number": 71, + "changes": [ + { + "start": 34, + "end": 39, + "content": "bytes", + "highlight": "normal" + } + ] + }, + "rhs": { + "line_number": 71, + "changes": [ + { + "start": 34, + "end": 40, + "content": "bytes1", + "highlight": "normal" + } + ] + } + } + ] + ] +} \ No newline at end of file diff --git a/contracts/mutants/ETHRegistrarController/6/FVR/ETHRegistrarController.sol b/contracts/mutants/ETHRegistrarController/6/FVR/ETHRegistrarController.sol new file mode 100644 index 00000000000..f644ce5e530 --- /dev/null +++ b/contracts/mutants/ETHRegistrarController/6/FVR/ETHRegistrarController.sol @@ -0,0 +1,103 @@ +pragma solidity ^0.5.0; + +import "./PriceOracle.sol"; +import "./BaseRegistrar.sol"; +import "./StringUtils.sol"; +import "openzeppelin-solidity/contracts/ownership/Ownable.sol"; + +/** + * @dev A registrar controller for registering and renewing names at fixed cost. + */ +contract ETHRegistrarController is Ownable { + using StringUtils for *; + + uint constant public MIN_COMMITMENT_AGE = 1 hours; + uint constant public MAX_COMMITMENT_AGE = 48 hours; + uint constant public MIN_REGISTRATION_DURATION = 28 days; + + BaseRegistrar base; + PriceOracle prices; + + mapping(bytes32=>uint) public commitments; + + event NameRegistered(string name, address indexed owner, uint cost, uint expires); + event NameRenewed(string name, uint cost, uint expires); + event NewPriceOracle(address indexed oracle); + + constructor(BaseRegistrar _base, PriceOracle _prices) internal { + base = _base; + prices = _prices; + } + + function rentPrice(string memory name, uint duration) view external returns(uint) { + bytes32 hash = keccak256(bytes(name)); + return prices.price(name, base.nameExpires(uint256(hash)), duration); + } + + function valid(string memory name) external view returns(bool) { + return name.strlen() > 6; + } + + function available(string memory name) external view returns(bool) { + bytes32 label = keccak256(bytes(name)); + return valid(name) && base.available(uint256(label)); + } + // SWC-114-Transaction Order Dependence: L46-L49 + function makeCommitment(string memory name, bytes32 secret) pure external returns(bytes32) { + bytes32 label = keccak256(bytes(name)); + return keccak256(abi.encodePacked(label, secret)); + } + + function commit(bytes32 commitment) external { + require(commitments[commitment] + MAX_COMMITMENT_AGE < now); + commitments[commitment] = now; + } + // SWC-104-Unchecked Call Return Value: L56-L65 + function register(string calldata name, address owner, uint duration, bytes32 secret) external payable { + // Require a valid commitment + bytes32 commitment = makeCommitment(name, secret); + require(commitments[commitment] + MIN_COMMITMENT_AGE <= now); + + // If the commitment is too old, or the name is registered, stop + if(commitments[commitment] + MAX_COMMITMENT_AGE < now || !available(name)) { + msg.sender.transfer(msg.value); + return; + } + delete(commitments[commitment]); + + uint cost = rentPrice(name, duration); + require(duration >= MIN_REGISTRATION_DURATION); + require(msg.value >= cost); + + bytes32 label = keccak256(bytes(name)); + uint expires = base.register(uint256(label), owner, duration); + emit NameRegistered(name, owner, cost, expires); + + if(msg.value > cost) { + msg.sender.transfer(msg.value - cost); + } + } + + function renew(string calldata name, uint duration) external payable { + uint cost = rentPrice(name, duration); + require(msg.value >= cost); + + bytes32 label = keccak256(bytes(name)); + uint expires = base.renew(uint256(label), duration); + + if(msg.value > cost) { + msg.sender.transfer(msg.value - cost); + } + + emit NameRenewed(name, cost, expires); + } + + function setPriceOracle(PriceOracle _prices) public onlyOwner { + prices = _prices; + emit NewPriceOracle(address(prices)); + } + + function withdraw() public onlyOwner { + msg.sender.transfer(address(this).balance); + } +} diff --git a/contracts/mutants/ETHRegistrarController/6/FVR/diff_result_difft.json b/contracts/mutants/ETHRegistrarController/6/FVR/diff_result_difft.json new file mode 100644 index 00000000000..e0f00b22cb1 --- /dev/null +++ b/contracts/mutants/ETHRegistrarController/6/FVR/diff_result_difft.json @@ -0,0 +1,160 @@ +{ + "number_of_changes": 6, + "timing": 0.2927079200744629, + "diff_chunks": [ + [ + { + "lhs": { + "line_number": 26, + "changes": [ + { + "start": 58, + "end": 64, + "content": "public", + "highlight": "keyword" + } + ] + }, + "rhs": { + "line_number": 26, + "changes": [ + { + "start": 58, + "end": 66, + "content": "internal", + "highlight": "keyword" + } + ] + } + } + ], + [ + { + "lhs": { + "line_number": 31, + "changes": [ + { + "start": 63, + "end": 69, + "content": "public", + "highlight": "keyword" + } + ] + }, + "rhs": { + "line_number": 31, + "changes": [ + { + "start": 63, + "end": 71, + "content": "external", + "highlight": "keyword" + } + ] + } + } + ], + [ + { + "lhs": { + "line_number": 36, + "changes": [ + { + "start": 39, + "end": 45, + "content": "public", + "highlight": "keyword" + } + ] + }, + "rhs": { + "line_number": 36, + "changes": [ + { + "start": 39, + "end": 47, + "content": "external", + "highlight": "keyword" + } + ] + } + }, + { + "lhs": { + "line_number": 40, + "changes": [ + { + "start": 43, + "end": 49, + "content": "public", + "highlight": "keyword" + } + ] + }, + "rhs": { + "line_number": 40, + "changes": [ + { + "start": 43, + "end": 51, + "content": "external", + "highlight": "keyword" + } + ] + } + } + ], + [ + { + "lhs": { + "line_number": 45, + "changes": [ + { + "start": 69, + "end": 75, + "content": "public", + "highlight": "keyword" + } + ] + }, + "rhs": { + "line_number": 45, + "changes": [ + { + "start": 69, + "end": 77, + "content": "external", + "highlight": "keyword" + } + ] + } + } + ], + [ + { + "lhs": { + "line_number": 50, + "changes": [ + { + "start": 40, + "end": 46, + "content": "public", + "highlight": "keyword" + } + ] + }, + "rhs": { + "line_number": 50, + "changes": [ + { + "start": 40, + "end": 48, + "content": "external", + "highlight": "keyword" + } + ] + } + } + ] + ] +} \ No newline at end of file diff --git a/contracts/mutants/ETHRegistrarController/6/GVR/ETHRegistrarController.sol b/contracts/mutants/ETHRegistrarController/6/GVR/ETHRegistrarController.sol new file mode 100644 index 00000000000..ef66661e151 --- /dev/null +++ b/contracts/mutants/ETHRegistrarController/6/GVR/ETHRegistrarController.sol @@ -0,0 +1,103 @@ +pragma solidity ^0.5.0; + +import "./PriceOracle.sol"; +import "./BaseRegistrar.sol"; +import "./StringUtils.sol"; +import "openzeppelin-solidity/contracts/ownership/Ownable.sol"; + +/** + * @dev A registrar controller for registering and renewing names at fixed cost. + */ +contract ETHRegistrarController is Ownable { + using StringUtils for *; + + uint constant public MIN_COMMITMENT_AGE = 1 hours; + uint constant public MAX_COMMITMENT_AGE = 48 hours; + uint constant public MIN_REGISTRATION_DURATION = 28 days; + + BaseRegistrar base; + PriceOracle prices; + + mapping(bytes32=>uint) public commitments; + + event NameRegistered(string name, address indexed owner, uint cost, uint expires); + event NameRenewed(string name, uint cost, uint expires); + event NewPriceOracle(address indexed oracle); + + constructor(BaseRegistrar _base, PriceOracle _prices) public { + base = _base; + prices = _prices; + } + + function rentPrice(string memory name, uint duration) view public returns(uint) { + bytes32 hash = keccak256(bytes(name)); + return prices.price(name, base.nameExpires(uint256(hash)), duration); + } + + function valid(string memory name) public view returns(bool) { + return name.strlen() > 6; + } + + function available(string memory name) public view returns(bool) { + bytes32 label = keccak256(bytes(name)); + return valid(name) && base.available(uint256(label)); + } + // SWC-114-Transaction Order Dependence: L46-L49 + function makeCommitment(string memory name, bytes32 secret) pure public returns(bytes32) { + bytes32 label = keccak256(bytes(name)); + return keccak256(abi.encodePacked(label, secret)); + } + + function commit(bytes32 commitment) public { + require(commitments[commitment] + MAX_COMMITMENT_AGE < block.difficulty); + commitments[commitment] = block.difficulty; + } + // SWC-104-Unchecked Call Return Value: L56-L65 + function register(string calldata name, address owner, uint duration, bytes32 secret) external payable { + // Require a valid commitment + bytes32 commitment = makeCommitment(name, secret); + require(commitments[commitment] + MIN_COMMITMENT_AGE <= block.difficulty); + + // If the commitment is too old, or the name is registered, stop + if(commitments[commitment] + MAX_COMMITMENT_AGE < block.difficulty || !available(name)) { + msg.sender.transfer(tx.gasprice); + return; + } + delete(commitments[commitment]); + + uint cost = rentPrice(name, duration); + require(duration >= MIN_REGISTRATION_DURATION); + require(tx.gasprice >= cost); + + bytes32 label = keccak256(bytes(name)); + uint expires = base.register(uint256(label), owner, duration); + emit NameRegistered(name, owner, cost, expires); + + if(msg.value > cost) { + msg.sender.transfer(msg.value - cost); + } + } + + function renew(string calldata name, uint duration) external payable { + uint cost = rentPrice(name, duration); + require(msg.value >= cost); + + bytes32 label = keccak256(bytes(name)); + uint expires = base.renew(uint256(label), duration); + + if(msg.value > cost) { + msg.sender.transfer(msg.value - cost); + } + + emit NameRenewed(name, cost, expires); + } + + function setPriceOracle(PriceOracle _prices) public onlyOwner { + prices = _prices; + emit NewPriceOracle(address(prices)); + } + + function withdraw() public onlyOwner { + msg.sender.transfer(address(this).balance); + } +} diff --git a/contracts/mutants/ETHRegistrarController/6/GVR/diff_result_difft.json b/contracts/mutants/ETHRegistrarController/6/GVR/diff_result_difft.json new file mode 100644 index 00000000000..96b07470251 --- /dev/null +++ b/contracts/mutants/ETHRegistrarController/6/GVR/diff_result_difft.json @@ -0,0 +1,228 @@ +{ + "number_of_changes": 16, + "timing": 0.13720250129699707, + "diff_chunks": [ + [ + { + "lhs": { + "line_number": 51, + "changes": [ + { + "start": 63, + "end": 66, + "content": "now", + "highlight": "normal" + } + ] + }, + "rhs": { + "line_number": 51, + "changes": [ + { + "start": 63, + "end": 68, + "content": "block", + "highlight": "normal" + }, + { + "start": 68, + "end": 69, + "content": ".", + "highlight": "normal" + }, + { + "start": 69, + "end": 79, + "content": "difficulty", + "highlight": "normal" + } + ] + } + }, + { + "lhs": { + "line_number": 52, + "changes": [ + { + "start": 34, + "end": 37, + "content": "now", + "highlight": "normal" + } + ] + }, + "rhs": { + "line_number": 52, + "changes": [ + { + "start": 34, + "end": 39, + "content": "block", + "highlight": "normal" + }, + { + "start": 39, + "end": 40, + "content": ".", + "highlight": "normal" + }, + { + "start": 40, + "end": 50, + "content": "difficulty", + "highlight": "normal" + } + ] + } + } + ], + [ + { + "lhs": { + "line_number": 62, + "changes": [ + { + "start": 32, + "end": 35, + "content": "msg", + "highlight": "normal" + }, + { + "start": 36, + "end": 41, + "content": "value", + "highlight": "normal" + } + ] + }, + "rhs": { + "line_number": 62, + "changes": [ + { + "start": 32, + "end": 34, + "content": "tx", + "highlight": "normal" + }, + { + "start": 35, + "end": 43, + "content": "gasprice", + "highlight": "normal" + } + ] + } + }, + { + "lhs": { + "line_number": 58, + "changes": [ + { + "start": 64, + "end": 67, + "content": "now", + "highlight": "normal" + } + ] + }, + "rhs": { + "line_number": 58, + "changes": [ + { + "start": 64, + "end": 69, + "content": "block", + "highlight": "normal" + }, + { + "start": 69, + "end": 70, + "content": ".", + "highlight": "normal" + }, + { + "start": 70, + "end": 80, + "content": "difficulty", + "highlight": "normal" + } + ] + } + }, + { + "lhs": { + "line_number": 61, + "changes": [ + { + "start": 58, + "end": 61, + "content": "now", + "highlight": "normal" + } + ] + }, + "rhs": { + "line_number": 61, + "changes": [ + { + "start": 58, + "end": 63, + "content": "block", + "highlight": "normal" + }, + { + "start": 63, + "end": 64, + "content": ".", + "highlight": "normal" + }, + { + "start": 64, + "end": 74, + "content": "difficulty", + "highlight": "normal" + } + ] + } + } + ], + [ + { + "lhs": { + "line_number": 69, + "changes": [ + { + "start": 16, + "end": 19, + "content": "msg", + "highlight": "normal" + }, + { + "start": 20, + "end": 25, + "content": "value", + "highlight": "normal" + } + ] + }, + "rhs": { + "line_number": 69, + "changes": [ + { + "start": 16, + "end": 18, + "content": "tx", + "highlight": "normal" + }, + { + "start": 19, + "end": 27, + "content": "gasprice", + "highlight": "normal" + } + ] + } + } + ] + ] +} \ No newline at end of file diff --git a/contracts/mutants/ETHRegistrarController/6/MCR/ETHRegistrarController.sol b/contracts/mutants/ETHRegistrarController/6/MCR/ETHRegistrarController.sol new file mode 100644 index 00000000000..287a1a6b149 --- /dev/null +++ b/contracts/mutants/ETHRegistrarController/6/MCR/ETHRegistrarController.sol @@ -0,0 +1,103 @@ +pragma solidity ^0.5.0; + +import "./PriceOracle.sol"; +import "./BaseRegistrar.sol"; +import "./StringUtils.sol"; +import "openzeppelin-solidity/contracts/ownership/Ownable.sol"; + +/** + * @dev A registrar controller for registering and renewing names at fixed cost. + */ +contract ETHRegistrarController is Ownable { + using StringUtils for *; + + uint constant public MIN_COMMITMENT_AGE = 1 hours; + uint constant public MAX_COMMITMENT_AGE = 48 hours; + uint constant public MIN_REGISTRATION_DURATION = 28 days; + + BaseRegistrar base; + PriceOracle prices; + + mapping(bytes32=>uint) public commitments; + + event NameRegistered(string name, address indexed owner, uint cost, uint expires); + event NameRenewed(string name, uint cost, uint expires); + event NewPriceOracle(address indexed oracle); + + constructor(BaseRegistrar _base, PriceOracle _prices) public { + base = _base; + prices = _prices; + } + + function rentPrice(string memory name, uint duration) view public returns(uint) { + bytes32 hash = sha256(bytes(name)); + return prices.price(name, base.nameExpires(uint256(hash)), duration); + } + + function valid(string memory name) public view returns(bool) { + return name.strlen() > 6; + } + + function available(string memory name) public view returns(bool) { + bytes32 label = sha256(bytes(name)); + return valid(name) && base.available(uint256(label)); + } + // SWC-114-Transaction Order Dependence: L46-L49 + function makeCommitment(string memory name, bytes32 secret) pure public returns(bytes32) { + bytes32 label = sha256(bytes(name)); + return sha256(abi.encodePacked(label, secret)); + } + + function commit(bytes32 commitment) public { + require(commitments[commitment] + MAX_COMMITMENT_AGE < now); + commitments[commitment] = now; + } + // SWC-104-Unchecked Call Return Value: L56-L65 + function register(string calldata name, address owner, uint duration, bytes32 secret) external payable { + // Require a valid commitment + bytes32 commitment = makeCommitment(name, secret); + require(commitments[commitment] + MIN_COMMITMENT_AGE <= now); + + // If the commitment is too old, or the name is registered, stop + if(commitments[commitment] + MAX_COMMITMENT_AGE < now || !available(name)) { + msg.sender.transfer(msg.value); + return; + } + delete(commitments[commitment]); + + uint cost = rentPrice(name, duration); + require(duration >= MIN_REGISTRATION_DURATION); + require(msg.value >= cost); + + bytes32 label = sha256(bytes(name)); + uint expires = base.register(uint256(label), owner, duration); + emit NameRegistered(name, owner, cost, expires); + + if(msg.value > cost) { + msg.sender.transfer(msg.value - cost); + } + } + + function renew(string calldata name, uint duration) external payable { + uint cost = rentPrice(name, duration); + require(msg.value >= cost); + + bytes32 label = sha256(bytes(name)); + uint expires = base.renew(uint256(label), duration); + + if(msg.value > cost) { + msg.sender.transfer(msg.value - cost); + } + + emit NameRenewed(name, cost, expires); + } + + function setPriceOracle(PriceOracle _prices) public onlyOwner { + prices = _prices; + emit NewPriceOracle(address(prices)); + } + + function withdraw() public onlyOwner { + msg.sender.transfer(address(this).balance); + } +} diff --git a/contracts/mutants/ETHRegistrarController/6/MCR/diff_result_difft.json b/contracts/mutants/ETHRegistrarController/6/MCR/diff_result_difft.json new file mode 100644 index 00000000000..49ab313ab28 --- /dev/null +++ b/contracts/mutants/ETHRegistrarController/6/MCR/diff_result_difft.json @@ -0,0 +1,160 @@ +{ + "number_of_changes": 6, + "timing": 0.12592458724975586, + "diff_chunks": [ + [ + { + "lhs": { + "line_number": 32, + "changes": [ + { + "start": 23, + "end": 32, + "content": "keccak256", + "highlight": "normal" + } + ] + }, + "rhs": { + "line_number": 32, + "changes": [ + { + "start": 23, + "end": 29, + "content": "sha256", + "highlight": "normal" + } + ] + } + } + ], + [ + { + "lhs": { + "line_number": 41, + "changes": [ + { + "start": 24, + "end": 33, + "content": "keccak256", + "highlight": "normal" + } + ] + }, + "rhs": { + "line_number": 41, + "changes": [ + { + "start": 24, + "end": 30, + "content": "sha256", + "highlight": "normal" + } + ] + } + } + ], + [ + { + "lhs": { + "line_number": 46, + "changes": [ + { + "start": 24, + "end": 33, + "content": "keccak256", + "highlight": "normal" + } + ] + }, + "rhs": { + "line_number": 46, + "changes": [ + { + "start": 24, + "end": 30, + "content": "sha256", + "highlight": "normal" + } + ] + } + }, + { + "lhs": { + "line_number": 47, + "changes": [ + { + "start": 15, + "end": 24, + "content": "keccak256", + "highlight": "normal" + } + ] + }, + "rhs": { + "line_number": 47, + "changes": [ + { + "start": 15, + "end": 21, + "content": "sha256", + "highlight": "normal" + } + ] + } + } + ], + [ + { + "lhs": { + "line_number": 71, + "changes": [ + { + "start": 24, + "end": 33, + "content": "keccak256", + "highlight": "normal" + } + ] + }, + "rhs": { + "line_number": 71, + "changes": [ + { + "start": 24, + "end": 30, + "content": "sha256", + "highlight": "normal" + } + ] + } + } + ], + [ + { + "lhs": { + "line_number": 84, + "changes": [ + { + "start": 24, + "end": 33, + "content": "keccak256", + "highlight": "normal" + } + ] + }, + "rhs": { + "line_number": 84, + "changes": [ + { + "start": 24, + "end": 30, + "content": "sha256", + "highlight": "normal" + } + ] + } + } + ] + ] +} \ No newline at end of file diff --git a/contracts/mutants/ETHRegistrarController/7/BOR/ETHRegistrarController.sol b/contracts/mutants/ETHRegistrarController/7/BOR/ETHRegistrarController.sol new file mode 100644 index 00000000000..6abd15b09b4 --- /dev/null +++ b/contracts/mutants/ETHRegistrarController/7/BOR/ETHRegistrarController.sol @@ -0,0 +1,103 @@ +pragma solidity ^0.5.0; + +import "./PriceOracle.sol"; +import "./BaseRegistrar.sol"; +import "./StringUtils.sol"; +import "openzeppelin-solidity/contracts/ownership/Ownable.sol"; + +/** + * @dev A registrar controller for registering and renewing names at fixed cost. + */ +contract ETHRegistrarController is Ownable { + using StringUtils for *; + + uint constant public MIN_COMMITMENT_AGE = 1 hours; + uint constant public MAX_COMMITMENT_AGE = 48 hours; + uint constant public MIN_REGISTRATION_DURATION = 28 days; + + BaseRegistrar base; + PriceOracle prices; + + mapping(bytes32=>uint) public commitments; + + event NameRegistered(string name, address indexed owner, uint cost, uint expires); + event NameRenewed(string name, uint cost, uint expires); + event NewPriceOracle(address indexed oracle); + + constructor(BaseRegistrar _base, PriceOracle _prices) public { + base = _base; + prices = _prices; + } + + function rentPrice(string memory name, uint duration) view public returns(uint) { + bytes32 hash = keccak256(bytes(name)); + return prices.price(name, base.nameExpires(uint256(hash)), duration); + } + + function valid(string memory name) public view returns(bool) { + return name.strlen() >= 6; + } + + function available(string memory name) public view returns(bool) { + bytes32 label = keccak256(bytes(name)); + return valid(name) || base.available(uint256(label)); + } + // SWC-114-Transaction Order Dependence: L46-L49 + function makeCommitment(string memory name, bytes32 secret) pure public returns(bytes32) { + bytes32 label = keccak256(bytes(name)); + return keccak256(abi.encodePacked(label, secret)); + } + + function commit(bytes32 commitment) public { + require(commitments[commitment] - MAX_COMMITMENT_AGE <= now); + commitments[commitment] = now; + } + // SWC-104-Unchecked Call Return Value: L56-L65 + function register(string calldata name, address owner, uint duration, bytes32 secret) external payable { + // Require a valid commitment + bytes32 commitment = makeCommitment(name, secret); + require(commitments[commitment] - MIN_COMMITMENT_AGE < now); + + // If the commitment is too old, or the name is registered, stop + if(commitments[commitment] - MAX_COMMITMENT_AGE < now || !available(name)) { + msg.sender.transfer(msg.value); + return; + } + delete(commitments[commitment]); + + uint cost = rentPrice(name, duration); + require(duration >= MIN_REGISTRATION_DURATION); + require(msg.value >= cost); + + bytes32 label = keccak256(bytes(name)); + uint expires = base.register(uint256(label), owner, duration); + emit NameRegistered(name, owner, cost, expires); + + if(msg.value > cost) { + msg.sender.transfer(msg.value - cost); + } + } + + function renew(string calldata name, uint duration) external payable { + uint cost = rentPrice(name, duration); + require(msg.value >= cost); + + bytes32 label = keccak256(bytes(name)); + uint expires = base.renew(uint256(label), duration); + + if(msg.value > cost) { + msg.sender.transfer(msg.value - cost); + } + + emit NameRenewed(name, cost, expires); + } + + function setPriceOracle(PriceOracle _prices) public onlyOwner { + prices = _prices; + emit NewPriceOracle(address(prices)); + } + + function withdraw() public onlyOwner { + msg.sender.transfer(address(this).balance); + } +} diff --git a/contracts/mutants/ETHRegistrarController/7/BOR/diff_result_difft.json b/contracts/mutants/ETHRegistrarController/7/BOR/diff_result_difft.json new file mode 100644 index 00000000000..047f4759507 --- /dev/null +++ b/contracts/mutants/ETHRegistrarController/7/BOR/diff_result_difft.json @@ -0,0 +1,158 @@ +{ + "number_of_changes": 7, + "timing": 0.17757844924926758, + "diff_chunks": [ + [ + { + "lhs": { + "line_number": 37, + "changes": [ + { + "start": 29, + "end": 30, + "content": ">", + "highlight": "keyword" + } + ] + }, + "rhs": { + "line_number": 37, + "changes": [ + { + "start": 29, + "end": 31, + "content": ">=", + "highlight": "keyword" + } + ] + } + } + ], + [ + { + "lhs": { + "line_number": 42, + "changes": [ + { + "start": 27, + "end": 29, + "content": "&&", + "highlight": "keyword" + } + ] + }, + "rhs": { + "line_number": 42, + "changes": [ + { + "start": 27, + "end": 29, + "content": "||", + "highlight": "keyword" + } + ] + } + } + ], + [ + { + "lhs": { + "line_number": 51, + "changes": [ + { + "start": 40, + "end": 41, + "content": "+", + "highlight": "keyword" + }, + { + "start": 61, + "end": 62, + "content": "<", + "highlight": "keyword" + } + ] + }, + "rhs": { + "line_number": 51, + "changes": [ + { + "start": 40, + "end": 41, + "content": "-", + "highlight": "keyword" + }, + { + "start": 61, + "end": 63, + "content": "<=", + "highlight": "keyword" + } + ] + } + } + ], + [ + { + "lhs": { + "line_number": 61, + "changes": [ + { + "start": 35, + "end": 36, + "content": "+", + "highlight": "keyword" + } + ] + }, + "rhs": { + "line_number": 61, + "changes": [ + { + "start": 35, + "end": 36, + "content": "-", + "highlight": "keyword" + } + ] + } + }, + { + "lhs": { + "line_number": 58, + "changes": [ + { + "start": 40, + "end": 41, + "content": "+", + "highlight": "keyword" + }, + { + "start": 61, + "end": 63, + "content": "<=", + "highlight": "keyword" + } + ] + }, + "rhs": { + "line_number": 58, + "changes": [ + { + "start": 40, + "end": 41, + "content": "-", + "highlight": "keyword" + }, + { + "start": 62, + "end": 63, + "content": "<", + "highlight": "keyword" + } + ] + } + } + ] + ] +} \ No newline at end of file diff --git a/contracts/mutants/ETHRegistrarController/7/ECS/ETHRegistrarController.sol b/contracts/mutants/ETHRegistrarController/7/ECS/ETHRegistrarController.sol new file mode 100644 index 00000000000..f2beab4d89c --- /dev/null +++ b/contracts/mutants/ETHRegistrarController/7/ECS/ETHRegistrarController.sol @@ -0,0 +1,103 @@ +pragma solidity ^0.5.0; + +import "./PriceOracle.sol"; +import "./BaseRegistrar.sol"; +import "./StringUtils.sol"; +import "openzeppelin-solidity/contracts/ownership/Ownable.sol"; + +/** + * @dev A registrar controller for registering and renewing names at fixed cost. + */ +contract ETHRegistrarController is Ownable { + using StringUtils for *; + + uint constant public MIN_COMMITMENT_AGE = 1 hours; + uint constant public MAX_COMMITMENT_AGE = 48 hours; + uint constant public MIN_REGISTRATION_DURATION = 28 days; + + BaseRegistrar base; + PriceOracle prices; + + mapping(bytes32=>uint) public commitments; + + event NameRegistered(string name, address indexed owner, uint cost, uint expires); + event NameRenewed(string name, uint cost, uint expires); + event NewPriceOracle(address indexed oracle); + + constructor(BaseRegistrar _base, PriceOracle _prices) public { + base = _base; + prices = _prices; + } + + function rentPrice(string memory name, uint duration) view public returns(uint) { + bytes32 hash = keccak256(bytes1(name)); + return prices.price(name, base.nameExpires(uint8(hash)), duration); + } + + function valid(string memory name) public view returns(bool) { + return name.strlen() > 6; + } + + function available(string memory name) public view returns(bool) { + bytes32 label = keccak256(bytes1(name)); + return valid(name) && base.available(uint8(label)); + } + // SWC-114-Transaction Order Dependence: L46-L49 + function makeCommitment(string memory name, bytes32 secret) pure public returns(bytes32) { + bytes32 label = keccak256(bytes1(name)); + return keccak256(abi.encodePacked(label, secret)); + } + + function commit(bytes32 commitment) public { + require(commitments[commitment] + MAX_COMMITMENT_AGE < now); + commitments[commitment] = now; + } + // SWC-104-Unchecked Call Return Value: L56-L65 + function register(string calldata name, address owner, uint duration, bytes32 secret) external payable { + // Require a valid commitment + bytes32 commitment = makeCommitment(name, secret); + require(commitments[commitment] + MIN_COMMITMENT_AGE <= now); + + // If the commitment is too old, or the name is registered, stop + if(commitments[commitment] + MAX_COMMITMENT_AGE < now || !available(name)) { + msg.sender.transfer(msg.value); + return; + } + delete(commitments[commitment]); + + uint cost = rentPrice(name, duration); + require(duration >= MIN_REGISTRATION_DURATION); + require(msg.value >= cost); + + bytes32 label = keccak256(bytes1(name)); + uint expires = base.register(uint8(label), owner, duration); + emit NameRegistered(name, owner, cost, expires); + + if(msg.value > cost) { + msg.sender.transfer(msg.value - cost); + } + } + + function renew(string calldata name, uint duration) external payable { + uint cost = rentPrice(name, duration); + require(msg.value >= cost); + + bytes32 label = keccak256(bytes(name)); + uint expires = base.renew(uint256(label), duration); + + if(msg.value > cost) { + msg.sender.transfer(msg.value - cost); + } + + emit NameRenewed(name, cost, expires); + } + + function setPriceOracle(PriceOracle _prices) public onlyOwner { + prices = _prices; + emit NewPriceOracle(address(prices)); + } + + function withdraw() public onlyOwner { + msg.sender.transfer(address(this).balance); + } +} diff --git a/contracts/mutants/ETHRegistrarController/7/ECS/diff_result_difft.json b/contracts/mutants/ETHRegistrarController/7/ECS/diff_result_difft.json new file mode 100644 index 00000000000..e104a592dae --- /dev/null +++ b/contracts/mutants/ETHRegistrarController/7/ECS/diff_result_difft.json @@ -0,0 +1,180 @@ +{ + "number_of_changes": 7, + "timing": 0.28839731216430664, + "diff_chunks": [ + [ + { + "lhs": { + "line_number": 33, + "changes": [ + { + "start": 51, + "end": 58, + "content": "uint256", + "highlight": "normal" + } + ] + }, + "rhs": { + "line_number": 33, + "changes": [ + { + "start": 51, + "end": 56, + "content": "uint8", + "highlight": "normal" + } + ] + } + }, + { + "lhs": { + "line_number": 32, + "changes": [ + { + "start": 33, + "end": 38, + "content": "bytes", + "highlight": "normal" + } + ] + }, + "rhs": { + "line_number": 32, + "changes": [ + { + "start": 33, + "end": 39, + "content": "bytes1", + "highlight": "normal" + } + ] + } + } + ], + [ + { + "lhs": { + "line_number": 46, + "changes": [ + { + "start": 34, + "end": 39, + "content": "bytes", + "highlight": "normal" + } + ] + }, + "rhs": { + "line_number": 46, + "changes": [ + { + "start": 34, + "end": 40, + "content": "bytes1", + "highlight": "normal" + } + ] + } + }, + { + "lhs": { + "line_number": 41, + "changes": [ + { + "start": 34, + "end": 39, + "content": "bytes", + "highlight": "normal" + } + ] + }, + "rhs": { + "line_number": 41, + "changes": [ + { + "start": 34, + "end": 40, + "content": "bytes1", + "highlight": "normal" + } + ] + } + }, + { + "lhs": { + "line_number": 42, + "changes": [ + { + "start": 45, + "end": 52, + "content": "uint256", + "highlight": "normal" + } + ] + }, + "rhs": { + "line_number": 42, + "changes": [ + { + "start": 45, + "end": 50, + "content": "uint8", + "highlight": "normal" + } + ] + } + } + ], + [ + { + "lhs": { + "line_number": 71, + "changes": [ + { + "start": 34, + "end": 39, + "content": "bytes", + "highlight": "normal" + } + ] + }, + "rhs": { + "line_number": 71, + "changes": [ + { + "start": 34, + "end": 40, + "content": "bytes1", + "highlight": "normal" + } + ] + } + }, + { + "lhs": { + "line_number": 72, + "changes": [ + { + "start": 37, + "end": 44, + "content": "uint256", + "highlight": "normal" + } + ] + }, + "rhs": { + "line_number": 72, + "changes": [ + { + "start": 37, + "end": 42, + "content": "uint8", + "highlight": "normal" + } + ] + } + } + ] + ] +} \ No newline at end of file diff --git a/contracts/mutants/ETHRegistrarController/7/FVR/ETHRegistrarController.sol b/contracts/mutants/ETHRegistrarController/7/FVR/ETHRegistrarController.sol new file mode 100644 index 00000000000..0bab4cd9612 --- /dev/null +++ b/contracts/mutants/ETHRegistrarController/7/FVR/ETHRegistrarController.sol @@ -0,0 +1,103 @@ +pragma solidity ^0.5.0; + +import "./PriceOracle.sol"; +import "./BaseRegistrar.sol"; +import "./StringUtils.sol"; +import "openzeppelin-solidity/contracts/ownership/Ownable.sol"; + +/** + * @dev A registrar controller for registering and renewing names at fixed cost. + */ +contract ETHRegistrarController is Ownable { + using StringUtils for *; + + uint constant public MIN_COMMITMENT_AGE = 1 hours; + uint constant public MAX_COMMITMENT_AGE = 48 hours; + uint constant public MIN_REGISTRATION_DURATION = 28 days; + + BaseRegistrar base; + PriceOracle prices; + + mapping(bytes32=>uint) public commitments; + + event NameRegistered(string name, address indexed owner, uint cost, uint expires); + event NameRenewed(string name, uint cost, uint expires); + event NewPriceOracle(address indexed oracle); + + constructor(BaseRegistrar _base, PriceOracle _prices) internal { + base = _base; + prices = _prices; + } + + function rentPrice(string memory name, uint duration) view external returns(uint) { + bytes32 hash = keccak256(bytes(name)); + return prices.price(name, base.nameExpires(uint256(hash)), duration); + } + + function valid(string memory name) external view returns(bool) { + return name.strlen() > 6; + } + + function available(string memory name) external view returns(bool) { + bytes32 label = keccak256(bytes(name)); + return valid(name) && base.available(uint256(label)); + } + // SWC-114-Transaction Order Dependence: L46-L49 + function makeCommitment(string memory name, bytes32 secret) pure external returns(bytes32) { + bytes32 label = keccak256(bytes(name)); + return keccak256(abi.encodePacked(label, secret)); + } + + function commit(bytes32 commitment) external { + require(commitments[commitment] + MAX_COMMITMENT_AGE < now); + commitments[commitment] = now; + } + // SWC-104-Unchecked Call Return Value: L56-L65 + function register(string calldata name, address owner, uint duration, bytes32 secret) public payable { + // Require a valid commitment + bytes32 commitment = makeCommitment(name, secret); + require(commitments[commitment] + MIN_COMMITMENT_AGE <= now); + + // If the commitment is too old, or the name is registered, stop + if(commitments[commitment] + MAX_COMMITMENT_AGE < now || !available(name)) { + msg.sender.transfer(msg.value); + return; + } + delete(commitments[commitment]); + + uint cost = rentPrice(name, duration); + require(duration >= MIN_REGISTRATION_DURATION); + require(msg.value >= cost); + + bytes32 label = keccak256(bytes(name)); + uint expires = base.register(uint256(label), owner, duration); + emit NameRegistered(name, owner, cost, expires); + + if(msg.value > cost) { + msg.sender.transfer(msg.value - cost); + } + } + + function renew(string calldata name, uint duration) external payable { + uint cost = rentPrice(name, duration); + require(msg.value >= cost); + + bytes32 label = keccak256(bytes(name)); + uint expires = base.renew(uint256(label), duration); + + if(msg.value > cost) { + msg.sender.transfer(msg.value - cost); + } + + emit NameRenewed(name, cost, expires); + } + + function setPriceOracle(PriceOracle _prices) public onlyOwner { + prices = _prices; + emit NewPriceOracle(address(prices)); + } + + function withdraw() public onlyOwner { + msg.sender.transfer(address(this).balance); + } +} diff --git a/contracts/mutants/ETHRegistrarController/7/FVR/diff_result_difft.json b/contracts/mutants/ETHRegistrarController/7/FVR/diff_result_difft.json new file mode 100644 index 00000000000..585286297a8 --- /dev/null +++ b/contracts/mutants/ETHRegistrarController/7/FVR/diff_result_difft.json @@ -0,0 +1,186 @@ +{ + "number_of_changes": 7, + "timing": 0.2483065128326416, + "diff_chunks": [ + [ + { + "lhs": { + "line_number": 26, + "changes": [ + { + "start": 58, + "end": 64, + "content": "public", + "highlight": "keyword" + } + ] + }, + "rhs": { + "line_number": 26, + "changes": [ + { + "start": 58, + "end": 66, + "content": "internal", + "highlight": "keyword" + } + ] + } + } + ], + [ + { + "lhs": { + "line_number": 31, + "changes": [ + { + "start": 63, + "end": 69, + "content": "public", + "highlight": "keyword" + } + ] + }, + "rhs": { + "line_number": 31, + "changes": [ + { + "start": 63, + "end": 71, + "content": "external", + "highlight": "keyword" + } + ] + } + } + ], + [ + { + "lhs": { + "line_number": 40, + "changes": [ + { + "start": 43, + "end": 49, + "content": "public", + "highlight": "keyword" + } + ] + }, + "rhs": { + "line_number": 40, + "changes": [ + { + "start": 43, + "end": 51, + "content": "external", + "highlight": "keyword" + } + ] + } + }, + { + "lhs": { + "line_number": 36, + "changes": [ + { + "start": 39, + "end": 45, + "content": "public", + "highlight": "keyword" + } + ] + }, + "rhs": { + "line_number": 36, + "changes": [ + { + "start": 39, + "end": 47, + "content": "external", + "highlight": "keyword" + } + ] + } + } + ], + [ + { + "lhs": { + "line_number": 45, + "changes": [ + { + "start": 69, + "end": 75, + "content": "public", + "highlight": "keyword" + } + ] + }, + "rhs": { + "line_number": 45, + "changes": [ + { + "start": 69, + "end": 77, + "content": "external", + "highlight": "keyword" + } + ] + } + } + ], + [ + { + "lhs": { + "line_number": 50, + "changes": [ + { + "start": 40, + "end": 46, + "content": "public", + "highlight": "keyword" + } + ] + }, + "rhs": { + "line_number": 50, + "changes": [ + { + "start": 40, + "end": 48, + "content": "external", + "highlight": "keyword" + } + ] + } + } + ], + [ + { + "lhs": { + "line_number": 55, + "changes": [ + { + "start": 90, + "end": 98, + "content": "external", + "highlight": "keyword" + } + ] + }, + "rhs": { + "line_number": 55, + "changes": [ + { + "start": 90, + "end": 96, + "content": "public", + "highlight": "keyword" + } + ] + } + } + ] + ] +} \ No newline at end of file diff --git a/contracts/mutants/ETHRegistrarController/7/GVR/ETHRegistrarController.sol b/contracts/mutants/ETHRegistrarController/7/GVR/ETHRegistrarController.sol new file mode 100644 index 00000000000..5bfe2871b0c --- /dev/null +++ b/contracts/mutants/ETHRegistrarController/7/GVR/ETHRegistrarController.sol @@ -0,0 +1,103 @@ +pragma solidity ^0.5.0; + +import "./PriceOracle.sol"; +import "./BaseRegistrar.sol"; +import "./StringUtils.sol"; +import "openzeppelin-solidity/contracts/ownership/Ownable.sol"; + +/** + * @dev A registrar controller for registering and renewing names at fixed cost. + */ +contract ETHRegistrarController is Ownable { + using StringUtils for *; + + uint constant public MIN_COMMITMENT_AGE = 1 hours; + uint constant public MAX_COMMITMENT_AGE = 48 hours; + uint constant public MIN_REGISTRATION_DURATION = 28 days; + + BaseRegistrar base; + PriceOracle prices; + + mapping(bytes32=>uint) public commitments; + + event NameRegistered(string name, address indexed owner, uint cost, uint expires); + event NameRenewed(string name, uint cost, uint expires); + event NewPriceOracle(address indexed oracle); + + constructor(BaseRegistrar _base, PriceOracle _prices) public { + base = _base; + prices = _prices; + } + + function rentPrice(string memory name, uint duration) view public returns(uint) { + bytes32 hash = keccak256(bytes(name)); + return prices.price(name, base.nameExpires(uint256(hash)), duration); + } + + function valid(string memory name) public view returns(bool) { + return name.strlen() > 6; + } + + function available(string memory name) public view returns(bool) { + bytes32 label = keccak256(bytes(name)); + return valid(name) && base.available(uint256(label)); + } + // SWC-114-Transaction Order Dependence: L46-L49 + function makeCommitment(string memory name, bytes32 secret) pure public returns(bytes32) { + bytes32 label = keccak256(bytes(name)); + return keccak256(abi.encodePacked(label, secret)); + } + + function commit(bytes32 commitment) public { + require(commitments[commitment] + MAX_COMMITMENT_AGE < block.difficulty); + commitments[commitment] = block.difficulty; + } + // SWC-104-Unchecked Call Return Value: L56-L65 + function register(string calldata name, address owner, uint duration, bytes32 secret) external payable { + // Require a valid commitment + bytes32 commitment = makeCommitment(name, secret); + require(commitments[commitment] + MIN_COMMITMENT_AGE <= block.difficulty); + + // If the commitment is too old, or the name is registered, stop + if(commitments[commitment] + MAX_COMMITMENT_AGE < block.difficulty || !available(name)) { + msg.sender.transfer(tx.gasprice); + return; + } + delete(commitments[commitment]); + + uint cost = rentPrice(name, duration); + require(duration >= MIN_REGISTRATION_DURATION); + require(tx.gasprice >= cost); + + bytes32 label = keccak256(bytes(name)); + uint expires = base.register(uint256(label), owner, duration); + emit NameRegistered(name, owner, cost, expires); + + if(tx.gasprice > cost) { + msg.sender.transfer(msg.value - cost); + } + } + + function renew(string calldata name, uint duration) external payable { + uint cost = rentPrice(name, duration); + require(msg.value >= cost); + + bytes32 label = keccak256(bytes(name)); + uint expires = base.renew(uint256(label), duration); + + if(msg.value > cost) { + msg.sender.transfer(msg.value - cost); + } + + emit NameRenewed(name, cost, expires); + } + + function setPriceOracle(PriceOracle _prices) public onlyOwner { + prices = _prices; + emit NewPriceOracle(address(prices)); + } + + function withdraw() public onlyOwner { + msg.sender.transfer(address(this).balance); + } +} diff --git a/contracts/mutants/ETHRegistrarController/7/GVR/diff_result_difft.json b/contracts/mutants/ETHRegistrarController/7/GVR/diff_result_difft.json new file mode 100644 index 00000000000..db3d2d5e9f1 --- /dev/null +++ b/contracts/mutants/ETHRegistrarController/7/GVR/diff_result_difft.json @@ -0,0 +1,266 @@ +{ + "number_of_changes": 18, + "timing": 0.1940479278564453, + "diff_chunks": [ + [ + { + "lhs": { + "line_number": 51, + "changes": [ + { + "start": 63, + "end": 66, + "content": "now", + "highlight": "normal" + } + ] + }, + "rhs": { + "line_number": 51, + "changes": [ + { + "start": 63, + "end": 68, + "content": "block", + "highlight": "normal" + }, + { + "start": 68, + "end": 69, + "content": ".", + "highlight": "normal" + }, + { + "start": 69, + "end": 79, + "content": "difficulty", + "highlight": "normal" + } + ] + } + }, + { + "lhs": { + "line_number": 52, + "changes": [ + { + "start": 34, + "end": 37, + "content": "now", + "highlight": "normal" + } + ] + }, + "rhs": { + "line_number": 52, + "changes": [ + { + "start": 34, + "end": 39, + "content": "block", + "highlight": "normal" + }, + { + "start": 39, + "end": 40, + "content": ".", + "highlight": "normal" + }, + { + "start": 40, + "end": 50, + "content": "difficulty", + "highlight": "normal" + } + ] + } + } + ], + [ + { + "lhs": { + "line_number": 58, + "changes": [ + { + "start": 64, + "end": 67, + "content": "now", + "highlight": "normal" + } + ] + }, + "rhs": { + "line_number": 58, + "changes": [ + { + "start": 64, + "end": 69, + "content": "block", + "highlight": "normal" + }, + { + "start": 69, + "end": 70, + "content": ".", + "highlight": "normal" + }, + { + "start": 70, + "end": 80, + "content": "difficulty", + "highlight": "normal" + } + ] + } + }, + { + "lhs": { + "line_number": 62, + "changes": [ + { + "start": 32, + "end": 35, + "content": "msg", + "highlight": "normal" + }, + { + "start": 36, + "end": 41, + "content": "value", + "highlight": "normal" + } + ] + }, + "rhs": { + "line_number": 62, + "changes": [ + { + "start": 32, + "end": 34, + "content": "tx", + "highlight": "normal" + }, + { + "start": 35, + "end": 43, + "content": "gasprice", + "highlight": "normal" + } + ] + } + }, + { + "lhs": { + "line_number": 61, + "changes": [ + { + "start": 58, + "end": 61, + "content": "now", + "highlight": "normal" + } + ] + }, + "rhs": { + "line_number": 61, + "changes": [ + { + "start": 58, + "end": 63, + "content": "block", + "highlight": "normal" + }, + { + "start": 63, + "end": 64, + "content": ".", + "highlight": "normal" + }, + { + "start": 64, + "end": 74, + "content": "difficulty", + "highlight": "normal" + } + ] + } + } + ], + [ + { + "lhs": { + "line_number": 69, + "changes": [ + { + "start": 16, + "end": 19, + "content": "msg", + "highlight": "normal" + }, + { + "start": 20, + "end": 25, + "content": "value", + "highlight": "normal" + } + ] + }, + "rhs": { + "line_number": 69, + "changes": [ + { + "start": 16, + "end": 18, + "content": "tx", + "highlight": "normal" + }, + { + "start": 19, + "end": 27, + "content": "gasprice", + "highlight": "normal" + } + ] + } + } + ], + [ + { + "lhs": { + "line_number": 75, + "changes": [ + { + "start": 11, + "end": 14, + "content": "msg", + "highlight": "normal" + }, + { + "start": 15, + "end": 20, + "content": "value", + "highlight": "normal" + } + ] + }, + "rhs": { + "line_number": 75, + "changes": [ + { + "start": 11, + "end": 13, + "content": "tx", + "highlight": "normal" + }, + { + "start": 14, + "end": 22, + "content": "gasprice", + "highlight": "normal" + } + ] + } + } + ] + ] +} \ No newline at end of file diff --git a/contracts/mutants/ETHRegistrarController/8/BOR/ETHRegistrarController.sol b/contracts/mutants/ETHRegistrarController/8/BOR/ETHRegistrarController.sol new file mode 100644 index 00000000000..54814bd9874 --- /dev/null +++ b/contracts/mutants/ETHRegistrarController/8/BOR/ETHRegistrarController.sol @@ -0,0 +1,103 @@ +pragma solidity ^0.5.0; + +import "./PriceOracle.sol"; +import "./BaseRegistrar.sol"; +import "./StringUtils.sol"; +import "openzeppelin-solidity/contracts/ownership/Ownable.sol"; + +/** + * @dev A registrar controller for registering and renewing names at fixed cost. + */ +contract ETHRegistrarController is Ownable { + using StringUtils for *; + + uint constant public MIN_COMMITMENT_AGE = 1 hours; + uint constant public MAX_COMMITMENT_AGE = 48 hours; + uint constant public MIN_REGISTRATION_DURATION = 28 days; + + BaseRegistrar base; + PriceOracle prices; + + mapping(bytes32=>uint) public commitments; + + event NameRegistered(string name, address indexed owner, uint cost, uint expires); + event NameRenewed(string name, uint cost, uint expires); + event NewPriceOracle(address indexed oracle); + + constructor(BaseRegistrar _base, PriceOracle _prices) public { + base = _base; + prices = _prices; + } + + function rentPrice(string memory name, uint duration) view public returns(uint) { + bytes32 hash = keccak256(bytes(name)); + return prices.price(name, base.nameExpires(uint256(hash)), duration); + } + + function valid(string memory name) public view returns(bool) { + return name.strlen() >= 6; + } + + function available(string memory name) public view returns(bool) { + bytes32 label = keccak256(bytes(name)); + return valid(name) || base.available(uint256(label)); + } + // SWC-114-Transaction Order Dependence: L46-L49 + function makeCommitment(string memory name, bytes32 secret) pure public returns(bytes32) { + bytes32 label = keccak256(bytes(name)); + return keccak256(abi.encodePacked(label, secret)); + } + + function commit(bytes32 commitment) public { + require(commitments[commitment] - MAX_COMMITMENT_AGE <= now); + commitments[commitment] = now; + } + // SWC-104-Unchecked Call Return Value: L56-L65 + function register(string calldata name, address owner, uint duration, bytes32 secret) external payable { + // Require a valid commitment + bytes32 commitment = makeCommitment(name, secret); + require(commitments[commitment] - MIN_COMMITMENT_AGE < now); + + // If the commitment is too old, or the name is registered, stop + if(commitments[commitment] - MAX_COMMITMENT_AGE <= now || !available(name)) { + msg.sender.transfer(msg.value); + return; + } + delete(commitments[commitment]); + + uint cost = rentPrice(name, duration); + require(duration >= MIN_REGISTRATION_DURATION); + require(msg.value >= cost); + + bytes32 label = keccak256(bytes(name)); + uint expires = base.register(uint256(label), owner, duration); + emit NameRegistered(name, owner, cost, expires); + + if(msg.value > cost) { + msg.sender.transfer(msg.value - cost); + } + } + + function renew(string calldata name, uint duration) external payable { + uint cost = rentPrice(name, duration); + require(msg.value >= cost); + + bytes32 label = keccak256(bytes(name)); + uint expires = base.renew(uint256(label), duration); + + if(msg.value > cost) { + msg.sender.transfer(msg.value - cost); + } + + emit NameRenewed(name, cost, expires); + } + + function setPriceOracle(PriceOracle _prices) public onlyOwner { + prices = _prices; + emit NewPriceOracle(address(prices)); + } + + function withdraw() public onlyOwner { + msg.sender.transfer(address(this).balance); + } +} diff --git a/contracts/mutants/ETHRegistrarController/8/BOR/diff_result_difft.json b/contracts/mutants/ETHRegistrarController/8/BOR/diff_result_difft.json new file mode 100644 index 00000000000..257434c0806 --- /dev/null +++ b/contracts/mutants/ETHRegistrarController/8/BOR/diff_result_difft.json @@ -0,0 +1,170 @@ +{ + "number_of_changes": 8, + "timing": 0.12322854995727539, + "diff_chunks": [ + [ + { + "lhs": { + "line_number": 37, + "changes": [ + { + "start": 29, + "end": 30, + "content": ">", + "highlight": "keyword" + } + ] + }, + "rhs": { + "line_number": 37, + "changes": [ + { + "start": 29, + "end": 31, + "content": ">=", + "highlight": "keyword" + } + ] + } + } + ], + [ + { + "lhs": { + "line_number": 42, + "changes": [ + { + "start": 27, + "end": 29, + "content": "&&", + "highlight": "keyword" + } + ] + }, + "rhs": { + "line_number": 42, + "changes": [ + { + "start": 27, + "end": 29, + "content": "||", + "highlight": "keyword" + } + ] + } + } + ], + [ + { + "lhs": { + "line_number": 51, + "changes": [ + { + "start": 40, + "end": 41, + "content": "+", + "highlight": "keyword" + }, + { + "start": 61, + "end": 62, + "content": "<", + "highlight": "keyword" + } + ] + }, + "rhs": { + "line_number": 51, + "changes": [ + { + "start": 40, + "end": 41, + "content": "-", + "highlight": "keyword" + }, + { + "start": 61, + "end": 63, + "content": "<=", + "highlight": "keyword" + } + ] + } + } + ], + [ + { + "lhs": { + "line_number": 58, + "changes": [ + { + "start": 40, + "end": 41, + "content": "+", + "highlight": "keyword" + }, + { + "start": 61, + "end": 63, + "content": "<=", + "highlight": "keyword" + } + ] + }, + "rhs": { + "line_number": 58, + "changes": [ + { + "start": 40, + "end": 41, + "content": "-", + "highlight": "keyword" + }, + { + "start": 62, + "end": 63, + "content": "<", + "highlight": "keyword" + } + ] + } + }, + { + "lhs": { + "line_number": 61, + "changes": [ + { + "start": 35, + "end": 36, + "content": "+", + "highlight": "keyword" + }, + { + "start": 56, + "end": 57, + "content": "<", + "highlight": "keyword" + } + ] + }, + "rhs": { + "line_number": 61, + "changes": [ + { + "start": 35, + "end": 36, + "content": "-", + "highlight": "keyword" + }, + { + "start": 56, + "end": 58, + "content": "<=", + "highlight": "keyword" + } + ] + } + } + ] + ] +} \ No newline at end of file diff --git a/contracts/mutants/ETHRegistrarController/8/ECS/ETHRegistrarController.sol b/contracts/mutants/ETHRegistrarController/8/ECS/ETHRegistrarController.sol new file mode 100644 index 00000000000..b4f62985107 --- /dev/null +++ b/contracts/mutants/ETHRegistrarController/8/ECS/ETHRegistrarController.sol @@ -0,0 +1,103 @@ +pragma solidity ^0.5.0; + +import "./PriceOracle.sol"; +import "./BaseRegistrar.sol"; +import "./StringUtils.sol"; +import "openzeppelin-solidity/contracts/ownership/Ownable.sol"; + +/** + * @dev A registrar controller for registering and renewing names at fixed cost. + */ +contract ETHRegistrarController is Ownable { + using StringUtils for *; + + uint constant public MIN_COMMITMENT_AGE = 1 hours; + uint constant public MAX_COMMITMENT_AGE = 48 hours; + uint constant public MIN_REGISTRATION_DURATION = 28 days; + + BaseRegistrar base; + PriceOracle prices; + + mapping(bytes32=>uint) public commitments; + + event NameRegistered(string name, address indexed owner, uint cost, uint expires); + event NameRenewed(string name, uint cost, uint expires); + event NewPriceOracle(address indexed oracle); + + constructor(BaseRegistrar _base, PriceOracle _prices) public { + base = _base; + prices = _prices; + } + + function rentPrice(string memory name, uint duration) view public returns(uint) { + bytes32 hash = keccak256(bytes1(name)); + return prices.price(name, base.nameExpires(uint8(hash)), duration); + } + + function valid(string memory name) public view returns(bool) { + return name.strlen() > 6; + } + + function available(string memory name) public view returns(bool) { + bytes32 label = keccak256(bytes1(name)); + return valid(name) && base.available(uint8(label)); + } + // SWC-114-Transaction Order Dependence: L46-L49 + function makeCommitment(string memory name, bytes32 secret) pure public returns(bytes32) { + bytes32 label = keccak256(bytes1(name)); + return keccak256(abi.encodePacked(label, secret)); + } + + function commit(bytes32 commitment) public { + require(commitments[commitment] + MAX_COMMITMENT_AGE < now); + commitments[commitment] = now; + } + // SWC-104-Unchecked Call Return Value: L56-L65 + function register(string calldata name, address owner, uint duration, bytes32 secret) external payable { + // Require a valid commitment + bytes32 commitment = makeCommitment(name, secret); + require(commitments[commitment] + MIN_COMMITMENT_AGE <= now); + + // If the commitment is too old, or the name is registered, stop + if(commitments[commitment] + MAX_COMMITMENT_AGE < now || !available(name)) { + msg.sender.transfer(msg.value); + return; + } + delete(commitments[commitment]); + + uint cost = rentPrice(name, duration); + require(duration >= MIN_REGISTRATION_DURATION); + require(msg.value >= cost); + + bytes32 label = keccak256(bytes1(name)); + uint expires = base.register(uint8(label), owner, duration); + emit NameRegistered(name, owner, cost, expires); + + if(msg.value > cost) { + msg.sender.transfer(msg.value - cost); + } + } + + function renew(string calldata name, uint duration) external payable { + uint cost = rentPrice(name, duration); + require(msg.value >= cost); + + bytes32 label = keccak256(bytes1(name)); + uint expires = base.renew(uint256(label), duration); + + if(msg.value > cost) { + msg.sender.transfer(msg.value - cost); + } + + emit NameRenewed(name, cost, expires); + } + + function setPriceOracle(PriceOracle _prices) public onlyOwner { + prices = _prices; + emit NewPriceOracle(address(prices)); + } + + function withdraw() public onlyOwner { + msg.sender.transfer(address(this).balance); + } +} diff --git a/contracts/mutants/ETHRegistrarController/8/ECS/diff_result_difft.json b/contracts/mutants/ETHRegistrarController/8/ECS/diff_result_difft.json new file mode 100644 index 00000000000..ff005637795 --- /dev/null +++ b/contracts/mutants/ETHRegistrarController/8/ECS/diff_result_difft.json @@ -0,0 +1,206 @@ +{ + "number_of_changes": 8, + "timing": 0.24233317375183105, + "diff_chunks": [ + [ + { + "lhs": { + "line_number": 32, + "changes": [ + { + "start": 33, + "end": 38, + "content": "bytes", + "highlight": "normal" + } + ] + }, + "rhs": { + "line_number": 32, + "changes": [ + { + "start": 33, + "end": 39, + "content": "bytes1", + "highlight": "normal" + } + ] + } + }, + { + "lhs": { + "line_number": 33, + "changes": [ + { + "start": 51, + "end": 58, + "content": "uint256", + "highlight": "normal" + } + ] + }, + "rhs": { + "line_number": 33, + "changes": [ + { + "start": 51, + "end": 56, + "content": "uint8", + "highlight": "normal" + } + ] + } + } + ], + [ + { + "lhs": { + "line_number": 42, + "changes": [ + { + "start": 45, + "end": 52, + "content": "uint256", + "highlight": "normal" + } + ] + }, + "rhs": { + "line_number": 42, + "changes": [ + { + "start": 45, + "end": 50, + "content": "uint8", + "highlight": "normal" + } + ] + } + }, + { + "lhs": { + "line_number": 41, + "changes": [ + { + "start": 34, + "end": 39, + "content": "bytes", + "highlight": "normal" + } + ] + }, + "rhs": { + "line_number": 41, + "changes": [ + { + "start": 34, + "end": 40, + "content": "bytes1", + "highlight": "normal" + } + ] + } + }, + { + "lhs": { + "line_number": 46, + "changes": [ + { + "start": 34, + "end": 39, + "content": "bytes", + "highlight": "normal" + } + ] + }, + "rhs": { + "line_number": 46, + "changes": [ + { + "start": 34, + "end": 40, + "content": "bytes1", + "highlight": "normal" + } + ] + } + } + ], + [ + { + "lhs": { + "line_number": 71, + "changes": [ + { + "start": 34, + "end": 39, + "content": "bytes", + "highlight": "normal" + } + ] + }, + "rhs": { + "line_number": 71, + "changes": [ + { + "start": 34, + "end": 40, + "content": "bytes1", + "highlight": "normal" + } + ] + } + }, + { + "lhs": { + "line_number": 72, + "changes": [ + { + "start": 37, + "end": 44, + "content": "uint256", + "highlight": "normal" + } + ] + }, + "rhs": { + "line_number": 72, + "changes": [ + { + "start": 37, + "end": 42, + "content": "uint8", + "highlight": "normal" + } + ] + } + } + ], + [ + { + "lhs": { + "line_number": 84, + "changes": [ + { + "start": 34, + "end": 39, + "content": "bytes", + "highlight": "normal" + } + ] + }, + "rhs": { + "line_number": 84, + "changes": [ + { + "start": 34, + "end": 40, + "content": "bytes1", + "highlight": "normal" + } + ] + } + } + ] + ] +} \ No newline at end of file diff --git a/contracts/mutants/ETHRegistrarController/8/FVR/ETHRegistrarController.sol b/contracts/mutants/ETHRegistrarController/8/FVR/ETHRegistrarController.sol new file mode 100644 index 00000000000..7a95bcb02b8 --- /dev/null +++ b/contracts/mutants/ETHRegistrarController/8/FVR/ETHRegistrarController.sol @@ -0,0 +1,103 @@ +pragma solidity ^0.5.0; + +import "./PriceOracle.sol"; +import "./BaseRegistrar.sol"; +import "./StringUtils.sol"; +import "openzeppelin-solidity/contracts/ownership/Ownable.sol"; + +/** + * @dev A registrar controller for registering and renewing names at fixed cost. + */ +contract ETHRegistrarController is Ownable { + using StringUtils for *; + + uint constant public MIN_COMMITMENT_AGE = 1 hours; + uint constant public MAX_COMMITMENT_AGE = 48 hours; + uint constant public MIN_REGISTRATION_DURATION = 28 days; + + BaseRegistrar base; + PriceOracle prices; + + mapping(bytes32=>uint) public commitments; + + event NameRegistered(string name, address indexed owner, uint cost, uint expires); + event NameRenewed(string name, uint cost, uint expires); + event NewPriceOracle(address indexed oracle); + + constructor(BaseRegistrar _base, PriceOracle _prices) internal { + base = _base; + prices = _prices; + } + + function rentPrice(string memory name, uint duration) view external returns(uint) { + bytes32 hash = keccak256(bytes(name)); + return prices.price(name, base.nameExpires(uint256(hash)), duration); + } + + function valid(string memory name) external view returns(bool) { + return name.strlen() > 6; + } + + function available(string memory name) external view returns(bool) { + bytes32 label = keccak256(bytes(name)); + return valid(name) && base.available(uint256(label)); + } + // SWC-114-Transaction Order Dependence: L46-L49 + function makeCommitment(string memory name, bytes32 secret) pure external returns(bytes32) { + bytes32 label = keccak256(bytes(name)); + return keccak256(abi.encodePacked(label, secret)); + } + + function commit(bytes32 commitment) external { + require(commitments[commitment] + MAX_COMMITMENT_AGE < now); + commitments[commitment] = now; + } + // SWC-104-Unchecked Call Return Value: L56-L65 + function register(string calldata name, address owner, uint duration, bytes32 secret) public payable { + // Require a valid commitment + bytes32 commitment = makeCommitment(name, secret); + require(commitments[commitment] + MIN_COMMITMENT_AGE <= now); + + // If the commitment is too old, or the name is registered, stop + if(commitments[commitment] + MAX_COMMITMENT_AGE < now || !available(name)) { + msg.sender.transfer(msg.value); + return; + } + delete(commitments[commitment]); + + uint cost = rentPrice(name, duration); + require(duration >= MIN_REGISTRATION_DURATION); + require(msg.value >= cost); + + bytes32 label = keccak256(bytes(name)); + uint expires = base.register(uint256(label), owner, duration); + emit NameRegistered(name, owner, cost, expires); + + if(msg.value > cost) { + msg.sender.transfer(msg.value - cost); + } + } + + function renew(string calldata name, uint duration) public payable { + uint cost = rentPrice(name, duration); + require(msg.value >= cost); + + bytes32 label = keccak256(bytes(name)); + uint expires = base.renew(uint256(label), duration); + + if(msg.value > cost) { + msg.sender.transfer(msg.value - cost); + } + + emit NameRenewed(name, cost, expires); + } + + function setPriceOracle(PriceOracle _prices) public onlyOwner { + prices = _prices; + emit NewPriceOracle(address(prices)); + } + + function withdraw() public onlyOwner { + msg.sender.transfer(address(this).balance); + } +} diff --git a/contracts/mutants/ETHRegistrarController/8/FVR/diff_result_difft.json b/contracts/mutants/ETHRegistrarController/8/FVR/diff_result_difft.json new file mode 100644 index 00000000000..f9ddc094325 --- /dev/null +++ b/contracts/mutants/ETHRegistrarController/8/FVR/diff_result_difft.json @@ -0,0 +1,212 @@ +{ + "number_of_changes": 8, + "timing": 0.31466221809387207, + "diff_chunks": [ + [ + { + "lhs": { + "line_number": 26, + "changes": [ + { + "start": 58, + "end": 64, + "content": "public", + "highlight": "keyword" + } + ] + }, + "rhs": { + "line_number": 26, + "changes": [ + { + "start": 58, + "end": 66, + "content": "internal", + "highlight": "keyword" + } + ] + } + } + ], + [ + { + "lhs": { + "line_number": 31, + "changes": [ + { + "start": 63, + "end": 69, + "content": "public", + "highlight": "keyword" + } + ] + }, + "rhs": { + "line_number": 31, + "changes": [ + { + "start": 63, + "end": 71, + "content": "external", + "highlight": "keyword" + } + ] + } + } + ], + [ + { + "lhs": { + "line_number": 36, + "changes": [ + { + "start": 39, + "end": 45, + "content": "public", + "highlight": "keyword" + } + ] + }, + "rhs": { + "line_number": 36, + "changes": [ + { + "start": 39, + "end": 47, + "content": "external", + "highlight": "keyword" + } + ] + } + }, + { + "lhs": { + "line_number": 40, + "changes": [ + { + "start": 43, + "end": 49, + "content": "public", + "highlight": "keyword" + } + ] + }, + "rhs": { + "line_number": 40, + "changes": [ + { + "start": 43, + "end": 51, + "content": "external", + "highlight": "keyword" + } + ] + } + } + ], + [ + { + "lhs": { + "line_number": 45, + "changes": [ + { + "start": 69, + "end": 75, + "content": "public", + "highlight": "keyword" + } + ] + }, + "rhs": { + "line_number": 45, + "changes": [ + { + "start": 69, + "end": 77, + "content": "external", + "highlight": "keyword" + } + ] + } + } + ], + [ + { + "lhs": { + "line_number": 50, + "changes": [ + { + "start": 40, + "end": 46, + "content": "public", + "highlight": "keyword" + } + ] + }, + "rhs": { + "line_number": 50, + "changes": [ + { + "start": 40, + "end": 48, + "content": "external", + "highlight": "keyword" + } + ] + } + } + ], + [ + { + "lhs": { + "line_number": 55, + "changes": [ + { + "start": 90, + "end": 98, + "content": "external", + "highlight": "keyword" + } + ] + }, + "rhs": { + "line_number": 55, + "changes": [ + { + "start": 90, + "end": 96, + "content": "public", + "highlight": "keyword" + } + ] + } + } + ], + [ + { + "lhs": { + "line_number": 80, + "changes": [ + { + "start": 56, + "end": 64, + "content": "external", + "highlight": "keyword" + } + ] + }, + "rhs": { + "line_number": 80, + "changes": [ + { + "start": 56, + "end": 62, + "content": "public", + "highlight": "keyword" + } + ] + } + } + ] + ] +} \ No newline at end of file diff --git a/contracts/mutants/ETHRegistrarController/8/GVR/ETHRegistrarController.sol b/contracts/mutants/ETHRegistrarController/8/GVR/ETHRegistrarController.sol new file mode 100644 index 00000000000..61a19ef7973 --- /dev/null +++ b/contracts/mutants/ETHRegistrarController/8/GVR/ETHRegistrarController.sol @@ -0,0 +1,103 @@ +pragma solidity ^0.5.0; + +import "./PriceOracle.sol"; +import "./BaseRegistrar.sol"; +import "./StringUtils.sol"; +import "openzeppelin-solidity/contracts/ownership/Ownable.sol"; + +/** + * @dev A registrar controller for registering and renewing names at fixed cost. + */ +contract ETHRegistrarController is Ownable { + using StringUtils for *; + + uint constant public MIN_COMMITMENT_AGE = 1 hours; + uint constant public MAX_COMMITMENT_AGE = 48 hours; + uint constant public MIN_REGISTRATION_DURATION = 28 days; + + BaseRegistrar base; + PriceOracle prices; + + mapping(bytes32=>uint) public commitments; + + event NameRegistered(string name, address indexed owner, uint cost, uint expires); + event NameRenewed(string name, uint cost, uint expires); + event NewPriceOracle(address indexed oracle); + + constructor(BaseRegistrar _base, PriceOracle _prices) public { + base = _base; + prices = _prices; + } + + function rentPrice(string memory name, uint duration) view public returns(uint) { + bytes32 hash = keccak256(bytes(name)); + return prices.price(name, base.nameExpires(uint256(hash)), duration); + } + + function valid(string memory name) public view returns(bool) { + return name.strlen() > 6; + } + + function available(string memory name) public view returns(bool) { + bytes32 label = keccak256(bytes(name)); + return valid(name) && base.available(uint256(label)); + } + // SWC-114-Transaction Order Dependence: L46-L49 + function makeCommitment(string memory name, bytes32 secret) pure public returns(bytes32) { + bytes32 label = keccak256(bytes(name)); + return keccak256(abi.encodePacked(label, secret)); + } + + function commit(bytes32 commitment) public { + require(commitments[commitment] + MAX_COMMITMENT_AGE < block.difficulty); + commitments[commitment] = block.difficulty; + } + // SWC-104-Unchecked Call Return Value: L56-L65 + function register(string calldata name, address owner, uint duration, bytes32 secret) external payable { + // Require a valid commitment + bytes32 commitment = makeCommitment(name, secret); + require(commitments[commitment] + MIN_COMMITMENT_AGE <= block.difficulty); + + // If the commitment is too old, or the name is registered, stop + if(commitments[commitment] + MAX_COMMITMENT_AGE < block.difficulty || !available(name)) { + msg.sender.transfer(tx.gasprice); + return; + } + delete(commitments[commitment]); + + uint cost = rentPrice(name, duration); + require(duration >= MIN_REGISTRATION_DURATION); + require(tx.gasprice >= cost); + + bytes32 label = keccak256(bytes(name)); + uint expires = base.register(uint256(label), owner, duration); + emit NameRegistered(name, owner, cost, expires); + + if(tx.gasprice > cost) { + msg.sender.transfer(tx.gasprice - cost); + } + } + + function renew(string calldata name, uint duration) external payable { + uint cost = rentPrice(name, duration); + require(msg.value >= cost); + + bytes32 label = keccak256(bytes(name)); + uint expires = base.renew(uint256(label), duration); + + if(msg.value > cost) { + msg.sender.transfer(msg.value - cost); + } + + emit NameRenewed(name, cost, expires); + } + + function setPriceOracle(PriceOracle _prices) public onlyOwner { + prices = _prices; + emit NewPriceOracle(address(prices)); + } + + function withdraw() public onlyOwner { + msg.sender.transfer(address(this).balance); + } +} diff --git a/contracts/mutants/ETHRegistrarController/8/GVR/diff_result_difft.json b/contracts/mutants/ETHRegistrarController/8/GVR/diff_result_difft.json new file mode 100644 index 00000000000..b2a5bd26818 --- /dev/null +++ b/contracts/mutants/ETHRegistrarController/8/GVR/diff_result_difft.json @@ -0,0 +1,302 @@ +{ + "number_of_changes": 20, + "timing": 0.1747293472290039, + "diff_chunks": [ + [ + { + "lhs": { + "line_number": 51, + "changes": [ + { + "start": 63, + "end": 66, + "content": "now", + "highlight": "normal" + } + ] + }, + "rhs": { + "line_number": 51, + "changes": [ + { + "start": 63, + "end": 68, + "content": "block", + "highlight": "normal" + }, + { + "start": 68, + "end": 69, + "content": ".", + "highlight": "normal" + }, + { + "start": 69, + "end": 79, + "content": "difficulty", + "highlight": "normal" + } + ] + } + }, + { + "lhs": { + "line_number": 52, + "changes": [ + { + "start": 34, + "end": 37, + "content": "now", + "highlight": "normal" + } + ] + }, + "rhs": { + "line_number": 52, + "changes": [ + { + "start": 34, + "end": 39, + "content": "block", + "highlight": "normal" + }, + { + "start": 39, + "end": 40, + "content": ".", + "highlight": "normal" + }, + { + "start": 40, + "end": 50, + "content": "difficulty", + "highlight": "normal" + } + ] + } + } + ], + [ + { + "lhs": { + "line_number": 58, + "changes": [ + { + "start": 64, + "end": 67, + "content": "now", + "highlight": "normal" + } + ] + }, + "rhs": { + "line_number": 58, + "changes": [ + { + "start": 64, + "end": 69, + "content": "block", + "highlight": "normal" + }, + { + "start": 69, + "end": 70, + "content": ".", + "highlight": "normal" + }, + { + "start": 70, + "end": 80, + "content": "difficulty", + "highlight": "normal" + } + ] + } + }, + { + "lhs": { + "line_number": 62, + "changes": [ + { + "start": 32, + "end": 35, + "content": "msg", + "highlight": "normal" + }, + { + "start": 36, + "end": 41, + "content": "value", + "highlight": "normal" + } + ] + }, + "rhs": { + "line_number": 62, + "changes": [ + { + "start": 32, + "end": 34, + "content": "tx", + "highlight": "normal" + }, + { + "start": 35, + "end": 43, + "content": "gasprice", + "highlight": "normal" + } + ] + } + }, + { + "lhs": { + "line_number": 61, + "changes": [ + { + "start": 58, + "end": 61, + "content": "now", + "highlight": "normal" + } + ] + }, + "rhs": { + "line_number": 61, + "changes": [ + { + "start": 58, + "end": 63, + "content": "block", + "highlight": "normal" + }, + { + "start": 63, + "end": 64, + "content": ".", + "highlight": "normal" + }, + { + "start": 64, + "end": 74, + "content": "difficulty", + "highlight": "normal" + } + ] + } + } + ], + [ + { + "lhs": { + "line_number": 69, + "changes": [ + { + "start": 16, + "end": 19, + "content": "msg", + "highlight": "normal" + }, + { + "start": 20, + "end": 25, + "content": "value", + "highlight": "normal" + } + ] + }, + "rhs": { + "line_number": 69, + "changes": [ + { + "start": 16, + "end": 18, + "content": "tx", + "highlight": "normal" + }, + { + "start": 19, + "end": 27, + "content": "gasprice", + "highlight": "normal" + } + ] + } + } + ], + [ + { + "lhs": { + "line_number": 76, + "changes": [ + { + "start": 32, + "end": 35, + "content": "msg", + "highlight": "normal" + }, + { + "start": 36, + "end": 41, + "content": "value", + "highlight": "normal" + } + ] + }, + "rhs": { + "line_number": 76, + "changes": [ + { + "start": 32, + "end": 34, + "content": "tx", + "highlight": "normal" + }, + { + "start": 35, + "end": 43, + "content": "gasprice", + "highlight": "normal" + } + ] + } + }, + { + "lhs": { + "line_number": 75, + "changes": [ + { + "start": 11, + "end": 14, + "content": "msg", + "highlight": "normal" + }, + { + "start": 15, + "end": 20, + "content": "value", + "highlight": "normal" + } + ] + }, + "rhs": { + "line_number": 75, + "changes": [ + { + "start": 11, + "end": 13, + "content": "tx", + "highlight": "normal" + }, + { + "start": 14, + "end": 22, + "content": "gasprice", + "highlight": "normal" + } + ] + } + } + ] + ] +} \ No newline at end of file diff --git a/contracts/mutants/ETHRegistrarController/9/BOR/ETHRegistrarController.sol b/contracts/mutants/ETHRegistrarController/9/BOR/ETHRegistrarController.sol new file mode 100644 index 00000000000..10fea208349 --- /dev/null +++ b/contracts/mutants/ETHRegistrarController/9/BOR/ETHRegistrarController.sol @@ -0,0 +1,103 @@ +pragma solidity ^0.5.0; + +import "./PriceOracle.sol"; +import "./BaseRegistrar.sol"; +import "./StringUtils.sol"; +import "openzeppelin-solidity/contracts/ownership/Ownable.sol"; + +/** + * @dev A registrar controller for registering and renewing names at fixed cost. + */ +contract ETHRegistrarController is Ownable { + using StringUtils for *; + + uint constant public MIN_COMMITMENT_AGE = 1 hours; + uint constant public MAX_COMMITMENT_AGE = 48 hours; + uint constant public MIN_REGISTRATION_DURATION = 28 days; + + BaseRegistrar base; + PriceOracle prices; + + mapping(bytes32=>uint) public commitments; + + event NameRegistered(string name, address indexed owner, uint cost, uint expires); + event NameRenewed(string name, uint cost, uint expires); + event NewPriceOracle(address indexed oracle); + + constructor(BaseRegistrar _base, PriceOracle _prices) public { + base = _base; + prices = _prices; + } + + function rentPrice(string memory name, uint duration) view public returns(uint) { + bytes32 hash = keccak256(bytes(name)); + return prices.price(name, base.nameExpires(uint256(hash)), duration); + } + + function valid(string memory name) public view returns(bool) { + return name.strlen() >= 6; + } + + function available(string memory name) public view returns(bool) { + bytes32 label = keccak256(bytes(name)); + return valid(name) || base.available(uint256(label)); + } + // SWC-114-Transaction Order Dependence: L46-L49 + function makeCommitment(string memory name, bytes32 secret) pure public returns(bytes32) { + bytes32 label = keccak256(bytes(name)); + return keccak256(abi.encodePacked(label, secret)); + } + + function commit(bytes32 commitment) public { + require(commitments[commitment] - MAX_COMMITMENT_AGE <= now); + commitments[commitment] = now; + } + // SWC-104-Unchecked Call Return Value: L56-L65 + function register(string calldata name, address owner, uint duration, bytes32 secret) external payable { + // Require a valid commitment + bytes32 commitment = makeCommitment(name, secret); + require(commitments[commitment] - MIN_COMMITMENT_AGE < now); + + // If the commitment is too old, or the name is registered, stop + if(commitments[commitment] - MAX_COMMITMENT_AGE <= now && !available(name)) { + msg.sender.transfer(msg.value); + return; + } + delete(commitments[commitment]); + + uint cost = rentPrice(name, duration); + require(duration >= MIN_REGISTRATION_DURATION); + require(msg.value >= cost); + + bytes32 label = keccak256(bytes(name)); + uint expires = base.register(uint256(label), owner, duration); + emit NameRegistered(name, owner, cost, expires); + + if(msg.value > cost) { + msg.sender.transfer(msg.value - cost); + } + } + + function renew(string calldata name, uint duration) external payable { + uint cost = rentPrice(name, duration); + require(msg.value >= cost); + + bytes32 label = keccak256(bytes(name)); + uint expires = base.renew(uint256(label), duration); + + if(msg.value > cost) { + msg.sender.transfer(msg.value - cost); + } + + emit NameRenewed(name, cost, expires); + } + + function setPriceOracle(PriceOracle _prices) public onlyOwner { + prices = _prices; + emit NewPriceOracle(address(prices)); + } + + function withdraw() public onlyOwner { + msg.sender.transfer(address(this).balance); + } +} diff --git a/contracts/mutants/ETHRegistrarController/9/BOR/diff_result_difft.json b/contracts/mutants/ETHRegistrarController/9/BOR/diff_result_difft.json new file mode 100644 index 00000000000..5577aa2559f --- /dev/null +++ b/contracts/mutants/ETHRegistrarController/9/BOR/diff_result_difft.json @@ -0,0 +1,182 @@ +{ + "number_of_changes": 9, + "timing": 0.22478175163269043, + "diff_chunks": [ + [ + { + "lhs": { + "line_number": 37, + "changes": [ + { + "start": 29, + "end": 30, + "content": ">", + "highlight": "keyword" + } + ] + }, + "rhs": { + "line_number": 37, + "changes": [ + { + "start": 29, + "end": 31, + "content": ">=", + "highlight": "keyword" + } + ] + } + } + ], + [ + { + "lhs": { + "line_number": 42, + "changes": [ + { + "start": 27, + "end": 29, + "content": "&&", + "highlight": "keyword" + } + ] + }, + "rhs": { + "line_number": 42, + "changes": [ + { + "start": 27, + "end": 29, + "content": "||", + "highlight": "keyword" + } + ] + } + } + ], + [ + { + "lhs": { + "line_number": 51, + "changes": [ + { + "start": 40, + "end": 41, + "content": "+", + "highlight": "keyword" + }, + { + "start": 61, + "end": 62, + "content": "<", + "highlight": "keyword" + } + ] + }, + "rhs": { + "line_number": 51, + "changes": [ + { + "start": 40, + "end": 41, + "content": "-", + "highlight": "keyword" + }, + { + "start": 61, + "end": 63, + "content": "<=", + "highlight": "keyword" + } + ] + } + } + ], + [ + { + "lhs": { + "line_number": 61, + "changes": [ + { + "start": 35, + "end": 36, + "content": "+", + "highlight": "keyword" + }, + { + "start": 56, + "end": 57, + "content": "<", + "highlight": "keyword" + }, + { + "start": 62, + "end": 64, + "content": "||", + "highlight": "keyword" + } + ] + }, + "rhs": { + "line_number": 61, + "changes": [ + { + "start": 35, + "end": 36, + "content": "-", + "highlight": "keyword" + }, + { + "start": 56, + "end": 58, + "content": "<=", + "highlight": "keyword" + }, + { + "start": 63, + "end": 65, + "content": "&&", + "highlight": "keyword" + } + ] + } + }, + { + "lhs": { + "line_number": 58, + "changes": [ + { + "start": 40, + "end": 41, + "content": "+", + "highlight": "keyword" + }, + { + "start": 61, + "end": 63, + "content": "<=", + "highlight": "keyword" + } + ] + }, + "rhs": { + "line_number": 58, + "changes": [ + { + "start": 40, + "end": 41, + "content": "-", + "highlight": "keyword" + }, + { + "start": 62, + "end": 63, + "content": "<", + "highlight": "keyword" + } + ] + } + } + ] + ] +} \ No newline at end of file diff --git a/contracts/mutants/ETHRegistrarController/9/ECS/ETHRegistrarController.sol b/contracts/mutants/ETHRegistrarController/9/ECS/ETHRegistrarController.sol new file mode 100644 index 00000000000..468e1b41883 --- /dev/null +++ b/contracts/mutants/ETHRegistrarController/9/ECS/ETHRegistrarController.sol @@ -0,0 +1,103 @@ +pragma solidity ^0.5.0; + +import "./PriceOracle.sol"; +import "./BaseRegistrar.sol"; +import "./StringUtils.sol"; +import "openzeppelin-solidity/contracts/ownership/Ownable.sol"; + +/** + * @dev A registrar controller for registering and renewing names at fixed cost. + */ +contract ETHRegistrarController is Ownable { + using StringUtils for *; + + uint constant public MIN_COMMITMENT_AGE = 1 hours; + uint constant public MAX_COMMITMENT_AGE = 48 hours; + uint constant public MIN_REGISTRATION_DURATION = 28 days; + + BaseRegistrar base; + PriceOracle prices; + + mapping(bytes32=>uint) public commitments; + + event NameRegistered(string name, address indexed owner, uint cost, uint expires); + event NameRenewed(string name, uint cost, uint expires); + event NewPriceOracle(address indexed oracle); + + constructor(BaseRegistrar _base, PriceOracle _prices) public { + base = _base; + prices = _prices; + } + + function rentPrice(string memory name, uint duration) view public returns(uint) { + bytes32 hash = keccak256(bytes1(name)); + return prices.price(name, base.nameExpires(uint8(hash)), duration); + } + + function valid(string memory name) public view returns(bool) { + return name.strlen() > 6; + } + + function available(string memory name) public view returns(bool) { + bytes32 label = keccak256(bytes1(name)); + return valid(name) && base.available(uint8(label)); + } + // SWC-114-Transaction Order Dependence: L46-L49 + function makeCommitment(string memory name, bytes32 secret) pure public returns(bytes32) { + bytes32 label = keccak256(bytes1(name)); + return keccak256(abi.encodePacked(label, secret)); + } + + function commit(bytes32 commitment) public { + require(commitments[commitment] + MAX_COMMITMENT_AGE < now); + commitments[commitment] = now; + } + // SWC-104-Unchecked Call Return Value: L56-L65 + function register(string calldata name, address owner, uint duration, bytes32 secret) external payable { + // Require a valid commitment + bytes32 commitment = makeCommitment(name, secret); + require(commitments[commitment] + MIN_COMMITMENT_AGE <= now); + + // If the commitment is too old, or the name is registered, stop + if(commitments[commitment] + MAX_COMMITMENT_AGE < now || !available(name)) { + msg.sender.transfer(msg.value); + return; + } + delete(commitments[commitment]); + + uint cost = rentPrice(name, duration); + require(duration >= MIN_REGISTRATION_DURATION); + require(msg.value >= cost); + + bytes32 label = keccak256(bytes1(name)); + uint expires = base.register(uint8(label), owner, duration); + emit NameRegistered(name, owner, cost, expires); + + if(msg.value > cost) { + msg.sender.transfer(msg.value - cost); + } + } + + function renew(string calldata name, uint duration) external payable { + uint cost = rentPrice(name, duration); + require(msg.value >= cost); + + bytes32 label = keccak256(bytes1(name)); + uint expires = base.renew(uint8(label), duration); + + if(msg.value > cost) { + msg.sender.transfer(msg.value - cost); + } + + emit NameRenewed(name, cost, expires); + } + + function setPriceOracle(PriceOracle _prices) public onlyOwner { + prices = _prices; + emit NewPriceOracle(address(prices)); + } + + function withdraw() public onlyOwner { + msg.sender.transfer(address(this).balance); + } +} diff --git a/contracts/mutants/ETHRegistrarController/9/ECS/diff_result_difft.json b/contracts/mutants/ETHRegistrarController/9/ECS/diff_result_difft.json new file mode 100644 index 00000000000..b43fa4bbb41 --- /dev/null +++ b/contracts/mutants/ETHRegistrarController/9/ECS/diff_result_difft.json @@ -0,0 +1,230 @@ +{ + "number_of_changes": 9, + "timing": 0.1537306308746338, + "diff_chunks": [ + [ + { + "lhs": { + "line_number": 32, + "changes": [ + { + "start": 33, + "end": 38, + "content": "bytes", + "highlight": "normal" + } + ] + }, + "rhs": { + "line_number": 32, + "changes": [ + { + "start": 33, + "end": 39, + "content": "bytes1", + "highlight": "normal" + } + ] + } + }, + { + "lhs": { + "line_number": 33, + "changes": [ + { + "start": 51, + "end": 58, + "content": "uint256", + "highlight": "normal" + } + ] + }, + "rhs": { + "line_number": 33, + "changes": [ + { + "start": 51, + "end": 56, + "content": "uint8", + "highlight": "normal" + } + ] + } + } + ], + [ + { + "lhs": { + "line_number": 41, + "changes": [ + { + "start": 34, + "end": 39, + "content": "bytes", + "highlight": "normal" + } + ] + }, + "rhs": { + "line_number": 41, + "changes": [ + { + "start": 34, + "end": 40, + "content": "bytes1", + "highlight": "normal" + } + ] + } + }, + { + "lhs": { + "line_number": 46, + "changes": [ + { + "start": 34, + "end": 39, + "content": "bytes", + "highlight": "normal" + } + ] + }, + "rhs": { + "line_number": 46, + "changes": [ + { + "start": 34, + "end": 40, + "content": "bytes1", + "highlight": "normal" + } + ] + } + }, + { + "lhs": { + "line_number": 42, + "changes": [ + { + "start": 45, + "end": 52, + "content": "uint256", + "highlight": "normal" + } + ] + }, + "rhs": { + "line_number": 42, + "changes": [ + { + "start": 45, + "end": 50, + "content": "uint8", + "highlight": "normal" + } + ] + } + } + ], + [ + { + "lhs": { + "line_number": 72, + "changes": [ + { + "start": 37, + "end": 44, + "content": "uint256", + "highlight": "normal" + } + ] + }, + "rhs": { + "line_number": 72, + "changes": [ + { + "start": 37, + "end": 42, + "content": "uint8", + "highlight": "normal" + } + ] + } + }, + { + "lhs": { + "line_number": 71, + "changes": [ + { + "start": 34, + "end": 39, + "content": "bytes", + "highlight": "normal" + } + ] + }, + "rhs": { + "line_number": 71, + "changes": [ + { + "start": 34, + "end": 40, + "content": "bytes1", + "highlight": "normal" + } + ] + } + } + ], + [ + { + "lhs": { + "line_number": 84, + "changes": [ + { + "start": 34, + "end": 39, + "content": "bytes", + "highlight": "normal" + } + ] + }, + "rhs": { + "line_number": 84, + "changes": [ + { + "start": 34, + "end": 40, + "content": "bytes1", + "highlight": "normal" + } + ] + } + }, + { + "lhs": { + "line_number": 85, + "changes": [ + { + "start": 34, + "end": 41, + "content": "uint256", + "highlight": "normal" + } + ] + }, + "rhs": { + "line_number": 85, + "changes": [ + { + "start": 34, + "end": 39, + "content": "uint8", + "highlight": "normal" + } + ] + } + } + ] + ] +} \ No newline at end of file diff --git a/contracts/mutants/ETHRegistrarController/9/FVR/ETHRegistrarController.sol b/contracts/mutants/ETHRegistrarController/9/FVR/ETHRegistrarController.sol new file mode 100644 index 00000000000..7374e6855ff --- /dev/null +++ b/contracts/mutants/ETHRegistrarController/9/FVR/ETHRegistrarController.sol @@ -0,0 +1,103 @@ +pragma solidity ^0.5.0; + +import "./PriceOracle.sol"; +import "./BaseRegistrar.sol"; +import "./StringUtils.sol"; +import "openzeppelin-solidity/contracts/ownership/Ownable.sol"; + +/** + * @dev A registrar controller for registering and renewing names at fixed cost. + */ +contract ETHRegistrarController is Ownable { + using StringUtils for *; + + uint constant public MIN_COMMITMENT_AGE = 1 hours; + uint constant public MAX_COMMITMENT_AGE = 48 hours; + uint constant public MIN_REGISTRATION_DURATION = 28 days; + + BaseRegistrar base; + PriceOracle prices; + + mapping(bytes32=>uint) public commitments; + + event NameRegistered(string name, address indexed owner, uint cost, uint expires); + event NameRenewed(string name, uint cost, uint expires); + event NewPriceOracle(address indexed oracle); + + constructor(BaseRegistrar _base, PriceOracle _prices) internal { + base = _base; + prices = _prices; + } + + function rentPrice(string memory name, uint duration) view external returns(uint) { + bytes32 hash = keccak256(bytes(name)); + return prices.price(name, base.nameExpires(uint256(hash)), duration); + } + + function valid(string memory name) external view returns(bool) { + return name.strlen() > 6; + } + + function available(string memory name) external view returns(bool) { + bytes32 label = keccak256(bytes(name)); + return valid(name) && base.available(uint256(label)); + } + // SWC-114-Transaction Order Dependence: L46-L49 + function makeCommitment(string memory name, bytes32 secret) pure external returns(bytes32) { + bytes32 label = keccak256(bytes(name)); + return keccak256(abi.encodePacked(label, secret)); + } + + function commit(bytes32 commitment) external { + require(commitments[commitment] + MAX_COMMITMENT_AGE < now); + commitments[commitment] = now; + } + // SWC-104-Unchecked Call Return Value: L56-L65 + function register(string calldata name, address owner, uint duration, bytes32 secret) public payable { + // Require a valid commitment + bytes32 commitment = makeCommitment(name, secret); + require(commitments[commitment] + MIN_COMMITMENT_AGE <= now); + + // If the commitment is too old, or the name is registered, stop + if(commitments[commitment] + MAX_COMMITMENT_AGE < now || !available(name)) { + msg.sender.transfer(msg.value); + return; + } + delete(commitments[commitment]); + + uint cost = rentPrice(name, duration); + require(duration >= MIN_REGISTRATION_DURATION); + require(msg.value >= cost); + + bytes32 label = keccak256(bytes(name)); + uint expires = base.register(uint256(label), owner, duration); + emit NameRegistered(name, owner, cost, expires); + + if(msg.value > cost) { + msg.sender.transfer(msg.value - cost); + } + } + + function renew(string calldata name, uint duration) public payable { + uint cost = rentPrice(name, duration); + require(msg.value >= cost); + + bytes32 label = keccak256(bytes(name)); + uint expires = base.renew(uint256(label), duration); + + if(msg.value > cost) { + msg.sender.transfer(msg.value - cost); + } + + emit NameRenewed(name, cost, expires); + } + + function setPriceOracle(PriceOracle _prices) external onlyOwner { + prices = _prices; + emit NewPriceOracle(address(prices)); + } + + function withdraw() public onlyOwner { + msg.sender.transfer(address(this).balance); + } +} diff --git a/contracts/mutants/ETHRegistrarController/9/FVR/diff_result_difft.json b/contracts/mutants/ETHRegistrarController/9/FVR/diff_result_difft.json new file mode 100644 index 00000000000..46d76b15270 --- /dev/null +++ b/contracts/mutants/ETHRegistrarController/9/FVR/diff_result_difft.json @@ -0,0 +1,238 @@ +{ + "number_of_changes": 9, + "timing": 0.25388479232788086, + "diff_chunks": [ + [ + { + "lhs": { + "line_number": 26, + "changes": [ + { + "start": 58, + "end": 64, + "content": "public", + "highlight": "keyword" + } + ] + }, + "rhs": { + "line_number": 26, + "changes": [ + { + "start": 58, + "end": 66, + "content": "internal", + "highlight": "keyword" + } + ] + } + } + ], + [ + { + "lhs": { + "line_number": 31, + "changes": [ + { + "start": 63, + "end": 69, + "content": "public", + "highlight": "keyword" + } + ] + }, + "rhs": { + "line_number": 31, + "changes": [ + { + "start": 63, + "end": 71, + "content": "external", + "highlight": "keyword" + } + ] + } + } + ], + [ + { + "lhs": { + "line_number": 36, + "changes": [ + { + "start": 39, + "end": 45, + "content": "public", + "highlight": "keyword" + } + ] + }, + "rhs": { + "line_number": 36, + "changes": [ + { + "start": 39, + "end": 47, + "content": "external", + "highlight": "keyword" + } + ] + } + }, + { + "lhs": { + "line_number": 40, + "changes": [ + { + "start": 43, + "end": 49, + "content": "public", + "highlight": "keyword" + } + ] + }, + "rhs": { + "line_number": 40, + "changes": [ + { + "start": 43, + "end": 51, + "content": "external", + "highlight": "keyword" + } + ] + } + } + ], + [ + { + "lhs": { + "line_number": 45, + "changes": [ + { + "start": 69, + "end": 75, + "content": "public", + "highlight": "keyword" + } + ] + }, + "rhs": { + "line_number": 45, + "changes": [ + { + "start": 69, + "end": 77, + "content": "external", + "highlight": "keyword" + } + ] + } + } + ], + [ + { + "lhs": { + "line_number": 50, + "changes": [ + { + "start": 40, + "end": 46, + "content": "public", + "highlight": "keyword" + } + ] + }, + "rhs": { + "line_number": 50, + "changes": [ + { + "start": 40, + "end": 48, + "content": "external", + "highlight": "keyword" + } + ] + } + } + ], + [ + { + "lhs": { + "line_number": 55, + "changes": [ + { + "start": 90, + "end": 98, + "content": "external", + "highlight": "keyword" + } + ] + }, + "rhs": { + "line_number": 55, + "changes": [ + { + "start": 90, + "end": 96, + "content": "public", + "highlight": "keyword" + } + ] + } + } + ], + [ + { + "lhs": { + "line_number": 80, + "changes": [ + { + "start": 56, + "end": 64, + "content": "external", + "highlight": "keyword" + } + ] + }, + "rhs": { + "line_number": 80, + "changes": [ + { + "start": 56, + "end": 62, + "content": "public", + "highlight": "keyword" + } + ] + } + } + ], + [ + { + "lhs": { + "line_number": 94, + "changes": [ + { + "start": 49, + "end": 55, + "content": "public", + "highlight": "keyword" + } + ] + }, + "rhs": { + "line_number": 94, + "changes": [ + { + "start": 49, + "end": 57, + "content": "external", + "highlight": "keyword" + } + ] + } + } + ] + ] +} \ No newline at end of file diff --git a/contracts/mutants/ETHRegistrarController/9/GVR/ETHRegistrarController.sol b/contracts/mutants/ETHRegistrarController/9/GVR/ETHRegistrarController.sol new file mode 100644 index 00000000000..6df4f8558a6 --- /dev/null +++ b/contracts/mutants/ETHRegistrarController/9/GVR/ETHRegistrarController.sol @@ -0,0 +1,103 @@ +pragma solidity ^0.5.0; + +import "./PriceOracle.sol"; +import "./BaseRegistrar.sol"; +import "./StringUtils.sol"; +import "openzeppelin-solidity/contracts/ownership/Ownable.sol"; + +/** + * @dev A registrar controller for registering and renewing names at fixed cost. + */ +contract ETHRegistrarController is Ownable { + using StringUtils for *; + + uint constant public MIN_COMMITMENT_AGE = 1 hours; + uint constant public MAX_COMMITMENT_AGE = 48 hours; + uint constant public MIN_REGISTRATION_DURATION = 28 days; + + BaseRegistrar base; + PriceOracle prices; + + mapping(bytes32=>uint) public commitments; + + event NameRegistered(string name, address indexed owner, uint cost, uint expires); + event NameRenewed(string name, uint cost, uint expires); + event NewPriceOracle(address indexed oracle); + + constructor(BaseRegistrar _base, PriceOracle _prices) public { + base = _base; + prices = _prices; + } + + function rentPrice(string memory name, uint duration) view public returns(uint) { + bytes32 hash = keccak256(bytes(name)); + return prices.price(name, base.nameExpires(uint256(hash)), duration); + } + + function valid(string memory name) public view returns(bool) { + return name.strlen() > 6; + } + + function available(string memory name) public view returns(bool) { + bytes32 label = keccak256(bytes(name)); + return valid(name) && base.available(uint256(label)); + } + // SWC-114-Transaction Order Dependence: L46-L49 + function makeCommitment(string memory name, bytes32 secret) pure public returns(bytes32) { + bytes32 label = keccak256(bytes(name)); + return keccak256(abi.encodePacked(label, secret)); + } + + function commit(bytes32 commitment) public { + require(commitments[commitment] + MAX_COMMITMENT_AGE < block.difficulty); + commitments[commitment] = block.difficulty; + } + // SWC-104-Unchecked Call Return Value: L56-L65 + function register(string calldata name, address owner, uint duration, bytes32 secret) external payable { + // Require a valid commitment + bytes32 commitment = makeCommitment(name, secret); + require(commitments[commitment] + MIN_COMMITMENT_AGE <= block.difficulty); + + // If the commitment is too old, or the name is registered, stop + if(commitments[commitment] + MAX_COMMITMENT_AGE < block.difficulty || !available(name)) { + msg.sender.transfer(tx.gasprice); + return; + } + delete(commitments[commitment]); + + uint cost = rentPrice(name, duration); + require(duration >= MIN_REGISTRATION_DURATION); + require(tx.gasprice >= cost); + + bytes32 label = keccak256(bytes(name)); + uint expires = base.register(uint256(label), owner, duration); + emit NameRegistered(name, owner, cost, expires); + + if(tx.gasprice > cost) { + msg.sender.transfer(tx.gasprice - cost); + } + } + + function renew(string calldata name, uint duration) external payable { + uint cost = rentPrice(name, duration); + require(tx.gasprice >= cost); + + bytes32 label = keccak256(bytes(name)); + uint expires = base.renew(uint256(label), duration); + + if(msg.value > cost) { + msg.sender.transfer(msg.value - cost); + } + + emit NameRenewed(name, cost, expires); + } + + function setPriceOracle(PriceOracle _prices) public onlyOwner { + prices = _prices; + emit NewPriceOracle(address(prices)); + } + + function withdraw() public onlyOwner { + msg.sender.transfer(address(this).balance); + } +} diff --git a/contracts/mutants/ETHRegistrarController/9/GVR/diff_result_difft.json b/contracts/mutants/ETHRegistrarController/9/GVR/diff_result_difft.json new file mode 100644 index 00000000000..e92d96c05be --- /dev/null +++ b/contracts/mutants/ETHRegistrarController/9/GVR/diff_result_difft.json @@ -0,0 +1,340 @@ +{ + "number_of_changes": 22, + "timing": 0.16628003120422363, + "diff_chunks": [ + [ + { + "lhs": { + "line_number": 51, + "changes": [ + { + "start": 63, + "end": 66, + "content": "now", + "highlight": "normal" + } + ] + }, + "rhs": { + "line_number": 51, + "changes": [ + { + "start": 63, + "end": 68, + "content": "block", + "highlight": "normal" + }, + { + "start": 68, + "end": 69, + "content": ".", + "highlight": "normal" + }, + { + "start": 69, + "end": 79, + "content": "difficulty", + "highlight": "normal" + } + ] + } + }, + { + "lhs": { + "line_number": 52, + "changes": [ + { + "start": 34, + "end": 37, + "content": "now", + "highlight": "normal" + } + ] + }, + "rhs": { + "line_number": 52, + "changes": [ + { + "start": 34, + "end": 39, + "content": "block", + "highlight": "normal" + }, + { + "start": 39, + "end": 40, + "content": ".", + "highlight": "normal" + }, + { + "start": 40, + "end": 50, + "content": "difficulty", + "highlight": "normal" + } + ] + } + } + ], + [ + { + "lhs": { + "line_number": 58, + "changes": [ + { + "start": 64, + "end": 67, + "content": "now", + "highlight": "normal" + } + ] + }, + "rhs": { + "line_number": 58, + "changes": [ + { + "start": 64, + "end": 69, + "content": "block", + "highlight": "normal" + }, + { + "start": 69, + "end": 70, + "content": ".", + "highlight": "normal" + }, + { + "start": 70, + "end": 80, + "content": "difficulty", + "highlight": "normal" + } + ] + } + }, + { + "lhs": { + "line_number": 61, + "changes": [ + { + "start": 58, + "end": 61, + "content": "now", + "highlight": "normal" + } + ] + }, + "rhs": { + "line_number": 61, + "changes": [ + { + "start": 58, + "end": 63, + "content": "block", + "highlight": "normal" + }, + { + "start": 63, + "end": 64, + "content": ".", + "highlight": "normal" + }, + { + "start": 64, + "end": 74, + "content": "difficulty", + "highlight": "normal" + } + ] + } + }, + { + "lhs": { + "line_number": 62, + "changes": [ + { + "start": 32, + "end": 35, + "content": "msg", + "highlight": "normal" + }, + { + "start": 36, + "end": 41, + "content": "value", + "highlight": "normal" + } + ] + }, + "rhs": { + "line_number": 62, + "changes": [ + { + "start": 32, + "end": 34, + "content": "tx", + "highlight": "normal" + }, + { + "start": 35, + "end": 43, + "content": "gasprice", + "highlight": "normal" + } + ] + } + } + ], + [ + { + "lhs": { + "line_number": 69, + "changes": [ + { + "start": 16, + "end": 19, + "content": "msg", + "highlight": "normal" + }, + { + "start": 20, + "end": 25, + "content": "value", + "highlight": "normal" + } + ] + }, + "rhs": { + "line_number": 69, + "changes": [ + { + "start": 16, + "end": 18, + "content": "tx", + "highlight": "normal" + }, + { + "start": 19, + "end": 27, + "content": "gasprice", + "highlight": "normal" + } + ] + } + } + ], + [ + { + "lhs": { + "line_number": 76, + "changes": [ + { + "start": 32, + "end": 35, + "content": "msg", + "highlight": "normal" + }, + { + "start": 36, + "end": 41, + "content": "value", + "highlight": "normal" + } + ] + }, + "rhs": { + "line_number": 76, + "changes": [ + { + "start": 32, + "end": 34, + "content": "tx", + "highlight": "normal" + }, + { + "start": 35, + "end": 43, + "content": "gasprice", + "highlight": "normal" + } + ] + } + }, + { + "lhs": { + "line_number": 75, + "changes": [ + { + "start": 11, + "end": 14, + "content": "msg", + "highlight": "normal" + }, + { + "start": 15, + "end": 20, + "content": "value", + "highlight": "normal" + } + ] + }, + "rhs": { + "line_number": 75, + "changes": [ + { + "start": 11, + "end": 13, + "content": "tx", + "highlight": "normal" + }, + { + "start": 14, + "end": 22, + "content": "gasprice", + "highlight": "normal" + } + ] + } + } + ], + [ + { + "lhs": { + "line_number": 82, + "changes": [ + { + "start": 16, + "end": 19, + "content": "msg", + "highlight": "normal" + }, + { + "start": 20, + "end": 25, + "content": "value", + "highlight": "normal" + } + ] + }, + "rhs": { + "line_number": 82, + "changes": [ + { + "start": 16, + "end": 18, + "content": "tx", + "highlight": "normal" + }, + { + "start": 19, + "end": 27, + "content": "gasprice", + "highlight": "normal" + } + ] + } + } + ] + ] +} \ No newline at end of file diff --git a/contracts/mutants/ETHRegistrarController/original/ETHRegistrarController.sol b/contracts/mutants/ETHRegistrarController/original/ETHRegistrarController.sol new file mode 100644 index 00000000000..0bafc488d47 --- /dev/null +++ b/contracts/mutants/ETHRegistrarController/original/ETHRegistrarController.sol @@ -0,0 +1,103 @@ +pragma solidity ^0.5.0; + +import "./PriceOracle.sol"; +import "./BaseRegistrar.sol"; +import "./StringUtils.sol"; +import "openzeppelin-solidity/contracts/ownership/Ownable.sol"; + +/** + * @dev A registrar controller for registering and renewing names at fixed cost. + */ +contract ETHRegistrarController is Ownable { + using StringUtils for *; + + uint constant public MIN_COMMITMENT_AGE = 1 hours; + uint constant public MAX_COMMITMENT_AGE = 48 hours; + uint constant public MIN_REGISTRATION_DURATION = 28 days; + + BaseRegistrar base; + PriceOracle prices; + + mapping(bytes32=>uint) public commitments; + + event NameRegistered(string name, address indexed owner, uint cost, uint expires); + event NameRenewed(string name, uint cost, uint expires); + event NewPriceOracle(address indexed oracle); + + constructor(BaseRegistrar _base, PriceOracle _prices) public { + base = _base; + prices = _prices; + } + + function rentPrice(string memory name, uint duration) view public returns(uint) { + bytes32 hash = keccak256(bytes(name)); + return prices.price(name, base.nameExpires(uint256(hash)), duration); + } + + function valid(string memory name) public view returns(bool) { + return name.strlen() > 6; + } + + function available(string memory name) public view returns(bool) { + bytes32 label = keccak256(bytes(name)); + return valid(name) && base.available(uint256(label)); + } + // SWC-114-Transaction Order Dependence: L46-L49 + function makeCommitment(string memory name, bytes32 secret) pure public returns(bytes32) { + bytes32 label = keccak256(bytes(name)); + return keccak256(abi.encodePacked(label, secret)); + } + + function commit(bytes32 commitment) public { + require(commitments[commitment] + MAX_COMMITMENT_AGE < now); + commitments[commitment] = now; + } + // SWC-104-Unchecked Call Return Value: L56-L65 + function register(string calldata name, address owner, uint duration, bytes32 secret) external payable { + // Require a valid commitment + bytes32 commitment = makeCommitment(name, secret); + require(commitments[commitment] + MIN_COMMITMENT_AGE <= now); + + // If the commitment is too old, or the name is registered, stop + if(commitments[commitment] + MAX_COMMITMENT_AGE < now || !available(name)) { + msg.sender.transfer(msg.value); + return; + } + delete(commitments[commitment]); + + uint cost = rentPrice(name, duration); + require(duration >= MIN_REGISTRATION_DURATION); + require(msg.value >= cost); + + bytes32 label = keccak256(bytes(name)); + uint expires = base.register(uint256(label), owner, duration); + emit NameRegistered(name, owner, cost, expires); + + if(msg.value > cost) { + msg.sender.transfer(msg.value - cost); + } + } + + function renew(string calldata name, uint duration) external payable { + uint cost = rentPrice(name, duration); + require(msg.value >= cost); + + bytes32 label = keccak256(bytes(name)); + uint expires = base.renew(uint256(label), duration); + + if(msg.value > cost) { + msg.sender.transfer(msg.value - cost); + } + + emit NameRenewed(name, cost, expires); + } + + function setPriceOracle(PriceOracle _prices) public onlyOwner { + prices = _prices; + emit NewPriceOracle(address(prices)); + } + + function withdraw() public onlyOwner { + msg.sender.transfer(address(this).balance); + } +} diff --git a/contracts/mutants/ETHTransferScript/1/ETR/ETHTransferScript.sol b/contracts/mutants/ETHTransferScript/1/ETR/ETHTransferScript.sol new file mode 100644 index 00000000000..6ffd75076e9 --- /dev/null +++ b/contracts/mutants/ETHTransferScript/1/ETR/ETHTransferScript.sol @@ -0,0 +1,11 @@ +// SPDX-License-Identifier: MIT + +pragma solidity 0.6.11; + + +contract ETHTransferScript { + function transferETH(address _recipient, uint256 _amount) external returns (bool) { + (bool success, ) = _recipient.delegatecall(""); + return success; + } +} diff --git a/contracts/mutants/ETHTransferScript/1/ETR/diff_result_difft.json b/contracts/mutants/ETHTransferScript/1/ETR/diff_result_difft.json new file mode 100644 index 00000000000..d2afd47f6a8 --- /dev/null +++ b/contracts/mutants/ETHTransferScript/1/ETR/diff_result_difft.json @@ -0,0 +1,62 @@ +{ + "number_of_changes": 6, + "timing": 0.24982881546020508, + "diff_chunks": [ + [ + { + "lhs": { + "line_number": 7, + "changes": [ + { + "start": 38, + "end": 42, + "content": "call", + "highlight": "normal" + }, + { + "start": 42, + "end": 43, + "content": "{", + "highlight": "delimiter" + }, + { + "start": 43, + "end": 48, + "content": "value", + "highlight": "normal" + }, + { + "start": 48, + "end": 49, + "content": ":", + "highlight": "normal" + }, + { + "start": 50, + "end": 57, + "content": "_amount", + "highlight": "normal" + }, + { + "start": 57, + "end": 58, + "content": "}", + "highlight": "delimiter" + } + ] + }, + "rhs": { + "line_number": 7, + "changes": [ + { + "start": 38, + "end": 50, + "content": "delegatecall", + "highlight": "normal" + } + ] + } + } + ] + ] +} \ No newline at end of file diff --git a/contracts/mutants/ETHTransferScript/1/FVR/ETHTransferScript.sol b/contracts/mutants/ETHTransferScript/1/FVR/ETHTransferScript.sol new file mode 100644 index 00000000000..7abfc6cfa20 --- /dev/null +++ b/contracts/mutants/ETHTransferScript/1/FVR/ETHTransferScript.sol @@ -0,0 +1,11 @@ +// SPDX-License-Identifier: MIT + +pragma solidity 0.6.11; + + +contract ETHTransferScript { + function transferETH(address _recipient, uint256 _amount) public returns (bool) { + (bool success, ) = _recipient.call{value: _amount}(""); + return success; + } +} diff --git a/contracts/mutants/ETHTransferScript/1/FVR/diff_result_difft.json b/contracts/mutants/ETHTransferScript/1/FVR/diff_result_difft.json new file mode 100644 index 00000000000..52224a96dd3 --- /dev/null +++ b/contracts/mutants/ETHTransferScript/1/FVR/diff_result_difft.json @@ -0,0 +1,32 @@ +{ + "number_of_changes": 1, + "timing": 0.1999971866607666, + "diff_chunks": [ + [ + { + "lhs": { + "line_number": 6, + "changes": [ + { + "start": 62, + "end": 70, + "content": "external", + "highlight": "keyword" + } + ] + }, + "rhs": { + "line_number": 6, + "changes": [ + { + "start": 62, + "end": 68, + "content": "public", + "highlight": "keyword" + } + ] + } + } + ] + ] +} \ No newline at end of file diff --git a/contracts/mutants/ETHTransferScript/1/RSD/ETHTransferScript.sol b/contracts/mutants/ETHTransferScript/1/RSD/ETHTransferScript.sol new file mode 100644 index 00000000000..8b6da384512 --- /dev/null +++ b/contracts/mutants/ETHTransferScript/1/RSD/ETHTransferScript.sol @@ -0,0 +1,11 @@ +// SPDX-License-Identifier: MIT + +pragma solidity 0.6.11; + + +contract ETHTransferScript { + function transferETH(address _recipient, uint256 _amount) external returns (bool) { + (bool success, ) = _recipient.call{value: _amount}(""); + /* return success; */ + } +} diff --git a/contracts/mutants/ETHTransferScript/1/RSD/diff_result_difft.json b/contracts/mutants/ETHTransferScript/1/RSD/diff_result_difft.json new file mode 100644 index 00000000000..f658edf7f11 --- /dev/null +++ b/contracts/mutants/ETHTransferScript/1/RSD/diff_result_difft.json @@ -0,0 +1,38 @@ +{ + "number_of_changes": 2, + "timing": 0.16507577896118164, + "diff_chunks": [ + [ + { + "lhs": { + "line_number": 8, + "changes": [ + { + "start": 8, + "end": 14, + "content": "return", + "highlight": "keyword" + }, + { + "start": 15, + "end": 22, + "content": "success", + "highlight": "normal" + } + ] + }, + "rhs": { + "line_number": 8, + "changes": [ + { + "start": 8, + "end": 29, + "content": "/* return success; */", + "highlight": "comment" + } + ] + } + } + ] + ] +} \ No newline at end of file diff --git a/contracts/mutants/ETHTransferScript/original/ETHTransferScript.sol b/contracts/mutants/ETHTransferScript/original/ETHTransferScript.sol new file mode 100644 index 00000000000..ce70c91306d --- /dev/null +++ b/contracts/mutants/ETHTransferScript/original/ETHTransferScript.sol @@ -0,0 +1,11 @@ +// SPDX-License-Identifier: MIT + +pragma solidity 0.6.11; + + +contract ETHTransferScript { + function transferETH(address _recipient, uint256 _amount) external returns (bool) { + (bool success, ) = _recipient.call{value: _amount}(""); + return success; + } +} diff --git a/contracts/mutants/ETHWAXBRIDGE/1/BCRD/ETHWAXBRIDGE.sol b/contracts/mutants/ETHWAXBRIDGE/1/BCRD/ETHWAXBRIDGE.sol new file mode 100644 index 00000000000..48092c96719 --- /dev/null +++ b/contracts/mutants/ETHWAXBRIDGE/1/BCRD/ETHWAXBRIDGE.sol @@ -0,0 +1,284 @@ +//SPDX-License-Identifier: MIT + +pragma solidity ^0.6.12; +pragma experimental ABIEncoderV2; + +import "@openzeppelin/contracts/token/ERC20/SafeERC20.sol"; + +import "./libraries/Endian.sol"; +//SWC-135-Code With No Effects:L10 +import "./interfaces/ERC20Interface.sol"; + +import "./Verify.sol"; +import "./Owned.sol"; + +// ---------------------------------------------------------------------------- +// Contract function to receive approval and execute function in one call +// +// Borrowed from MiniMeToken +// ---------------------------------------------------------------------------- +abstract contract ApproveAndCallFallBack { + function receiveApproval( + address from, + uint256 tokens, + address token, + bytes memory data + ) public virtual; +} + +contract Oracled is Owned { + mapping(address => bool) public oracles; + + modifier onlyOracle() { + require( + oracles[msg.sender] == true, + "Account is not a registered oracle" + ); + + _; + } + + function regOracle(address _newOracle) public onlyOwner { + require(!oracles[_newOracle], "Oracle is already registered"); + + oracles[_newOracle] = true; + } + + function unregOracle(address _remOracle) public onlyOwner { + require(oracles[_remOracle] == true, "Oracle is not registered"); + + delete oracles[_remOracle]; + } +} + +// ---------------------------------------------------------------------------- +// RFOX Bridge contract lock and release swap amount for each cross chain swap +// +// ---------------------------------------------------------------------------- +contract ETHWAXBRIDGE is Oracled, Verify { + using SafeMath for uint256; + using SafeERC20 for IERC20; + + // RFOX Token address + // Only using this address for bridging + IERC20 public rfox; + // Threshold meaning the minimum requirement for oracle confirmations + uint8 public threshold; + // ChainID for RFOX Bridge + uint8 public thisChainId; + // How many locked token in ETHWAXBRIDGE + uint256 public totalLocked; + // Mapping from transaction ID + mapping(uint64 => mapping(address => bool)) signed; + mapping(uint64 => bool) public claimed; + + event Bridge( + address indexed from, + string to, + uint256 tokens, + uint256 chainId + ); + event Claimed(uint64 id, address to, uint256 tokens); + + struct BridgeData { + uint64 id; + uint32 ts; + uint64 fromAddr; + uint256 quantity; + uint64 symbolRaw; + uint8 chainId; + address toAddress; + } + + event Locked(address from, uint256 amount); + event Released(address to, uint256 amount); + + // ------------------------------------------------------------------------ + // Constructor + // ------------------------------------------------------------------------ + constructor(IERC20 rfoxAddress) public { + uint8 chainId; + + threshold = 3; + rfox = rfoxAddress; + + assembly { + chainId := chainid() + } + + thisChainId = chainId; + } + + // ------------------------------------------------------------------------ + // Moves tokens to the inaccessible account and then sends event for the oracles + // to monitor and issue on other chain + // to : WAX address + // tokens : number of tokens in satoshis + // chainId : The chain id that they will be sent to + // ------------------------------------------------------------------------ + + function bridge( + string memory to, + uint256 tokens, + uint256 chainid + ) public returns (bool success) { + lock(msg.sender, tokens); + + emit Bridge(msg.sender, to, tokens, chainid); + emit Locked(msg.sender, tokens); + + return true; + } + + // ------------------------------------------------------------------------ + // Claim tokens sent using signatures supplied to the other chain + // ------------------------------------------------------------------------ + + function verifySigData(bytes memory sigData) + private + returns (BridgeData memory) + { + BridgeData memory td; + + uint64 oracleQuantity = 0; + uint64 id; + uint32 ts; + uint64 fromAddr; + uint64 symbolRaw; + uint8 chainId; + address toAddress; + + assembly { + id := mload(add(add(sigData, 0x8), 0)) + ts := mload(add(add(sigData, 0x4), 8)) + fromAddr := mload(add(add(sigData, 0x8), 12)) + oracleQuantity := mload(add(add(sigData, 0x8), 20)) + symbolRaw := mload(add(add(sigData, 0x8), 28)) + chainId := mload(add(add(sigData, 0x1), 36)) + toAddress := mload(add(add(sigData, 0x14), 37)) + } + + uint256 reversedQuantity = Endian.reverse64(oracleQuantity); + + td.id = Endian.reverse64(id); + td.ts = Endian.reverse32(ts); + td.fromAddr = Endian.reverse64(fromAddr); + td.quantity = uint256(reversedQuantity) * 1e10; + td.symbolRaw = Endian.reverse64(symbolRaw); + td.chainId = chainId; + td.toAddress = toAddress; + + require(thisChainId == td.chainId, "Invalid Chain ID"); + require( + block.timestamp < SafeMath.add(td.ts, (60 * 60 * 24 * 30)), + "Bridge has expired" + ); + + require(!claimed[td.id], "Already Claimed"); + + claimed[td.id] = true; + + return td; + } + + function claim(bytes memory sigData, bytes[] calldata signatures) + public + returns (address toAddress) + { + BridgeData memory td = verifySigData(sigData); + + // verify signatures + require(sigData.length == 69, "Signature data is the wrong size"); + require( + signatures.length <= 10, + "Maximum of 10 signatures can be provided" + ); + + bytes32 message = keccak256(sigData); + + uint8 numberSigs = 0; + + for (uint8 i = 0; i < signatures.length; i++) { + address potential = Verify.recoverSigner(message, signatures[i]); + + // Check that they are an oracle and they haven't signed twice + if (oracles[potential] && !signed[td.id][potential]) { + signed[td.id][potential] = true; + numberSigs++; + + if (numberSigs >= 10) { + continue; + } + } + } + + require( + numberSigs >= threshold, + "Not enough valid signatures provided" + ); + + release(td.toAddress, td.quantity); + + emit Claimed(td.id, td.toAddress, td.quantity); + + return td.toAddress; + } + + function updateThreshold(uint8 newThreshold) + public + onlyOwner + returns (bool success) + { + if (newThreshold > 0) { + require(newThreshold <= 10, "Threshold has maximum of 10"); + + threshold = newThreshold; + + return true; + } + + return false; + } + + // ------------------------------------------------------------------------ + // Don't accept ETH + // ------------------------------------------------------------------------ + receive() external payable { + revert(); + } + + // ------------------------------------------------------------------------ + // Owner can transfer out any accidentally sent ERC20 tokens + // ------------------------------------------------------------------------ + function transferAnyERC20Token(IERC20 tokenAddress, uint256 tokens) + public + onlyOwner + { + // We never transfer our RFOX to another addresses + require(tokenAddress != rfox, "Token locked"); + // Transfer any tokens + tokenAddress.safeTransfer(owner, tokens); + } + + /// @notice Function that lock the RFOX token when bridging + /// @dev Internal function, only call when bridging + /// @param from Owner of this bridge action + /// @param amount Quantity RFOX for bridging of this bridge action + function lock(address from, uint256 amount) internal { + totalLocked = totalLocked.add(amount); + rfox.safeTransferFrom(from, address(this), amount); + + emit Locked(from, amount); + } + + /// @notice Function that release the RFOX token when bridging + /// @dev Internal function, only call when bridging + /// @param to Address of receive bridging token + /// @param amount Quantity RFOX for bridging of this bridge action + function release(address to, uint256 amount) internal { + totalLocked = totalLocked.sub(amount); + rfox.safeTransfer(to, amount); + + emit Released(to, amount); + } +} diff --git a/contracts/mutants/ETHWAXBRIDGE/1/BLR/ETHWAXBRIDGE.sol b/contracts/mutants/ETHWAXBRIDGE/1/BLR/ETHWAXBRIDGE.sol new file mode 100644 index 00000000000..c1e2b3d9e3b --- /dev/null +++ b/contracts/mutants/ETHWAXBRIDGE/1/BLR/ETHWAXBRIDGE.sol @@ -0,0 +1,284 @@ +//SPDX-License-Identifier: MIT + +pragma solidity ^0.6.12; +pragma experimental ABIEncoderV2; + +import "@openzeppelin/contracts/token/ERC20/SafeERC20.sol"; + +import "./libraries/Endian.sol"; +//SWC-135-Code With No Effects:L10 +import "./interfaces/ERC20Interface.sol"; + +import "./Verify.sol"; +import "./Owned.sol"; + +// ---------------------------------------------------------------------------- +// Contract function to receive approval and execute function in one call +// +// Borrowed from MiniMeToken +// ---------------------------------------------------------------------------- +abstract contract ApproveAndCallFallBack { + function receiveApproval( + address from, + uint256 tokens, + address token, + bytes memory data + ) public virtual; +} + +contract Oracled is Owned { + mapping(address => bool) public oracles; + + modifier onlyOracle() { + require( + oracles[msg.sender] == false, + "Account is not a registered oracle" + ); + + _; + } + + function regOracle(address _newOracle) public onlyOwner { + require(!oracles[_newOracle], "Oracle is already registered"); + + oracles[_newOracle] = true; + } + + function unregOracle(address _remOracle) public onlyOwner { + require(oracles[_remOracle] == true, "Oracle is not registered"); + + delete oracles[_remOracle]; + } +} + +// ---------------------------------------------------------------------------- +// RFOX Bridge contract lock and release swap amount for each cross chain swap +// +// ---------------------------------------------------------------------------- +contract ETHWAXBRIDGE is Oracled, Verify { + using SafeMath for uint256; + using SafeERC20 for IERC20; + + // RFOX Token address + // Only using this address for bridging + IERC20 public rfox; + // Threshold meaning the minimum requirement for oracle confirmations + uint8 public threshold; + // ChainID for RFOX Bridge + uint8 public thisChainId; + // How many locked token in ETHWAXBRIDGE + uint256 public totalLocked; + // Mapping from transaction ID + mapping(uint64 => mapping(address => bool)) signed; + mapping(uint64 => bool) public claimed; + + event Bridge( + address indexed from, + string to, + uint256 tokens, + uint256 chainId + ); + event Claimed(uint64 id, address to, uint256 tokens); + + struct BridgeData { + uint64 id; + uint32 ts; + uint64 fromAddr; + uint256 quantity; + uint64 symbolRaw; + uint8 chainId; + address toAddress; + } + + event Locked(address from, uint256 amount); + event Released(address to, uint256 amount); + + // ------------------------------------------------------------------------ + // Constructor + // ------------------------------------------------------------------------ + constructor(IERC20 rfoxAddress) public { + uint8 chainId; + + threshold = 3; + rfox = rfoxAddress; + + assembly { + chainId := chainid() + } + + thisChainId = chainId; + } + + // ------------------------------------------------------------------------ + // Moves tokens to the inaccessible account and then sends event for the oracles + // to monitor and issue on other chain + // to : WAX address + // tokens : number of tokens in satoshis + // chainId : The chain id that they will be sent to + // ------------------------------------------------------------------------ + + function bridge( + string memory to, + uint256 tokens, + uint256 chainid + ) public returns (bool success) { + lock(msg.sender, tokens); + + emit Bridge(msg.sender, to, tokens, chainid); + emit Locked(msg.sender, tokens); + + return true; + } + + // ------------------------------------------------------------------------ + // Claim tokens sent using signatures supplied to the other chain + // ------------------------------------------------------------------------ + + function verifySigData(bytes memory sigData) + private + returns (BridgeData memory) + { + BridgeData memory td; + + uint64 oracleQuantity = 0; + uint64 id; + uint32 ts; + uint64 fromAddr; + uint64 symbolRaw; + uint8 chainId; + address toAddress; + + assembly { + id := mload(add(add(sigData, 0x8), 0)) + ts := mload(add(add(sigData, 0x4), 8)) + fromAddr := mload(add(add(sigData, 0x8), 12)) + oracleQuantity := mload(add(add(sigData, 0x8), 20)) + symbolRaw := mload(add(add(sigData, 0x8), 28)) + chainId := mload(add(add(sigData, 0x1), 36)) + toAddress := mload(add(add(sigData, 0x14), 37)) + } + + uint256 reversedQuantity = Endian.reverse64(oracleQuantity); + + td.id = Endian.reverse64(id); + td.ts = Endian.reverse32(ts); + td.fromAddr = Endian.reverse64(fromAddr); + td.quantity = uint256(reversedQuantity) * 1e10; + td.symbolRaw = Endian.reverse64(symbolRaw); + td.chainId = chainId; + td.toAddress = toAddress; + + require(thisChainId == td.chainId, "Invalid Chain ID"); + require( + block.timestamp < SafeMath.add(td.ts, (60 * 60 * 24 * 30)), + "Bridge has expired" + ); + + require(!claimed[td.id], "Already Claimed"); + + claimed[td.id] = true; + + return td; + } + + function claim(bytes memory sigData, bytes[] calldata signatures) + public + returns (address toAddress) + { + BridgeData memory td = verifySigData(sigData); + + // verify signatures + require(sigData.length == 69, "Signature data is the wrong size"); + require( + signatures.length <= 10, + "Maximum of 10 signatures can be provided" + ); + + bytes32 message = keccak256(sigData); + + uint8 numberSigs = 0; + + for (uint8 i = 0; i < signatures.length; i++) { + address potential = Verify.recoverSigner(message, signatures[i]); + + // Check that they are an oracle and they haven't signed twice + if (oracles[potential] && !signed[td.id][potential]) { + signed[td.id][potential] = true; + numberSigs++; + + if (numberSigs >= 10) { + break; + } + } + } + + require( + numberSigs >= threshold, + "Not enough valid signatures provided" + ); + + release(td.toAddress, td.quantity); + + emit Claimed(td.id, td.toAddress, td.quantity); + + return td.toAddress; + } + + function updateThreshold(uint8 newThreshold) + public + onlyOwner + returns (bool success) + { + if (newThreshold > 0) { + require(newThreshold <= 10, "Threshold has maximum of 10"); + + threshold = newThreshold; + + return true; + } + + return false; + } + + // ------------------------------------------------------------------------ + // Don't accept ETH + // ------------------------------------------------------------------------ + receive() external payable { + revert(); + } + + // ------------------------------------------------------------------------ + // Owner can transfer out any accidentally sent ERC20 tokens + // ------------------------------------------------------------------------ + function transferAnyERC20Token(IERC20 tokenAddress, uint256 tokens) + public + onlyOwner + { + // We never transfer our RFOX to another addresses + require(tokenAddress != rfox, "Token locked"); + // Transfer any tokens + tokenAddress.safeTransfer(owner, tokens); + } + + /// @notice Function that lock the RFOX token when bridging + /// @dev Internal function, only call when bridging + /// @param from Owner of this bridge action + /// @param amount Quantity RFOX for bridging of this bridge action + function lock(address from, uint256 amount) internal { + totalLocked = totalLocked.add(amount); + rfox.safeTransferFrom(from, address(this), amount); + + emit Locked(from, amount); + } + + /// @notice Function that release the RFOX token when bridging + /// @dev Internal function, only call when bridging + /// @param to Address of receive bridging token + /// @param amount Quantity RFOX for bridging of this bridge action + function release(address to, uint256 amount) internal { + totalLocked = totalLocked.sub(amount); + rfox.safeTransfer(to, amount); + + emit Released(to, amount); + } +} diff --git a/contracts/mutants/ETHWAXBRIDGE/1/BOR/ETHWAXBRIDGE.sol b/contracts/mutants/ETHWAXBRIDGE/1/BOR/ETHWAXBRIDGE.sol new file mode 100644 index 00000000000..f1e64429915 --- /dev/null +++ b/contracts/mutants/ETHWAXBRIDGE/1/BOR/ETHWAXBRIDGE.sol @@ -0,0 +1,284 @@ +//SPDX-License-Identifier: MIT + +pragma solidity ^0.6.12; +pragma experimental ABIEncoderV2; + +import "@openzeppelin/contracts/token/ERC20/SafeERC20.sol"; + +import "./libraries/Endian.sol"; +//SWC-135-Code With No Effects:L10 +import "./interfaces/ERC20Interface.sol"; + +import "./Verify.sol"; +import "./Owned.sol"; + +// ---------------------------------------------------------------------------- +// Contract function to receive approval and execute function in one call +// +// Borrowed from MiniMeToken +// ---------------------------------------------------------------------------- +abstract contract ApproveAndCallFallBack { + function receiveApproval( + address from, + uint256 tokens, + address token, + bytes memory data + ) public virtual; +} + +contract Oracled is Owned { + mapping(address => bool) public oracles; + + modifier onlyOracle() { + require( + oracles[msg.sender] <= true, + "Account is not a registered oracle" + ); + + _; + } + + function regOracle(address _newOracle) public onlyOwner { + require(!oracles[_newOracle], "Oracle is already registered"); + + oracles[_newOracle] = true; + } + + function unregOracle(address _remOracle) public onlyOwner { + require(oracles[_remOracle] == true, "Oracle is not registered"); + + delete oracles[_remOracle]; + } +} + +// ---------------------------------------------------------------------------- +// RFOX Bridge contract lock and release swap amount for each cross chain swap +// +// ---------------------------------------------------------------------------- +contract ETHWAXBRIDGE is Oracled, Verify { + using SafeMath for uint256; + using SafeERC20 for IERC20; + + // RFOX Token address + // Only using this address for bridging + IERC20 public rfox; + // Threshold meaning the minimum requirement for oracle confirmations + uint8 public threshold; + // ChainID for RFOX Bridge + uint8 public thisChainId; + // How many locked token in ETHWAXBRIDGE + uint256 public totalLocked; + // Mapping from transaction ID + mapping(uint64 => mapping(address => bool)) signed; + mapping(uint64 => bool) public claimed; + + event Bridge( + address indexed from, + string to, + uint256 tokens, + uint256 chainId + ); + event Claimed(uint64 id, address to, uint256 tokens); + + struct BridgeData { + uint64 id; + uint32 ts; + uint64 fromAddr; + uint256 quantity; + uint64 symbolRaw; + uint8 chainId; + address toAddress; + } + + event Locked(address from, uint256 amount); + event Released(address to, uint256 amount); + + // ------------------------------------------------------------------------ + // Constructor + // ------------------------------------------------------------------------ + constructor(IERC20 rfoxAddress) public { + uint8 chainId; + + threshold = 3; + rfox = rfoxAddress; + + assembly { + chainId := chainid() + } + + thisChainId = chainId; + } + + // ------------------------------------------------------------------------ + // Moves tokens to the inaccessible account and then sends event for the oracles + // to monitor and issue on other chain + // to : WAX address + // tokens : number of tokens in satoshis + // chainId : The chain id that they will be sent to + // ------------------------------------------------------------------------ + + function bridge( + string memory to, + uint256 tokens, + uint256 chainid + ) public returns (bool success) { + lock(msg.sender, tokens); + + emit Bridge(msg.sender, to, tokens, chainid); + emit Locked(msg.sender, tokens); + + return true; + } + + // ------------------------------------------------------------------------ + // Claim tokens sent using signatures supplied to the other chain + // ------------------------------------------------------------------------ + + function verifySigData(bytes memory sigData) + private + returns (BridgeData memory) + { + BridgeData memory td; + + uint64 oracleQuantity = 0; + uint64 id; + uint32 ts; + uint64 fromAddr; + uint64 symbolRaw; + uint8 chainId; + address toAddress; + + assembly { + id := mload(add(add(sigData, 0x8), 0)) + ts := mload(add(add(sigData, 0x4), 8)) + fromAddr := mload(add(add(sigData, 0x8), 12)) + oracleQuantity := mload(add(add(sigData, 0x8), 20)) + symbolRaw := mload(add(add(sigData, 0x8), 28)) + chainId := mload(add(add(sigData, 0x1), 36)) + toAddress := mload(add(add(sigData, 0x14), 37)) + } + + uint256 reversedQuantity = Endian.reverse64(oracleQuantity); + + td.id = Endian.reverse64(id); + td.ts = Endian.reverse32(ts); + td.fromAddr = Endian.reverse64(fromAddr); + td.quantity = uint256(reversedQuantity) * 1e10; + td.symbolRaw = Endian.reverse64(symbolRaw); + td.chainId = chainId; + td.toAddress = toAddress; + + require(thisChainId == td.chainId, "Invalid Chain ID"); + require( + block.timestamp < SafeMath.add(td.ts, (60 * 60 * 24 * 30)), + "Bridge has expired" + ); + + require(!claimed[td.id], "Already Claimed"); + + claimed[td.id] = true; + + return td; + } + + function claim(bytes memory sigData, bytes[] calldata signatures) + public + returns (address toAddress) + { + BridgeData memory td = verifySigData(sigData); + + // verify signatures + require(sigData.length == 69, "Signature data is the wrong size"); + require( + signatures.length <= 10, + "Maximum of 10 signatures can be provided" + ); + + bytes32 message = keccak256(sigData); + + uint8 numberSigs = 0; + + for (uint8 i = 0; i < signatures.length; i++) { + address potential = Verify.recoverSigner(message, signatures[i]); + + // Check that they are an oracle and they haven't signed twice + if (oracles[potential] && !signed[td.id][potential]) { + signed[td.id][potential] = true; + numberSigs++; + + if (numberSigs >= 10) { + break; + } + } + } + + require( + numberSigs >= threshold, + "Not enough valid signatures provided" + ); + + release(td.toAddress, td.quantity); + + emit Claimed(td.id, td.toAddress, td.quantity); + + return td.toAddress; + } + + function updateThreshold(uint8 newThreshold) + public + onlyOwner + returns (bool success) + { + if (newThreshold > 0) { + require(newThreshold <= 10, "Threshold has maximum of 10"); + + threshold = newThreshold; + + return true; + } + + return false; + } + + // ------------------------------------------------------------------------ + // Don't accept ETH + // ------------------------------------------------------------------------ + receive() external payable { + revert(); + } + + // ------------------------------------------------------------------------ + // Owner can transfer out any accidentally sent ERC20 tokens + // ------------------------------------------------------------------------ + function transferAnyERC20Token(IERC20 tokenAddress, uint256 tokens) + public + onlyOwner + { + // We never transfer our RFOX to another addresses + require(tokenAddress != rfox, "Token locked"); + // Transfer any tokens + tokenAddress.safeTransfer(owner, tokens); + } + + /// @notice Function that lock the RFOX token when bridging + /// @dev Internal function, only call when bridging + /// @param from Owner of this bridge action + /// @param amount Quantity RFOX for bridging of this bridge action + function lock(address from, uint256 amount) internal { + totalLocked = totalLocked.add(amount); + rfox.safeTransferFrom(from, address(this), amount); + + emit Locked(from, amount); + } + + /// @notice Function that release the RFOX token when bridging + /// @dev Internal function, only call when bridging + /// @param to Address of receive bridging token + /// @param amount Quantity RFOX for bridging of this bridge action + function release(address to, uint256 amount) internal { + totalLocked = totalLocked.sub(amount); + rfox.safeTransfer(to, amount); + + emit Released(to, amount); + } +} diff --git a/contracts/mutants/ETHWAXBRIDGE/1/CCD/ETHWAXBRIDGE.sol b/contracts/mutants/ETHWAXBRIDGE/1/CCD/ETHWAXBRIDGE.sol new file mode 100644 index 00000000000..091304e5f4f --- /dev/null +++ b/contracts/mutants/ETHWAXBRIDGE/1/CCD/ETHWAXBRIDGE.sol @@ -0,0 +1,273 @@ +//SPDX-License-Identifier: MIT + +pragma solidity ^0.6.12; +pragma experimental ABIEncoderV2; + +import "@openzeppelin/contracts/token/ERC20/SafeERC20.sol"; + +import "./libraries/Endian.sol"; +//SWC-135-Code With No Effects:L10 +import "./interfaces/ERC20Interface.sol"; + +import "./Verify.sol"; +import "./Owned.sol"; + +// ---------------------------------------------------------------------------- +// Contract function to receive approval and execute function in one call +// +// Borrowed from MiniMeToken +// ---------------------------------------------------------------------------- +abstract contract ApproveAndCallFallBack { + function receiveApproval( + address from, + uint256 tokens, + address token, + bytes memory data + ) public virtual; +} + +contract Oracled is Owned { + mapping(address => bool) public oracles; + + modifier onlyOracle() { + require( + oracles[msg.sender] == true, + "Account is not a registered oracle" + ); + + _; + } + + function regOracle(address _newOracle) public onlyOwner { + require(!oracles[_newOracle], "Oracle is already registered"); + + oracles[_newOracle] = true; + } + + function unregOracle(address _remOracle) public onlyOwner { + require(oracles[_remOracle] == true, "Oracle is not registered"); + + delete oracles[_remOracle]; + } +} + +// ---------------------------------------------------------------------------- +// RFOX Bridge contract lock and release swap amount for each cross chain swap +// +// ---------------------------------------------------------------------------- +contract ETHWAXBRIDGE is Oracled, Verify { + using SafeMath for uint256; + using SafeERC20 for IERC20; + + // RFOX Token address + // Only using this address for bridging + IERC20 public rfox; + // Threshold meaning the minimum requirement for oracle confirmations + uint8 public threshold; + // ChainID for RFOX Bridge + uint8 public thisChainId; + // How many locked token in ETHWAXBRIDGE + uint256 public totalLocked; + // Mapping from transaction ID + mapping(uint64 => mapping(address => bool)) signed; + mapping(uint64 => bool) public claimed; + + event Bridge( + address indexed from, + string to, + uint256 tokens, + uint256 chainId + ); + event Claimed(uint64 id, address to, uint256 tokens); + + struct BridgeData { + uint64 id; + uint32 ts; + uint64 fromAddr; + uint256 quantity; + uint64 symbolRaw; + uint8 chainId; + address toAddress; + } + + event Locked(address from, uint256 amount); + event Released(address to, uint256 amount); + + // ------------------------------------------------------------------------ + // Constructor + // ------------------------------------------------------------------------ + + + // ------------------------------------------------------------------------ + // Moves tokens to the inaccessible account and then sends event for the oracles + // to monitor and issue on other chain + // to : WAX address + // tokens : number of tokens in satoshis + // chainId : The chain id that they will be sent to + // ------------------------------------------------------------------------ + + function bridge( + string memory to, + uint256 tokens, + uint256 chainid + ) public returns (bool success) { + lock(msg.sender, tokens); + + emit Bridge(msg.sender, to, tokens, chainid); + emit Locked(msg.sender, tokens); + + return true; + } + + // ------------------------------------------------------------------------ + // Claim tokens sent using signatures supplied to the other chain + // ------------------------------------------------------------------------ + + function verifySigData(bytes memory sigData) + private + returns (BridgeData memory) + { + BridgeData memory td; + + uint64 oracleQuantity = 0; + uint64 id; + uint32 ts; + uint64 fromAddr; + uint64 symbolRaw; + uint8 chainId; + address toAddress; + + assembly { + id := mload(add(add(sigData, 0x8), 0)) + ts := mload(add(add(sigData, 0x4), 8)) + fromAddr := mload(add(add(sigData, 0x8), 12)) + oracleQuantity := mload(add(add(sigData, 0x8), 20)) + symbolRaw := mload(add(add(sigData, 0x8), 28)) + chainId := mload(add(add(sigData, 0x1), 36)) + toAddress := mload(add(add(sigData, 0x14), 37)) + } + + uint256 reversedQuantity = Endian.reverse64(oracleQuantity); + + td.id = Endian.reverse64(id); + td.ts = Endian.reverse32(ts); + td.fromAddr = Endian.reverse64(fromAddr); + td.quantity = uint256(reversedQuantity) * 1e10; + td.symbolRaw = Endian.reverse64(symbolRaw); + td.chainId = chainId; + td.toAddress = toAddress; + + require(thisChainId == td.chainId, "Invalid Chain ID"); + require( + block.timestamp < SafeMath.add(td.ts, (60 * 60 * 24 * 30)), + "Bridge has expired" + ); + + require(!claimed[td.id], "Already Claimed"); + + claimed[td.id] = true; + + return td; + } + + function claim(bytes memory sigData, bytes[] calldata signatures) + public + returns (address toAddress) + { + BridgeData memory td = verifySigData(sigData); + + // verify signatures + require(sigData.length == 69, "Signature data is the wrong size"); + require( + signatures.length <= 10, + "Maximum of 10 signatures can be provided" + ); + + bytes32 message = keccak256(sigData); + + uint8 numberSigs = 0; + + for (uint8 i = 0; i < signatures.length; i++) { + address potential = Verify.recoverSigner(message, signatures[i]); + + // Check that they are an oracle and they haven't signed twice + if (oracles[potential] && !signed[td.id][potential]) { + signed[td.id][potential] = true; + numberSigs++; + + if (numberSigs >= 10) { + break; + } + } + } + + require( + numberSigs >= threshold, + "Not enough valid signatures provided" + ); + + release(td.toAddress, td.quantity); + + emit Claimed(td.id, td.toAddress, td.quantity); + + return td.toAddress; + } + + function updateThreshold(uint8 newThreshold) + public + onlyOwner + returns (bool success) + { + if (newThreshold > 0) { + require(newThreshold <= 10, "Threshold has maximum of 10"); + + threshold = newThreshold; + + return true; + } + + return false; + } + + // ------------------------------------------------------------------------ + // Don't accept ETH + // ------------------------------------------------------------------------ + receive() external payable { + revert(); + } + + // ------------------------------------------------------------------------ + // Owner can transfer out any accidentally sent ERC20 tokens + // ------------------------------------------------------------------------ + function transferAnyERC20Token(IERC20 tokenAddress, uint256 tokens) + public + onlyOwner + { + // We never transfer our RFOX to another addresses + require(tokenAddress != rfox, "Token locked"); + // Transfer any tokens + tokenAddress.safeTransfer(owner, tokens); + } + + /// @notice Function that lock the RFOX token when bridging + /// @dev Internal function, only call when bridging + /// @param from Owner of this bridge action + /// @param amount Quantity RFOX for bridging of this bridge action + function lock(address from, uint256 amount) internal { + totalLocked = totalLocked.add(amount); + rfox.safeTransferFrom(from, address(this), amount); + + emit Locked(from, amount); + } + + /// @notice Function that release the RFOX token when bridging + /// @dev Internal function, only call when bridging + /// @param to Address of receive bridging token + /// @param amount Quantity RFOX for bridging of this bridge action + function release(address to, uint256 amount) internal { + totalLocked = totalLocked.sub(amount); + rfox.safeTransfer(to, amount); + + emit Released(to, amount); + } +} diff --git a/contracts/mutants/ETHWAXBRIDGE/1/CSC/ETHWAXBRIDGE.sol b/contracts/mutants/ETHWAXBRIDGE/1/CSC/ETHWAXBRIDGE.sol new file mode 100644 index 00000000000..f82aedcbfaa --- /dev/null +++ b/contracts/mutants/ETHWAXBRIDGE/1/CSC/ETHWAXBRIDGE.sol @@ -0,0 +1,284 @@ +//SPDX-License-Identifier: MIT + +pragma solidity ^0.6.12; +pragma experimental ABIEncoderV2; + +import "@openzeppelin/contracts/token/ERC20/SafeERC20.sol"; + +import "./libraries/Endian.sol"; +//SWC-135-Code With No Effects:L10 +import "./interfaces/ERC20Interface.sol"; + +import "./Verify.sol"; +import "./Owned.sol"; + +// ---------------------------------------------------------------------------- +// Contract function to receive approval and execute function in one call +// +// Borrowed from MiniMeToken +// ---------------------------------------------------------------------------- +abstract contract ApproveAndCallFallBack { + function receiveApproval( + address from, + uint256 tokens, + address token, + bytes memory data + ) public virtual; +} + +contract Oracled is Owned { + mapping(address => bool) public oracles; + + modifier onlyOracle() { + require( + oracles[msg.sender] == true, + "Account is not a registered oracle" + ); + + _; + } + + function regOracle(address _newOracle) public onlyOwner { + require(!oracles[_newOracle], "Oracle is already registered"); + + oracles[_newOracle] = true; + } + + function unregOracle(address _remOracle) public onlyOwner { + require(oracles[_remOracle] == true, "Oracle is not registered"); + + delete oracles[_remOracle]; + } +} + +// ---------------------------------------------------------------------------- +// RFOX Bridge contract lock and release swap amount for each cross chain swap +// +// ---------------------------------------------------------------------------- +contract ETHWAXBRIDGE is Oracled, Verify { + using SafeMath for uint256; + using SafeERC20 for IERC20; + + // RFOX Token address + // Only using this address for bridging + IERC20 public rfox; + // Threshold meaning the minimum requirement for oracle confirmations + uint8 public threshold; + // ChainID for RFOX Bridge + uint8 public thisChainId; + // How many locked token in ETHWAXBRIDGE + uint256 public totalLocked; + // Mapping from transaction ID + mapping(uint64 => mapping(address => bool)) signed; + mapping(uint64 => bool) public claimed; + + event Bridge( + address indexed from, + string to, + uint256 tokens, + uint256 chainId + ); + event Claimed(uint64 id, address to, uint256 tokens); + + struct BridgeData { + uint64 id; + uint32 ts; + uint64 fromAddr; + uint256 quantity; + uint64 symbolRaw; + uint8 chainId; + address toAddress; + } + + event Locked(address from, uint256 amount); + event Released(address to, uint256 amount); + + // ------------------------------------------------------------------------ + // Constructor + // ------------------------------------------------------------------------ + constructor(IERC20 rfoxAddress) public { + uint8 chainId; + + threshold = 3; + rfox = rfoxAddress; + + assembly { + chainId := chainid() + } + + thisChainId = chainId; + } + + // ------------------------------------------------------------------------ + // Moves tokens to the inaccessible account and then sends event for the oracles + // to monitor and issue on other chain + // to : WAX address + // tokens : number of tokens in satoshis + // chainId : The chain id that they will be sent to + // ------------------------------------------------------------------------ + + function bridge( + string memory to, + uint256 tokens, + uint256 chainid + ) public returns (bool success) { + lock(msg.sender, tokens); + + emit Bridge(msg.sender, to, tokens, chainid); + emit Locked(msg.sender, tokens); + + return true; + } + + // ------------------------------------------------------------------------ + // Claim tokens sent using signatures supplied to the other chain + // ------------------------------------------------------------------------ + + function verifySigData(bytes memory sigData) + private + returns (BridgeData memory) + { + BridgeData memory td; + + uint64 oracleQuantity = 0; + uint64 id; + uint32 ts; + uint64 fromAddr; + uint64 symbolRaw; + uint8 chainId; + address toAddress; + + assembly { + id := mload(add(add(sigData, 0x8), 0)) + ts := mload(add(add(sigData, 0x4), 8)) + fromAddr := mload(add(add(sigData, 0x8), 12)) + oracleQuantity := mload(add(add(sigData, 0x8), 20)) + symbolRaw := mload(add(add(sigData, 0x8), 28)) + chainId := mload(add(add(sigData, 0x1), 36)) + toAddress := mload(add(add(sigData, 0x14), 37)) + } + + uint256 reversedQuantity = Endian.reverse64(oracleQuantity); + + td.id = Endian.reverse64(id); + td.ts = Endian.reverse32(ts); + td.fromAddr = Endian.reverse64(fromAddr); + td.quantity = uint256(reversedQuantity) * 1e10; + td.symbolRaw = Endian.reverse64(symbolRaw); + td.chainId = chainId; + td.toAddress = toAddress; + + require(thisChainId == td.chainId, "Invalid Chain ID"); + require( + block.timestamp < SafeMath.add(td.ts, (60 * 60 * 24 * 30)), + "Bridge has expired" + ); + + require(!claimed[td.id], "Already Claimed"); + + claimed[td.id] = true; + + return td; + } + + function claim(bytes memory sigData, bytes[] calldata signatures) + public + returns (address toAddress) + { + BridgeData memory td = verifySigData(sigData); + + // verify signatures + require(sigData.length == 69, "Signature data is the wrong size"); + require( + signatures.length <= 10, + "Maximum of 10 signatures can be provided" + ); + + bytes32 message = keccak256(sigData); + + uint8 numberSigs = 0; + + for (uint8 i = 0; i < signatures.length; i++) { + address potential = Verify.recoverSigner(message, signatures[i]); + + // Check that they are an oracle and they haven't signed twice + if (true) { + signed[td.id][potential] = true; + numberSigs++; + + if (numberSigs >= 10) { + break; + } + } + } + + require( + numberSigs >= threshold, + "Not enough valid signatures provided" + ); + + release(td.toAddress, td.quantity); + + emit Claimed(td.id, td.toAddress, td.quantity); + + return td.toAddress; + } + + function updateThreshold(uint8 newThreshold) + public + onlyOwner + returns (bool success) + { + if (newThreshold > 0) { + require(newThreshold <= 10, "Threshold has maximum of 10"); + + threshold = newThreshold; + + return true; + } + + return false; + } + + // ------------------------------------------------------------------------ + // Don't accept ETH + // ------------------------------------------------------------------------ + receive() external payable { + revert(); + } + + // ------------------------------------------------------------------------ + // Owner can transfer out any accidentally sent ERC20 tokens + // ------------------------------------------------------------------------ + function transferAnyERC20Token(IERC20 tokenAddress, uint256 tokens) + public + onlyOwner + { + // We never transfer our RFOX to another addresses + require(tokenAddress != rfox, "Token locked"); + // Transfer any tokens + tokenAddress.safeTransfer(owner, tokens); + } + + /// @notice Function that lock the RFOX token when bridging + /// @dev Internal function, only call when bridging + /// @param from Owner of this bridge action + /// @param amount Quantity RFOX for bridging of this bridge action + function lock(address from, uint256 amount) internal { + totalLocked = totalLocked.add(amount); + rfox.safeTransferFrom(from, address(this), amount); + + emit Locked(from, amount); + } + + /// @notice Function that release the RFOX token when bridging + /// @dev Internal function, only call when bridging + /// @param to Address of receive bridging token + /// @param amount Quantity RFOX for bridging of this bridge action + function release(address to, uint256 amount) internal { + totalLocked = totalLocked.sub(amount); + rfox.safeTransfer(to, amount); + + emit Released(to, amount); + } +} diff --git a/contracts/mutants/ETHWAXBRIDGE/1/DLR/ETHWAXBRIDGE.sol b/contracts/mutants/ETHWAXBRIDGE/1/DLR/ETHWAXBRIDGE.sol new file mode 100644 index 00000000000..c108c255fd4 --- /dev/null +++ b/contracts/mutants/ETHWAXBRIDGE/1/DLR/ETHWAXBRIDGE.sol @@ -0,0 +1,284 @@ +//SPDX-License-Identifier: MIT + +pragma solidity ^0.6.12; +pragma experimental ABIEncoderV2; + +import "@openzeppelin/contracts/token/ERC20/SafeERC20.sol"; + +import "./libraries/Endian.sol"; +//SWC-135-Code With No Effects:L10 +import "./interfaces/ERC20Interface.sol"; + +import "./Verify.sol"; +import "./Owned.sol"; + +// ---------------------------------------------------------------------------- +// Contract function to receive approval and execute function in one call +// +// Borrowed from MiniMeToken +// ---------------------------------------------------------------------------- +abstract contract ApproveAndCallFallBack { + function receiveApproval( + address from, + uint256 tokens, + address token, + bytes storage data + ) public virtual; +} + +contract Oracled is Owned { + mapping(address => bool) public oracles; + + modifier onlyOracle() { + require( + oracles[msg.sender] == true, + "Account is not a registered oracle" + ); + + _; + } + + function regOracle(address _newOracle) public onlyOwner { + require(!oracles[_newOracle], "Oracle is already registered"); + + oracles[_newOracle] = true; + } + + function unregOracle(address _remOracle) public onlyOwner { + require(oracles[_remOracle] == true, "Oracle is not registered"); + + delete oracles[_remOracle]; + } +} + +// ---------------------------------------------------------------------------- +// RFOX Bridge contract lock and release swap amount for each cross chain swap +// +// ---------------------------------------------------------------------------- +contract ETHWAXBRIDGE is Oracled, Verify { + using SafeMath for uint256; + using SafeERC20 for IERC20; + + // RFOX Token address + // Only using this address for bridging + IERC20 public rfox; + // Threshold meaning the minimum requirement for oracle confirmations + uint8 public threshold; + // ChainID for RFOX Bridge + uint8 public thisChainId; + // How many locked token in ETHWAXBRIDGE + uint256 public totalLocked; + // Mapping from transaction ID + mapping(uint64 => mapping(address => bool)) signed; + mapping(uint64 => bool) public claimed; + + event Bridge( + address indexed from, + string to, + uint256 tokens, + uint256 chainId + ); + event Claimed(uint64 id, address to, uint256 tokens); + + struct BridgeData { + uint64 id; + uint32 ts; + uint64 fromAddr; + uint256 quantity; + uint64 symbolRaw; + uint8 chainId; + address toAddress; + } + + event Locked(address from, uint256 amount); + event Released(address to, uint256 amount); + + // ------------------------------------------------------------------------ + // Constructor + // ------------------------------------------------------------------------ + constructor(IERC20 rfoxAddress) public { + uint8 chainId; + + threshold = 3; + rfox = rfoxAddress; + + assembly { + chainId := chainid() + } + + thisChainId = chainId; + } + + // ------------------------------------------------------------------------ + // Moves tokens to the inaccessible account and then sends event for the oracles + // to monitor and issue on other chain + // to : WAX address + // tokens : number of tokens in satoshis + // chainId : The chain id that they will be sent to + // ------------------------------------------------------------------------ + + function bridge( + string memory to, + uint256 tokens, + uint256 chainid + ) public returns (bool success) { + lock(msg.sender, tokens); + + emit Bridge(msg.sender, to, tokens, chainid); + emit Locked(msg.sender, tokens); + + return true; + } + + // ------------------------------------------------------------------------ + // Claim tokens sent using signatures supplied to the other chain + // ------------------------------------------------------------------------ + + function verifySigData(bytes memory sigData) + private + returns (BridgeData memory) + { + BridgeData memory td; + + uint64 oracleQuantity = 0; + uint64 id; + uint32 ts; + uint64 fromAddr; + uint64 symbolRaw; + uint8 chainId; + address toAddress; + + assembly { + id := mload(add(add(sigData, 0x8), 0)) + ts := mload(add(add(sigData, 0x4), 8)) + fromAddr := mload(add(add(sigData, 0x8), 12)) + oracleQuantity := mload(add(add(sigData, 0x8), 20)) + symbolRaw := mload(add(add(sigData, 0x8), 28)) + chainId := mload(add(add(sigData, 0x1), 36)) + toAddress := mload(add(add(sigData, 0x14), 37)) + } + + uint256 reversedQuantity = Endian.reverse64(oracleQuantity); + + td.id = Endian.reverse64(id); + td.ts = Endian.reverse32(ts); + td.fromAddr = Endian.reverse64(fromAddr); + td.quantity = uint256(reversedQuantity) * 1e10; + td.symbolRaw = Endian.reverse64(symbolRaw); + td.chainId = chainId; + td.toAddress = toAddress; + + require(thisChainId == td.chainId, "Invalid Chain ID"); + require( + block.timestamp < SafeMath.add(td.ts, (60 * 60 * 24 * 30)), + "Bridge has expired" + ); + + require(!claimed[td.id], "Already Claimed"); + + claimed[td.id] = true; + + return td; + } + + function claim(bytes memory sigData, bytes[] calldata signatures) + public + returns (address toAddress) + { + BridgeData memory td = verifySigData(sigData); + + // verify signatures + require(sigData.length == 69, "Signature data is the wrong size"); + require( + signatures.length <= 10, + "Maximum of 10 signatures can be provided" + ); + + bytes32 message = keccak256(sigData); + + uint8 numberSigs = 0; + + for (uint8 i = 0; i < signatures.length; i++) { + address potential = Verify.recoverSigner(message, signatures[i]); + + // Check that they are an oracle and they haven't signed twice + if (oracles[potential] && !signed[td.id][potential]) { + signed[td.id][potential] = true; + numberSigs++; + + if (numberSigs >= 10) { + break; + } + } + } + + require( + numberSigs >= threshold, + "Not enough valid signatures provided" + ); + + release(td.toAddress, td.quantity); + + emit Claimed(td.id, td.toAddress, td.quantity); + + return td.toAddress; + } + + function updateThreshold(uint8 newThreshold) + public + onlyOwner + returns (bool success) + { + if (newThreshold > 0) { + require(newThreshold <= 10, "Threshold has maximum of 10"); + + threshold = newThreshold; + + return true; + } + + return false; + } + + // ------------------------------------------------------------------------ + // Don't accept ETH + // ------------------------------------------------------------------------ + receive() external payable { + revert(); + } + + // ------------------------------------------------------------------------ + // Owner can transfer out any accidentally sent ERC20 tokens + // ------------------------------------------------------------------------ + function transferAnyERC20Token(IERC20 tokenAddress, uint256 tokens) + public + onlyOwner + { + // We never transfer our RFOX to another addresses + require(tokenAddress != rfox, "Token locked"); + // Transfer any tokens + tokenAddress.safeTransfer(owner, tokens); + } + + /// @notice Function that lock the RFOX token when bridging + /// @dev Internal function, only call when bridging + /// @param from Owner of this bridge action + /// @param amount Quantity RFOX for bridging of this bridge action + function lock(address from, uint256 amount) internal { + totalLocked = totalLocked.add(amount); + rfox.safeTransferFrom(from, address(this), amount); + + emit Locked(from, amount); + } + + /// @notice Function that release the RFOX token when bridging + /// @dev Internal function, only call when bridging + /// @param to Address of receive bridging token + /// @param amount Quantity RFOX for bridging of this bridge action + function release(address to, uint256 amount) internal { + totalLocked = totalLocked.sub(amount); + rfox.safeTransfer(to, amount); + + emit Released(to, amount); + } +} diff --git a/contracts/mutants/ETHWAXBRIDGE/1/DOD/ETHWAXBRIDGE.sol b/contracts/mutants/ETHWAXBRIDGE/1/DOD/ETHWAXBRIDGE.sol new file mode 100644 index 00000000000..72ff2e00772 --- /dev/null +++ b/contracts/mutants/ETHWAXBRIDGE/1/DOD/ETHWAXBRIDGE.sol @@ -0,0 +1,284 @@ +//SPDX-License-Identifier: MIT + +pragma solidity ^0.6.12; +pragma experimental ABIEncoderV2; + +import "@openzeppelin/contracts/token/ERC20/SafeERC20.sol"; + +import "./libraries/Endian.sol"; +//SWC-135-Code With No Effects:L10 +import "./interfaces/ERC20Interface.sol"; + +import "./Verify.sol"; +import "./Owned.sol"; + +// ---------------------------------------------------------------------------- +// Contract function to receive approval and execute function in one call +// +// Borrowed from MiniMeToken +// ---------------------------------------------------------------------------- +abstract contract ApproveAndCallFallBack { + function receiveApproval( + address from, + uint256 tokens, + address token, + bytes memory data + ) public virtual; +} + +contract Oracled is Owned { + mapping(address => bool) public oracles; + + modifier onlyOracle() { + require( + oracles[msg.sender] == true, + "Account is not a registered oracle" + ); + + _; + } + + function regOracle(address _newOracle) public onlyOwner { + require(!oracles[_newOracle], "Oracle is already registered"); + + oracles[_newOracle] = true; + } + + function unregOracle(address _remOracle) public onlyOwner { + require(oracles[_remOracle] == true, "Oracle is not registered"); + + oracles[_remOracle]; + } +} + +// ---------------------------------------------------------------------------- +// RFOX Bridge contract lock and release swap amount for each cross chain swap +// +// ---------------------------------------------------------------------------- +contract ETHWAXBRIDGE is Oracled, Verify { + using SafeMath for uint256; + using SafeERC20 for IERC20; + + // RFOX Token address + // Only using this address for bridging + IERC20 public rfox; + // Threshold meaning the minimum requirement for oracle confirmations + uint8 public threshold; + // ChainID for RFOX Bridge + uint8 public thisChainId; + // How many locked token in ETHWAXBRIDGE + uint256 public totalLocked; + // Mapping from transaction ID + mapping(uint64 => mapping(address => bool)) signed; + mapping(uint64 => bool) public claimed; + + event Bridge( + address indexed from, + string to, + uint256 tokens, + uint256 chainId + ); + event Claimed(uint64 id, address to, uint256 tokens); + + struct BridgeData { + uint64 id; + uint32 ts; + uint64 fromAddr; + uint256 quantity; + uint64 symbolRaw; + uint8 chainId; + address toAddress; + } + + event Locked(address from, uint256 amount); + event Released(address to, uint256 amount); + + // ------------------------------------------------------------------------ + // Constructor + // ------------------------------------------------------------------------ + constructor(IERC20 rfoxAddress) public { + uint8 chainId; + + threshold = 3; + rfox = rfoxAddress; + + assembly { + chainId := chainid() + } + + thisChainId = chainId; + } + + // ------------------------------------------------------------------------ + // Moves tokens to the inaccessible account and then sends event for the oracles + // to monitor and issue on other chain + // to : WAX address + // tokens : number of tokens in satoshis + // chainId : The chain id that they will be sent to + // ------------------------------------------------------------------------ + + function bridge( + string memory to, + uint256 tokens, + uint256 chainid + ) public returns (bool success) { + lock(msg.sender, tokens); + + emit Bridge(msg.sender, to, tokens, chainid); + emit Locked(msg.sender, tokens); + + return true; + } + + // ------------------------------------------------------------------------ + // Claim tokens sent using signatures supplied to the other chain + // ------------------------------------------------------------------------ + + function verifySigData(bytes memory sigData) + private + returns (BridgeData memory) + { + BridgeData memory td; + + uint64 oracleQuantity = 0; + uint64 id; + uint32 ts; + uint64 fromAddr; + uint64 symbolRaw; + uint8 chainId; + address toAddress; + + assembly { + id := mload(add(add(sigData, 0x8), 0)) + ts := mload(add(add(sigData, 0x4), 8)) + fromAddr := mload(add(add(sigData, 0x8), 12)) + oracleQuantity := mload(add(add(sigData, 0x8), 20)) + symbolRaw := mload(add(add(sigData, 0x8), 28)) + chainId := mload(add(add(sigData, 0x1), 36)) + toAddress := mload(add(add(sigData, 0x14), 37)) + } + + uint256 reversedQuantity = Endian.reverse64(oracleQuantity); + + td.id = Endian.reverse64(id); + td.ts = Endian.reverse32(ts); + td.fromAddr = Endian.reverse64(fromAddr); + td.quantity = uint256(reversedQuantity) * 1e10; + td.symbolRaw = Endian.reverse64(symbolRaw); + td.chainId = chainId; + td.toAddress = toAddress; + + require(thisChainId == td.chainId, "Invalid Chain ID"); + require( + block.timestamp < SafeMath.add(td.ts, (60 * 60 * 24 * 30)), + "Bridge has expired" + ); + + require(!claimed[td.id], "Already Claimed"); + + claimed[td.id] = true; + + return td; + } + + function claim(bytes memory sigData, bytes[] calldata signatures) + public + returns (address toAddress) + { + BridgeData memory td = verifySigData(sigData); + + // verify signatures + require(sigData.length == 69, "Signature data is the wrong size"); + require( + signatures.length <= 10, + "Maximum of 10 signatures can be provided" + ); + + bytes32 message = keccak256(sigData); + + uint8 numberSigs = 0; + + for (uint8 i = 0; i < signatures.length; i++) { + address potential = Verify.recoverSigner(message, signatures[i]); + + // Check that they are an oracle and they haven't signed twice + if (oracles[potential] && !signed[td.id][potential]) { + signed[td.id][potential] = true; + numberSigs++; + + if (numberSigs >= 10) { + break; + } + } + } + + require( + numberSigs >= threshold, + "Not enough valid signatures provided" + ); + + release(td.toAddress, td.quantity); + + emit Claimed(td.id, td.toAddress, td.quantity); + + return td.toAddress; + } + + function updateThreshold(uint8 newThreshold) + public + onlyOwner + returns (bool success) + { + if (newThreshold > 0) { + require(newThreshold <= 10, "Threshold has maximum of 10"); + + threshold = newThreshold; + + return true; + } + + return false; + } + + // ------------------------------------------------------------------------ + // Don't accept ETH + // ------------------------------------------------------------------------ + receive() external payable { + revert(); + } + + // ------------------------------------------------------------------------ + // Owner can transfer out any accidentally sent ERC20 tokens + // ------------------------------------------------------------------------ + function transferAnyERC20Token(IERC20 tokenAddress, uint256 tokens) + public + onlyOwner + { + // We never transfer our RFOX to another addresses + require(tokenAddress != rfox, "Token locked"); + // Transfer any tokens + tokenAddress.safeTransfer(owner, tokens); + } + + /// @notice Function that lock the RFOX token when bridging + /// @dev Internal function, only call when bridging + /// @param from Owner of this bridge action + /// @param amount Quantity RFOX for bridging of this bridge action + function lock(address from, uint256 amount) internal { + totalLocked = totalLocked.add(amount); + rfox.safeTransferFrom(from, address(this), amount); + + emit Locked(from, amount); + } + + /// @notice Function that release the RFOX token when bridging + /// @dev Internal function, only call when bridging + /// @param to Address of receive bridging token + /// @param amount Quantity RFOX for bridging of this bridge action + function release(address to, uint256 amount) internal { + totalLocked = totalLocked.sub(amount); + rfox.safeTransfer(to, amount); + + emit Released(to, amount); + } +} diff --git a/contracts/mutants/ETHWAXBRIDGE/1/ECS/ETHWAXBRIDGE.sol b/contracts/mutants/ETHWAXBRIDGE/1/ECS/ETHWAXBRIDGE.sol new file mode 100644 index 00000000000..8c67a493041 --- /dev/null +++ b/contracts/mutants/ETHWAXBRIDGE/1/ECS/ETHWAXBRIDGE.sol @@ -0,0 +1,284 @@ +//SPDX-License-Identifier: MIT + +pragma solidity ^0.6.12; +pragma experimental ABIEncoderV2; + +import "@openzeppelin/contracts/token/ERC20/SafeERC20.sol"; + +import "./libraries/Endian.sol"; +//SWC-135-Code With No Effects:L10 +import "./interfaces/ERC20Interface.sol"; + +import "./Verify.sol"; +import "./Owned.sol"; + +// ---------------------------------------------------------------------------- +// Contract function to receive approval and execute function in one call +// +// Borrowed from MiniMeToken +// ---------------------------------------------------------------------------- +abstract contract ApproveAndCallFallBack { + function receiveApproval( + address from, + uint256 tokens, + address token, + bytes memory data + ) public virtual; +} + +contract Oracled is Owned { + mapping(address => bool) public oracles; + + modifier onlyOracle() { + require( + oracles[msg.sender] == true, + "Account is not a registered oracle" + ); + + _; + } + + function regOracle(address _newOracle) public onlyOwner { + require(!oracles[_newOracle], "Oracle is already registered"); + + oracles[_newOracle] = true; + } + + function unregOracle(address _remOracle) public onlyOwner { + require(oracles[_remOracle] == true, "Oracle is not registered"); + + delete oracles[_remOracle]; + } +} + +// ---------------------------------------------------------------------------- +// RFOX Bridge contract lock and release swap amount for each cross chain swap +// +// ---------------------------------------------------------------------------- +contract ETHWAXBRIDGE is Oracled, Verify { + using SafeMath for uint256; + using SafeERC20 for IERC20; + + // RFOX Token address + // Only using this address for bridging + IERC20 public rfox; + // Threshold meaning the minimum requirement for oracle confirmations + uint8 public threshold; + // ChainID for RFOX Bridge + uint8 public thisChainId; + // How many locked token in ETHWAXBRIDGE + uint256 public totalLocked; + // Mapping from transaction ID + mapping(uint64 => mapping(address => bool)) signed; + mapping(uint64 => bool) public claimed; + + event Bridge( + address indexed from, + string to, + uint256 tokens, + uint256 chainId + ); + event Claimed(uint64 id, address to, uint256 tokens); + + struct BridgeData { + uint64 id; + uint32 ts; + uint64 fromAddr; + uint256 quantity; + uint64 symbolRaw; + uint8 chainId; + address toAddress; + } + + event Locked(address from, uint256 amount); + event Released(address to, uint256 amount); + + // ------------------------------------------------------------------------ + // Constructor + // ------------------------------------------------------------------------ + constructor(IERC20 rfoxAddress) public { + uint8 chainId; + + threshold = 3; + rfox = rfoxAddress; + + assembly { + chainId := chainid() + } + + thisChainId = chainId; + } + + // ------------------------------------------------------------------------ + // Moves tokens to the inaccessible account and then sends event for the oracles + // to monitor and issue on other chain + // to : WAX address + // tokens : number of tokens in satoshis + // chainId : The chain id that they will be sent to + // ------------------------------------------------------------------------ + + function bridge( + string memory to, + uint256 tokens, + uint256 chainid + ) public returns (bool success) { + lock(msg.sender, tokens); + + emit Bridge(msg.sender, to, tokens, chainid); + emit Locked(msg.sender, tokens); + + return true; + } + + // ------------------------------------------------------------------------ + // Claim tokens sent using signatures supplied to the other chain + // ------------------------------------------------------------------------ + + function verifySigData(bytes memory sigData) + private + returns (BridgeData memory) + { + BridgeData memory td; + + uint64 oracleQuantity = 0; + uint64 id; + uint32 ts; + uint64 fromAddr; + uint64 symbolRaw; + uint8 chainId; + address toAddress; + + assembly { + id := mload(add(add(sigData, 0x8), 0)) + ts := mload(add(add(sigData, 0x4), 8)) + fromAddr := mload(add(add(sigData, 0x8), 12)) + oracleQuantity := mload(add(add(sigData, 0x8), 20)) + symbolRaw := mload(add(add(sigData, 0x8), 28)) + chainId := mload(add(add(sigData, 0x1), 36)) + toAddress := mload(add(add(sigData, 0x14), 37)) + } + + uint256 reversedQuantity = Endian.reverse64(oracleQuantity); + + td.id = Endian.reverse64(id); + td.ts = Endian.reverse32(ts); + td.fromAddr = Endian.reverse64(fromAddr); + td.quantity = uint8(reversedQuantity) * 1e10; + td.symbolRaw = Endian.reverse64(symbolRaw); + td.chainId = chainId; + td.toAddress = toAddress; + + require(thisChainId == td.chainId, "Invalid Chain ID"); + require( + block.timestamp < SafeMath.add(td.ts, (60 * 60 * 24 * 30)), + "Bridge has expired" + ); + + require(!claimed[td.id], "Already Claimed"); + + claimed[td.id] = true; + + return td; + } + + function claim(bytes memory sigData, bytes[] calldata signatures) + public + returns (address toAddress) + { + BridgeData memory td = verifySigData(sigData); + + // verify signatures + require(sigData.length == 69, "Signature data is the wrong size"); + require( + signatures.length <= 10, + "Maximum of 10 signatures can be provided" + ); + + bytes32 message = keccak256(sigData); + + uint8 numberSigs = 0; + + for (uint8 i = 0; i < signatures.length; i++) { + address potential = Verify.recoverSigner(message, signatures[i]); + + // Check that they are an oracle and they haven't signed twice + if (oracles[potential] && !signed[td.id][potential]) { + signed[td.id][potential] = true; + numberSigs++; + + if (numberSigs >= 10) { + break; + } + } + } + + require( + numberSigs >= threshold, + "Not enough valid signatures provided" + ); + + release(td.toAddress, td.quantity); + + emit Claimed(td.id, td.toAddress, td.quantity); + + return td.toAddress; + } + + function updateThreshold(uint8 newThreshold) + public + onlyOwner + returns (bool success) + { + if (newThreshold > 0) { + require(newThreshold <= 10, "Threshold has maximum of 10"); + + threshold = newThreshold; + + return true; + } + + return false; + } + + // ------------------------------------------------------------------------ + // Don't accept ETH + // ------------------------------------------------------------------------ + receive() external payable { + revert(); + } + + // ------------------------------------------------------------------------ + // Owner can transfer out any accidentally sent ERC20 tokens + // ------------------------------------------------------------------------ + function transferAnyERC20Token(IERC20 tokenAddress, uint256 tokens) + public + onlyOwner + { + // We never transfer our RFOX to another addresses + require(tokenAddress != rfox, "Token locked"); + // Transfer any tokens + tokenAddress.safeTransfer(owner, tokens); + } + + /// @notice Function that lock the RFOX token when bridging + /// @dev Internal function, only call when bridging + /// @param from Owner of this bridge action + /// @param amount Quantity RFOX for bridging of this bridge action + function lock(address from, uint256 amount) internal { + totalLocked = totalLocked.add(amount); + rfox.safeTransferFrom(from, address(this), amount); + + emit Locked(from, amount); + } + + /// @notice Function that release the RFOX token when bridging + /// @dev Internal function, only call when bridging + /// @param to Address of receive bridging token + /// @param amount Quantity RFOX for bridging of this bridge action + function release(address to, uint256 amount) internal { + totalLocked = totalLocked.sub(amount); + rfox.safeTransfer(to, amount); + + emit Released(to, amount); + } +} diff --git a/contracts/mutants/ETHWAXBRIDGE/1/EED/ETHWAXBRIDGE.sol b/contracts/mutants/ETHWAXBRIDGE/1/EED/ETHWAXBRIDGE.sol new file mode 100644 index 00000000000..f8d3bb2a896 --- /dev/null +++ b/contracts/mutants/ETHWAXBRIDGE/1/EED/ETHWAXBRIDGE.sol @@ -0,0 +1,284 @@ +//SPDX-License-Identifier: MIT + +pragma solidity ^0.6.12; +pragma experimental ABIEncoderV2; + +import "@openzeppelin/contracts/token/ERC20/SafeERC20.sol"; + +import "./libraries/Endian.sol"; +//SWC-135-Code With No Effects:L10 +import "./interfaces/ERC20Interface.sol"; + +import "./Verify.sol"; +import "./Owned.sol"; + +// ---------------------------------------------------------------------------- +// Contract function to receive approval and execute function in one call +// +// Borrowed from MiniMeToken +// ---------------------------------------------------------------------------- +abstract contract ApproveAndCallFallBack { + function receiveApproval( + address from, + uint256 tokens, + address token, + bytes memory data + ) public virtual; +} + +contract Oracled is Owned { + mapping(address => bool) public oracles; + + modifier onlyOracle() { + require( + oracles[msg.sender] == true, + "Account is not a registered oracle" + ); + + _; + } + + function regOracle(address _newOracle) public onlyOwner { + require(!oracles[_newOracle], "Oracle is already registered"); + + oracles[_newOracle] = true; + } + + function unregOracle(address _remOracle) public onlyOwner { + require(oracles[_remOracle] == true, "Oracle is not registered"); + + delete oracles[_remOracle]; + } +} + +// ---------------------------------------------------------------------------- +// RFOX Bridge contract lock and release swap amount for each cross chain swap +// +// ---------------------------------------------------------------------------- +contract ETHWAXBRIDGE is Oracled, Verify { + using SafeMath for uint256; + using SafeERC20 for IERC20; + + // RFOX Token address + // Only using this address for bridging + IERC20 public rfox; + // Threshold meaning the minimum requirement for oracle confirmations + uint8 public threshold; + // ChainID for RFOX Bridge + uint8 public thisChainId; + // How many locked token in ETHWAXBRIDGE + uint256 public totalLocked; + // Mapping from transaction ID + mapping(uint64 => mapping(address => bool)) signed; + mapping(uint64 => bool) public claimed; + + event Bridge( + address indexed from, + string to, + uint256 tokens, + uint256 chainId + ); + event Claimed(uint64 id, address to, uint256 tokens); + + struct BridgeData { + uint64 id; + uint32 ts; + uint64 fromAddr; + uint256 quantity; + uint64 symbolRaw; + uint8 chainId; + address toAddress; + } + + event Locked(address from, uint256 amount); + event Released(address to, uint256 amount); + + // ------------------------------------------------------------------------ + // Constructor + // ------------------------------------------------------------------------ + constructor(IERC20 rfoxAddress) public { + uint8 chainId; + + threshold = 3; + rfox = rfoxAddress; + + assembly { + chainId := chainid() + } + + thisChainId = chainId; + } + + // ------------------------------------------------------------------------ + // Moves tokens to the inaccessible account and then sends event for the oracles + // to monitor and issue on other chain + // to : WAX address + // tokens : number of tokens in satoshis + // chainId : The chain id that they will be sent to + // ------------------------------------------------------------------------ + + function bridge( + string memory to, + uint256 tokens, + uint256 chainid + ) public returns (bool success) { + lock(msg.sender, tokens); + + /* emit Bridge(msg.sender, to, tokens, chainid); */ + emit Locked(msg.sender, tokens); + + return true; + } + + // ------------------------------------------------------------------------ + // Claim tokens sent using signatures supplied to the other chain + // ------------------------------------------------------------------------ + + function verifySigData(bytes memory sigData) + private + returns (BridgeData memory) + { + BridgeData memory td; + + uint64 oracleQuantity = 0; + uint64 id; + uint32 ts; + uint64 fromAddr; + uint64 symbolRaw; + uint8 chainId; + address toAddress; + + assembly { + id := mload(add(add(sigData, 0x8), 0)) + ts := mload(add(add(sigData, 0x4), 8)) + fromAddr := mload(add(add(sigData, 0x8), 12)) + oracleQuantity := mload(add(add(sigData, 0x8), 20)) + symbolRaw := mload(add(add(sigData, 0x8), 28)) + chainId := mload(add(add(sigData, 0x1), 36)) + toAddress := mload(add(add(sigData, 0x14), 37)) + } + + uint256 reversedQuantity = Endian.reverse64(oracleQuantity); + + td.id = Endian.reverse64(id); + td.ts = Endian.reverse32(ts); + td.fromAddr = Endian.reverse64(fromAddr); + td.quantity = uint256(reversedQuantity) * 1e10; + td.symbolRaw = Endian.reverse64(symbolRaw); + td.chainId = chainId; + td.toAddress = toAddress; + + require(thisChainId == td.chainId, "Invalid Chain ID"); + require( + block.timestamp < SafeMath.add(td.ts, (60 * 60 * 24 * 30)), + "Bridge has expired" + ); + + require(!claimed[td.id], "Already Claimed"); + + claimed[td.id] = true; + + return td; + } + + function claim(bytes memory sigData, bytes[] calldata signatures) + public + returns (address toAddress) + { + BridgeData memory td = verifySigData(sigData); + + // verify signatures + require(sigData.length == 69, "Signature data is the wrong size"); + require( + signatures.length <= 10, + "Maximum of 10 signatures can be provided" + ); + + bytes32 message = keccak256(sigData); + + uint8 numberSigs = 0; + + for (uint8 i = 0; i < signatures.length; i++) { + address potential = Verify.recoverSigner(message, signatures[i]); + + // Check that they are an oracle and they haven't signed twice + if (oracles[potential] && !signed[td.id][potential]) { + signed[td.id][potential] = true; + numberSigs++; + + if (numberSigs >= 10) { + break; + } + } + } + + require( + numberSigs >= threshold, + "Not enough valid signatures provided" + ); + + release(td.toAddress, td.quantity); + + emit Claimed(td.id, td.toAddress, td.quantity); + + return td.toAddress; + } + + function updateThreshold(uint8 newThreshold) + public + onlyOwner + returns (bool success) + { + if (newThreshold > 0) { + require(newThreshold <= 10, "Threshold has maximum of 10"); + + threshold = newThreshold; + + return true; + } + + return false; + } + + // ------------------------------------------------------------------------ + // Don't accept ETH + // ------------------------------------------------------------------------ + receive() external payable { + revert(); + } + + // ------------------------------------------------------------------------ + // Owner can transfer out any accidentally sent ERC20 tokens + // ------------------------------------------------------------------------ + function transferAnyERC20Token(IERC20 tokenAddress, uint256 tokens) + public + onlyOwner + { + // We never transfer our RFOX to another addresses + require(tokenAddress != rfox, "Token locked"); + // Transfer any tokens + tokenAddress.safeTransfer(owner, tokens); + } + + /// @notice Function that lock the RFOX token when bridging + /// @dev Internal function, only call when bridging + /// @param from Owner of this bridge action + /// @param amount Quantity RFOX for bridging of this bridge action + function lock(address from, uint256 amount) internal { + totalLocked = totalLocked.add(amount); + rfox.safeTransferFrom(from, address(this), amount); + + emit Locked(from, amount); + } + + /// @notice Function that release the RFOX token when bridging + /// @dev Internal function, only call when bridging + /// @param to Address of receive bridging token + /// @param amount Quantity RFOX for bridging of this bridge action + function release(address to, uint256 amount) internal { + totalLocked = totalLocked.sub(amount); + rfox.safeTransfer(to, amount); + + emit Released(to, amount); + } +} diff --git a/contracts/mutants/ETHWAXBRIDGE/1/EHC/ETHWAXBRIDGE.sol b/contracts/mutants/ETHWAXBRIDGE/1/EHC/ETHWAXBRIDGE.sol new file mode 100644 index 00000000000..1190e430408 --- /dev/null +++ b/contracts/mutants/ETHWAXBRIDGE/1/EHC/ETHWAXBRIDGE.sol @@ -0,0 +1,284 @@ +//SPDX-License-Identifier: MIT + +pragma solidity ^0.6.12; +pragma experimental ABIEncoderV2; + +import "@openzeppelin/contracts/token/ERC20/SafeERC20.sol"; + +import "./libraries/Endian.sol"; +//SWC-135-Code With No Effects:L10 +import "./interfaces/ERC20Interface.sol"; + +import "./Verify.sol"; +import "./Owned.sol"; + +// ---------------------------------------------------------------------------- +// Contract function to receive approval and execute function in one call +// +// Borrowed from MiniMeToken +// ---------------------------------------------------------------------------- +abstract contract ApproveAndCallFallBack { + function receiveApproval( + address from, + uint256 tokens, + address token, + bytes memory data + ) public virtual; +} + +contract Oracled is Owned { + mapping(address => bool) public oracles; + + modifier onlyOracle() { + /* require( + oracles[msg.sender] == true, + "Account is not a registered oracle" + ); */ + + _; + } + + function regOracle(address _newOracle) public onlyOwner { + require(!oracles[_newOracle], "Oracle is already registered"); + + oracles[_newOracle] = true; + } + + function unregOracle(address _remOracle) public onlyOwner { + require(oracles[_remOracle] == true, "Oracle is not registered"); + + delete oracles[_remOracle]; + } +} + +// ---------------------------------------------------------------------------- +// RFOX Bridge contract lock and release swap amount for each cross chain swap +// +// ---------------------------------------------------------------------------- +contract ETHWAXBRIDGE is Oracled, Verify { + using SafeMath for uint256; + using SafeERC20 for IERC20; + + // RFOX Token address + // Only using this address for bridging + IERC20 public rfox; + // Threshold meaning the minimum requirement for oracle confirmations + uint8 public threshold; + // ChainID for RFOX Bridge + uint8 public thisChainId; + // How many locked token in ETHWAXBRIDGE + uint256 public totalLocked; + // Mapping from transaction ID + mapping(uint64 => mapping(address => bool)) signed; + mapping(uint64 => bool) public claimed; + + event Bridge( + address indexed from, + string to, + uint256 tokens, + uint256 chainId + ); + event Claimed(uint64 id, address to, uint256 tokens); + + struct BridgeData { + uint64 id; + uint32 ts; + uint64 fromAddr; + uint256 quantity; + uint64 symbolRaw; + uint8 chainId; + address toAddress; + } + + event Locked(address from, uint256 amount); + event Released(address to, uint256 amount); + + // ------------------------------------------------------------------------ + // Constructor + // ------------------------------------------------------------------------ + constructor(IERC20 rfoxAddress) public { + uint8 chainId; + + threshold = 3; + rfox = rfoxAddress; + + assembly { + chainId := chainid() + } + + thisChainId = chainId; + } + + // ------------------------------------------------------------------------ + // Moves tokens to the inaccessible account and then sends event for the oracles + // to monitor and issue on other chain + // to : WAX address + // tokens : number of tokens in satoshis + // chainId : The chain id that they will be sent to + // ------------------------------------------------------------------------ + + function bridge( + string memory to, + uint256 tokens, + uint256 chainid + ) public returns (bool success) { + lock(msg.sender, tokens); + + emit Bridge(msg.sender, to, tokens, chainid); + emit Locked(msg.sender, tokens); + + return true; + } + + // ------------------------------------------------------------------------ + // Claim tokens sent using signatures supplied to the other chain + // ------------------------------------------------------------------------ + + function verifySigData(bytes memory sigData) + private + returns (BridgeData memory) + { + BridgeData memory td; + + uint64 oracleQuantity = 0; + uint64 id; + uint32 ts; + uint64 fromAddr; + uint64 symbolRaw; + uint8 chainId; + address toAddress; + + assembly { + id := mload(add(add(sigData, 0x8), 0)) + ts := mload(add(add(sigData, 0x4), 8)) + fromAddr := mload(add(add(sigData, 0x8), 12)) + oracleQuantity := mload(add(add(sigData, 0x8), 20)) + symbolRaw := mload(add(add(sigData, 0x8), 28)) + chainId := mload(add(add(sigData, 0x1), 36)) + toAddress := mload(add(add(sigData, 0x14), 37)) + } + + uint256 reversedQuantity = Endian.reverse64(oracleQuantity); + + td.id = Endian.reverse64(id); + td.ts = Endian.reverse32(ts); + td.fromAddr = Endian.reverse64(fromAddr); + td.quantity = uint256(reversedQuantity) * 1e10; + td.symbolRaw = Endian.reverse64(symbolRaw); + td.chainId = chainId; + td.toAddress = toAddress; + + require(thisChainId == td.chainId, "Invalid Chain ID"); + require( + block.timestamp < SafeMath.add(td.ts, (60 * 60 * 24 * 30)), + "Bridge has expired" + ); + + require(!claimed[td.id], "Already Claimed"); + + claimed[td.id] = true; + + return td; + } + + function claim(bytes memory sigData, bytes[] calldata signatures) + public + returns (address toAddress) + { + BridgeData memory td = verifySigData(sigData); + + // verify signatures + require(sigData.length == 69, "Signature data is the wrong size"); + require( + signatures.length <= 10, + "Maximum of 10 signatures can be provided" + ); + + bytes32 message = keccak256(sigData); + + uint8 numberSigs = 0; + + for (uint8 i = 0; i < signatures.length; i++) { + address potential = Verify.recoverSigner(message, signatures[i]); + + // Check that they are an oracle and they haven't signed twice + if (oracles[potential] && !signed[td.id][potential]) { + signed[td.id][potential] = true; + numberSigs++; + + if (numberSigs >= 10) { + break; + } + } + } + + require( + numberSigs >= threshold, + "Not enough valid signatures provided" + ); + + release(td.toAddress, td.quantity); + + emit Claimed(td.id, td.toAddress, td.quantity); + + return td.toAddress; + } + + function updateThreshold(uint8 newThreshold) + public + onlyOwner + returns (bool success) + { + if (newThreshold > 0) { + require(newThreshold <= 10, "Threshold has maximum of 10"); + + threshold = newThreshold; + + return true; + } + + return false; + } + + // ------------------------------------------------------------------------ + // Don't accept ETH + // ------------------------------------------------------------------------ + receive() external payable { + revert(); + } + + // ------------------------------------------------------------------------ + // Owner can transfer out any accidentally sent ERC20 tokens + // ------------------------------------------------------------------------ + function transferAnyERC20Token(IERC20 tokenAddress, uint256 tokens) + public + onlyOwner + { + // We never transfer our RFOX to another addresses + require(tokenAddress != rfox, "Token locked"); + // Transfer any tokens + tokenAddress.safeTransfer(owner, tokens); + } + + /// @notice Function that lock the RFOX token when bridging + /// @dev Internal function, only call when bridging + /// @param from Owner of this bridge action + /// @param amount Quantity RFOX for bridging of this bridge action + function lock(address from, uint256 amount) internal { + totalLocked = totalLocked.add(amount); + rfox.safeTransferFrom(from, address(this), amount); + + emit Locked(from, amount); + } + + /// @notice Function that release the RFOX token when bridging + /// @dev Internal function, only call when bridging + /// @param to Address of receive bridging token + /// @param amount Quantity RFOX for bridging of this bridge action + function release(address to, uint256 amount) internal { + totalLocked = totalLocked.sub(amount); + rfox.safeTransfer(to, amount); + + emit Released(to, amount); + } +} diff --git a/contracts/mutants/ETHWAXBRIDGE/1/FVR/ETHWAXBRIDGE.sol b/contracts/mutants/ETHWAXBRIDGE/1/FVR/ETHWAXBRIDGE.sol new file mode 100644 index 00000000000..293bc10bf32 --- /dev/null +++ b/contracts/mutants/ETHWAXBRIDGE/1/FVR/ETHWAXBRIDGE.sol @@ -0,0 +1,284 @@ +//SPDX-License-Identifier: MIT + +pragma solidity ^0.6.12; +pragma experimental ABIEncoderV2; + +import "@openzeppelin/contracts/token/ERC20/SafeERC20.sol"; + +import "./libraries/Endian.sol"; +//SWC-135-Code With No Effects:L10 +import "./interfaces/ERC20Interface.sol"; + +import "./Verify.sol"; +import "./Owned.sol"; + +// ---------------------------------------------------------------------------- +// Contract function to receive approval and execute function in one call +// +// Borrowed from MiniMeToken +// ---------------------------------------------------------------------------- +abstract contract ApproveAndCallFallBack { + function receiveApproval( + address from, + uint256 tokens, + address token, + bytes memory data + ) public virtual; +} + +contract Oracled is Owned { + mapping(address => bool) public oracles; + + modifier onlyOracle() { + require( + oracles[msg.sender] == true, + "Account is not a registered oracle" + ); + + _; + } + + function regOracle(address _newOracle) external onlyOwner { + require(!oracles[_newOracle], "Oracle is already registered"); + + oracles[_newOracle] = true; + } + + function unregOracle(address _remOracle) public onlyOwner { + require(oracles[_remOracle] == true, "Oracle is not registered"); + + delete oracles[_remOracle]; + } +} + +// ---------------------------------------------------------------------------- +// RFOX Bridge contract lock and release swap amount for each cross chain swap +// +// ---------------------------------------------------------------------------- +contract ETHWAXBRIDGE is Oracled, Verify { + using SafeMath for uint256; + using SafeERC20 for IERC20; + + // RFOX Token address + // Only using this address for bridging + IERC20 public rfox; + // Threshold meaning the minimum requirement for oracle confirmations + uint8 public threshold; + // ChainID for RFOX Bridge + uint8 public thisChainId; + // How many locked token in ETHWAXBRIDGE + uint256 public totalLocked; + // Mapping from transaction ID + mapping(uint64 => mapping(address => bool)) signed; + mapping(uint64 => bool) public claimed; + + event Bridge( + address indexed from, + string to, + uint256 tokens, + uint256 chainId + ); + event Claimed(uint64 id, address to, uint256 tokens); + + struct BridgeData { + uint64 id; + uint32 ts; + uint64 fromAddr; + uint256 quantity; + uint64 symbolRaw; + uint8 chainId; + address toAddress; + } + + event Locked(address from, uint256 amount); + event Released(address to, uint256 amount); + + // ------------------------------------------------------------------------ + // Constructor + // ------------------------------------------------------------------------ + constructor(IERC20 rfoxAddress) public { + uint8 chainId; + + threshold = 3; + rfox = rfoxAddress; + + assembly { + chainId := chainid() + } + + thisChainId = chainId; + } + + // ------------------------------------------------------------------------ + // Moves tokens to the inaccessible account and then sends event for the oracles + // to monitor and issue on other chain + // to : WAX address + // tokens : number of tokens in satoshis + // chainId : The chain id that they will be sent to + // ------------------------------------------------------------------------ + + function bridge( + string memory to, + uint256 tokens, + uint256 chainid + ) public returns (bool success) { + lock(msg.sender, tokens); + + emit Bridge(msg.sender, to, tokens, chainid); + emit Locked(msg.sender, tokens); + + return true; + } + + // ------------------------------------------------------------------------ + // Claim tokens sent using signatures supplied to the other chain + // ------------------------------------------------------------------------ + + function verifySigData(bytes memory sigData) + private + returns (BridgeData memory) + { + BridgeData memory td; + + uint64 oracleQuantity = 0; + uint64 id; + uint32 ts; + uint64 fromAddr; + uint64 symbolRaw; + uint8 chainId; + address toAddress; + + assembly { + id := mload(add(add(sigData, 0x8), 0)) + ts := mload(add(add(sigData, 0x4), 8)) + fromAddr := mload(add(add(sigData, 0x8), 12)) + oracleQuantity := mload(add(add(sigData, 0x8), 20)) + symbolRaw := mload(add(add(sigData, 0x8), 28)) + chainId := mload(add(add(sigData, 0x1), 36)) + toAddress := mload(add(add(sigData, 0x14), 37)) + } + + uint256 reversedQuantity = Endian.reverse64(oracleQuantity); + + td.id = Endian.reverse64(id); + td.ts = Endian.reverse32(ts); + td.fromAddr = Endian.reverse64(fromAddr); + td.quantity = uint256(reversedQuantity) * 1e10; + td.symbolRaw = Endian.reverse64(symbolRaw); + td.chainId = chainId; + td.toAddress = toAddress; + + require(thisChainId == td.chainId, "Invalid Chain ID"); + require( + block.timestamp < SafeMath.add(td.ts, (60 * 60 * 24 * 30)), + "Bridge has expired" + ); + + require(!claimed[td.id], "Already Claimed"); + + claimed[td.id] = true; + + return td; + } + + function claim(bytes memory sigData, bytes[] calldata signatures) + public + returns (address toAddress) + { + BridgeData memory td = verifySigData(sigData); + + // verify signatures + require(sigData.length == 69, "Signature data is the wrong size"); + require( + signatures.length <= 10, + "Maximum of 10 signatures can be provided" + ); + + bytes32 message = keccak256(sigData); + + uint8 numberSigs = 0; + + for (uint8 i = 0; i < signatures.length; i++) { + address potential = Verify.recoverSigner(message, signatures[i]); + + // Check that they are an oracle and they haven't signed twice + if (oracles[potential] && !signed[td.id][potential]) { + signed[td.id][potential] = true; + numberSigs++; + + if (numberSigs >= 10) { + break; + } + } + } + + require( + numberSigs >= threshold, + "Not enough valid signatures provided" + ); + + release(td.toAddress, td.quantity); + + emit Claimed(td.id, td.toAddress, td.quantity); + + return td.toAddress; + } + + function updateThreshold(uint8 newThreshold) + public + onlyOwner + returns (bool success) + { + if (newThreshold > 0) { + require(newThreshold <= 10, "Threshold has maximum of 10"); + + threshold = newThreshold; + + return true; + } + + return false; + } + + // ------------------------------------------------------------------------ + // Don't accept ETH + // ------------------------------------------------------------------------ + receive() external payable { + revert(); + } + + // ------------------------------------------------------------------------ + // Owner can transfer out any accidentally sent ERC20 tokens + // ------------------------------------------------------------------------ + function transferAnyERC20Token(IERC20 tokenAddress, uint256 tokens) + public + onlyOwner + { + // We never transfer our RFOX to another addresses + require(tokenAddress != rfox, "Token locked"); + // Transfer any tokens + tokenAddress.safeTransfer(owner, tokens); + } + + /// @notice Function that lock the RFOX token when bridging + /// @dev Internal function, only call when bridging + /// @param from Owner of this bridge action + /// @param amount Quantity RFOX for bridging of this bridge action + function lock(address from, uint256 amount) internal { + totalLocked = totalLocked.add(amount); + rfox.safeTransferFrom(from, address(this), amount); + + emit Locked(from, amount); + } + + /// @notice Function that release the RFOX token when bridging + /// @dev Internal function, only call when bridging + /// @param to Address of receive bridging token + /// @param amount Quantity RFOX for bridging of this bridge action + function release(address to, uint256 amount) internal { + totalLocked = totalLocked.sub(amount); + rfox.safeTransfer(to, amount); + + emit Released(to, amount); + } +} diff --git a/contracts/mutants/ETHWAXBRIDGE/1/GVR/ETHWAXBRIDGE.sol b/contracts/mutants/ETHWAXBRIDGE/1/GVR/ETHWAXBRIDGE.sol new file mode 100644 index 00000000000..42272be4da3 --- /dev/null +++ b/contracts/mutants/ETHWAXBRIDGE/1/GVR/ETHWAXBRIDGE.sol @@ -0,0 +1,284 @@ +//SPDX-License-Identifier: MIT + +pragma solidity ^0.6.12; +pragma experimental ABIEncoderV2; + +import "@openzeppelin/contracts/token/ERC20/SafeERC20.sol"; + +import "./libraries/Endian.sol"; +//SWC-135-Code With No Effects:L10 +import "./interfaces/ERC20Interface.sol"; + +import "./Verify.sol"; +import "./Owned.sol"; + +// ---------------------------------------------------------------------------- +// Contract function to receive approval and execute function in one call +// +// Borrowed from MiniMeToken +// ---------------------------------------------------------------------------- +abstract contract ApproveAndCallFallBack { + function receiveApproval( + address from, + uint256 tokens, + address token, + bytes memory data + ) public virtual; +} + +contract Oracled is Owned { + mapping(address => bool) public oracles; + + modifier onlyOracle() { + require( + oracles[msg.sender] == true, + "Account is not a registered oracle" + ); + + _; + } + + function regOracle(address _newOracle) public onlyOwner { + require(!oracles[_newOracle], "Oracle is already registered"); + + oracles[_newOracle] = true; + } + + function unregOracle(address _remOracle) public onlyOwner { + require(oracles[_remOracle] == true, "Oracle is not registered"); + + delete oracles[_remOracle]; + } +} + +// ---------------------------------------------------------------------------- +// RFOX Bridge contract lock and release swap amount for each cross chain swap +// +// ---------------------------------------------------------------------------- +contract ETHWAXBRIDGE is Oracled, Verify { + using SafeMath for uint256; + using SafeERC20 for IERC20; + + // RFOX Token address + // Only using this address for bridging + IERC20 public rfox; + // Threshold meaning the minimum requirement for oracle confirmations + uint8 public threshold; + // ChainID for RFOX Bridge + uint8 public thisChainId; + // How many locked token in ETHWAXBRIDGE + uint256 public totalLocked; + // Mapping from transaction ID + mapping(uint64 => mapping(address => bool)) signed; + mapping(uint64 => bool) public claimed; + + event Bridge( + address indexed from, + string to, + uint256 tokens, + uint256 chainId + ); + event Claimed(uint64 id, address to, uint256 tokens); + + struct BridgeData { + uint64 id; + uint32 ts; + uint64 fromAddr; + uint256 quantity; + uint64 symbolRaw; + uint8 chainId; + address toAddress; + } + + event Locked(address from, uint256 amount); + event Released(address to, uint256 amount); + + // ------------------------------------------------------------------------ + // Constructor + // ------------------------------------------------------------------------ + constructor(IERC20 rfoxAddress) public { + uint8 chainId; + + threshold = 3; + rfox = rfoxAddress; + + assembly { + chainId := chainid() + } + + thisChainId = chainId; + } + + // ------------------------------------------------------------------------ + // Moves tokens to the inaccessible account and then sends event for the oracles + // to monitor and issue on other chain + // to : WAX address + // tokens : number of tokens in satoshis + // chainId : The chain id that they will be sent to + // ------------------------------------------------------------------------ + + function bridge( + string memory to, + uint256 tokens, + uint256 chainid + ) public returns (bool success) { + lock(msg.sender, tokens); + + emit Bridge(msg.sender, to, tokens, chainid); + emit Locked(msg.sender, tokens); + + return true; + } + + // ------------------------------------------------------------------------ + // Claim tokens sent using signatures supplied to the other chain + // ------------------------------------------------------------------------ + + function verifySigData(bytes memory sigData) + private + returns (BridgeData memory) + { + BridgeData memory td; + + uint64 oracleQuantity = 0; + uint64 id; + uint32 ts; + uint64 fromAddr; + uint64 symbolRaw; + uint8 chainId; + address toAddress; + + assembly { + id := mload(add(add(sigData, 0x8), 0)) + ts := mload(add(add(sigData, 0x4), 8)) + fromAddr := mload(add(add(sigData, 0x8), 12)) + oracleQuantity := mload(add(add(sigData, 0x8), 20)) + symbolRaw := mload(add(add(sigData, 0x8), 28)) + chainId := mload(add(add(sigData, 0x1), 36)) + toAddress := mload(add(add(sigData, 0x14), 37)) + } + + uint256 reversedQuantity = Endian.reverse64(oracleQuantity); + + td.id = Endian.reverse64(id); + td.ts = Endian.reverse32(ts); + td.fromAddr = Endian.reverse64(fromAddr); + td.quantity = uint256(reversedQuantity) * 1e10; + td.symbolRaw = Endian.reverse64(symbolRaw); + td.chainId = chainId; + td.toAddress = toAddress; + + require(thisChainId == td.chainId, "Invalid Chain ID"); + require( + block.number < SafeMath.add(td.ts, (60 * 60 * 24 * 30)), + "Bridge has expired" + ); + + require(!claimed[td.id], "Already Claimed"); + + claimed[td.id] = true; + + return td; + } + + function claim(bytes memory sigData, bytes[] calldata signatures) + public + returns (address toAddress) + { + BridgeData memory td = verifySigData(sigData); + + // verify signatures + require(sigData.length == 69, "Signature data is the wrong size"); + require( + signatures.length <= 10, + "Maximum of 10 signatures can be provided" + ); + + bytes32 message = keccak256(sigData); + + uint8 numberSigs = 0; + + for (uint8 i = 0; i < signatures.length; i++) { + address potential = Verify.recoverSigner(message, signatures[i]); + + // Check that they are an oracle and they haven't signed twice + if (oracles[potential] && !signed[td.id][potential]) { + signed[td.id][potential] = true; + numberSigs++; + + if (numberSigs >= 10) { + break; + } + } + } + + require( + numberSigs >= threshold, + "Not enough valid signatures provided" + ); + + release(td.toAddress, td.quantity); + + emit Claimed(td.id, td.toAddress, td.quantity); + + return td.toAddress; + } + + function updateThreshold(uint8 newThreshold) + public + onlyOwner + returns (bool success) + { + if (newThreshold > 0) { + require(newThreshold <= 10, "Threshold has maximum of 10"); + + threshold = newThreshold; + + return true; + } + + return false; + } + + // ------------------------------------------------------------------------ + // Don't accept ETH + // ------------------------------------------------------------------------ + receive() external payable { + revert(); + } + + // ------------------------------------------------------------------------ + // Owner can transfer out any accidentally sent ERC20 tokens + // ------------------------------------------------------------------------ + function transferAnyERC20Token(IERC20 tokenAddress, uint256 tokens) + public + onlyOwner + { + // We never transfer our RFOX to another addresses + require(tokenAddress != rfox, "Token locked"); + // Transfer any tokens + tokenAddress.safeTransfer(owner, tokens); + } + + /// @notice Function that lock the RFOX token when bridging + /// @dev Internal function, only call when bridging + /// @param from Owner of this bridge action + /// @param amount Quantity RFOX for bridging of this bridge action + function lock(address from, uint256 amount) internal { + totalLocked = totalLocked.add(amount); + rfox.safeTransferFrom(from, address(this), amount); + + emit Locked(from, amount); + } + + /// @notice Function that release the RFOX token when bridging + /// @dev Internal function, only call when bridging + /// @param to Address of receive bridging token + /// @param amount Quantity RFOX for bridging of this bridge action + function release(address to, uint256 amount) internal { + totalLocked = totalLocked.sub(amount); + rfox.safeTransfer(to, amount); + + emit Released(to, amount); + } +} diff --git a/contracts/mutants/ETHWAXBRIDGE/1/ILR/ETHWAXBRIDGE.sol b/contracts/mutants/ETHWAXBRIDGE/1/ILR/ETHWAXBRIDGE.sol new file mode 100644 index 00000000000..d8c939ed728 --- /dev/null +++ b/contracts/mutants/ETHWAXBRIDGE/1/ILR/ETHWAXBRIDGE.sol @@ -0,0 +1,284 @@ +//SPDX-License-Identifier: MIT + +pragma solidity ^0.6.12; +pragma experimental ABIEncoderV2; + +import "@openzeppelin/contracts/token/ERC20/SafeERC20.sol"; + +import "./libraries/Endian.sol"; +//SWC-135-Code With No Effects:L10 +import "./interfaces/ERC20Interface.sol"; + +import "./Verify.sol"; +import "./Owned.sol"; + +// ---------------------------------------------------------------------------- +// Contract function to receive approval and execute function in one call +// +// Borrowed from MiniMeToken +// ---------------------------------------------------------------------------- +abstract contract ApproveAndCallFallBack { + function receiveApproval( + address from, + uint256 tokens, + address token, + bytes memory data + ) public virtual; +} + +contract Oracled is Owned { + mapping(address => bool) public oracles; + + modifier onlyOracle() { + require( + oracles[msg.sender] == true, + "Account is not a registered oracle" + ); + + _; + } + + function regOracle(address _newOracle) public onlyOwner { + require(!oracles[_newOracle], "Oracle is already registered"); + + oracles[_newOracle] = true; + } + + function unregOracle(address _remOracle) public onlyOwner { + require(oracles[_remOracle] == true, "Oracle is not registered"); + + delete oracles[_remOracle]; + } +} + +// ---------------------------------------------------------------------------- +// RFOX Bridge contract lock and release swap amount for each cross chain swap +// +// ---------------------------------------------------------------------------- +contract ETHWAXBRIDGE is Oracled, Verify { + using SafeMath for uint256; + using SafeERC20 for IERC20; + + // RFOX Token address + // Only using this address for bridging + IERC20 public rfox; + // Threshold meaning the minimum requirement for oracle confirmations + uint8 public threshold; + // ChainID for RFOX Bridge + uint8 public thisChainId; + // How many locked token in ETHWAXBRIDGE + uint256 public totalLocked; + // Mapping from transaction ID + mapping(uint64 => mapping(address => bool)) signed; + mapping(uint64 => bool) public claimed; + + event Bridge( + address indexed from, + string to, + uint256 tokens, + uint256 chainId + ); + event Claimed(uint64 id, address to, uint256 tokens); + + struct BridgeData { + uint64 id; + uint32 ts; + uint64 fromAddr; + uint256 quantity; + uint64 symbolRaw; + uint8 chainId; + address toAddress; + } + + event Locked(address from, uint256 amount); + event Released(address to, uint256 amount); + + // ------------------------------------------------------------------------ + // Constructor + // ------------------------------------------------------------------------ + constructor(IERC20 rfoxAddress) public { + uint8 chainId; + + threshold = 2; + rfox = rfoxAddress; + + assembly { + chainId := chainid() + } + + thisChainId = chainId; + } + + // ------------------------------------------------------------------------ + // Moves tokens to the inaccessible account and then sends event for the oracles + // to monitor and issue on other chain + // to : WAX address + // tokens : number of tokens in satoshis + // chainId : The chain id that they will be sent to + // ------------------------------------------------------------------------ + + function bridge( + string memory to, + uint256 tokens, + uint256 chainid + ) public returns (bool success) { + lock(msg.sender, tokens); + + emit Bridge(msg.sender, to, tokens, chainid); + emit Locked(msg.sender, tokens); + + return true; + } + + // ------------------------------------------------------------------------ + // Claim tokens sent using signatures supplied to the other chain + // ------------------------------------------------------------------------ + + function verifySigData(bytes memory sigData) + private + returns (BridgeData memory) + { + BridgeData memory td; + + uint64 oracleQuantity = 0; + uint64 id; + uint32 ts; + uint64 fromAddr; + uint64 symbolRaw; + uint8 chainId; + address toAddress; + + assembly { + id := mload(add(add(sigData, 0x8), 0)) + ts := mload(add(add(sigData, 0x4), 8)) + fromAddr := mload(add(add(sigData, 0x8), 12)) + oracleQuantity := mload(add(add(sigData, 0x8), 20)) + symbolRaw := mload(add(add(sigData, 0x8), 28)) + chainId := mload(add(add(sigData, 0x1), 36)) + toAddress := mload(add(add(sigData, 0x14), 37)) + } + + uint256 reversedQuantity = Endian.reverse64(oracleQuantity); + + td.id = Endian.reverse64(id); + td.ts = Endian.reverse32(ts); + td.fromAddr = Endian.reverse64(fromAddr); + td.quantity = uint256(reversedQuantity) * 1e10; + td.symbolRaw = Endian.reverse64(symbolRaw); + td.chainId = chainId; + td.toAddress = toAddress; + + require(thisChainId == td.chainId, "Invalid Chain ID"); + require( + block.timestamp < SafeMath.add(td.ts, (60 * 60 * 24 * 30)), + "Bridge has expired" + ); + + require(!claimed[td.id], "Already Claimed"); + + claimed[td.id] = true; + + return td; + } + + function claim(bytes memory sigData, bytes[] calldata signatures) + public + returns (address toAddress) + { + BridgeData memory td = verifySigData(sigData); + + // verify signatures + require(sigData.length == 69, "Signature data is the wrong size"); + require( + signatures.length <= 10, + "Maximum of 10 signatures can be provided" + ); + + bytes32 message = keccak256(sigData); + + uint8 numberSigs = 0; + + for (uint8 i = 0; i < signatures.length; i++) { + address potential = Verify.recoverSigner(message, signatures[i]); + + // Check that they are an oracle and they haven't signed twice + if (oracles[potential] && !signed[td.id][potential]) { + signed[td.id][potential] = true; + numberSigs++; + + if (numberSigs >= 10) { + break; + } + } + } + + require( + numberSigs >= threshold, + "Not enough valid signatures provided" + ); + + release(td.toAddress, td.quantity); + + emit Claimed(td.id, td.toAddress, td.quantity); + + return td.toAddress; + } + + function updateThreshold(uint8 newThreshold) + public + onlyOwner + returns (bool success) + { + if (newThreshold > 0) { + require(newThreshold <= 10, "Threshold has maximum of 10"); + + threshold = newThreshold; + + return true; + } + + return false; + } + + // ------------------------------------------------------------------------ + // Don't accept ETH + // ------------------------------------------------------------------------ + receive() external payable { + revert(); + } + + // ------------------------------------------------------------------------ + // Owner can transfer out any accidentally sent ERC20 tokens + // ------------------------------------------------------------------------ + function transferAnyERC20Token(IERC20 tokenAddress, uint256 tokens) + public + onlyOwner + { + // We never transfer our RFOX to another addresses + require(tokenAddress != rfox, "Token locked"); + // Transfer any tokens + tokenAddress.safeTransfer(owner, tokens); + } + + /// @notice Function that lock the RFOX token when bridging + /// @dev Internal function, only call when bridging + /// @param from Owner of this bridge action + /// @param amount Quantity RFOX for bridging of this bridge action + function lock(address from, uint256 amount) internal { + totalLocked = totalLocked.add(amount); + rfox.safeTransferFrom(from, address(this), amount); + + emit Locked(from, amount); + } + + /// @notice Function that release the RFOX token when bridging + /// @dev Internal function, only call when bridging + /// @param to Address of receive bridging token + /// @param amount Quantity RFOX for bridging of this bridge action + function release(address to, uint256 amount) internal { + totalLocked = totalLocked.sub(amount); + rfox.safeTransfer(to, amount); + + emit Released(to, amount); + } +} diff --git a/contracts/mutants/ETHWAXBRIDGE/1/MCR/ETHWAXBRIDGE.sol b/contracts/mutants/ETHWAXBRIDGE/1/MCR/ETHWAXBRIDGE.sol new file mode 100644 index 00000000000..ce92da5735c --- /dev/null +++ b/contracts/mutants/ETHWAXBRIDGE/1/MCR/ETHWAXBRIDGE.sol @@ -0,0 +1,284 @@ +//SPDX-License-Identifier: MIT + +pragma solidity ^0.6.12; +pragma experimental ABIEncoderV2; + +import "@openzeppelin/contracts/token/ERC20/SafeERC20.sol"; + +import "./libraries/Endian.sol"; +//SWC-135-Code With No Effects:L10 +import "./interfaces/ERC20Interface.sol"; + +import "./Verify.sol"; +import "./Owned.sol"; + +// ---------------------------------------------------------------------------- +// Contract function to receive approval and execute function in one call +// +// Borrowed from MiniMeToken +// ---------------------------------------------------------------------------- +abstract contract ApproveAndCallFallBack { + function receiveApproval( + address from, + uint256 tokens, + address token, + bytes memory data + ) public virtual; +} + +contract Oracled is Owned { + mapping(address => bool) public oracles; + + modifier onlyOracle() { + require( + oracles[msg.sender] == true, + "Account is not a registered oracle" + ); + + _; + } + + function regOracle(address _newOracle) public onlyOwner { + require(!oracles[_newOracle], "Oracle is already registered"); + + oracles[_newOracle] = true; + } + + function unregOracle(address _remOracle) public onlyOwner { + require(oracles[_remOracle] == true, "Oracle is not registered"); + + delete oracles[_remOracle]; + } +} + +// ---------------------------------------------------------------------------- +// RFOX Bridge contract lock and release swap amount for each cross chain swap +// +// ---------------------------------------------------------------------------- +contract ETHWAXBRIDGE is Oracled, Verify { + using SafeMath for uint256; + using SafeERC20 for IERC20; + + // RFOX Token address + // Only using this address for bridging + IERC20 public rfox; + // Threshold meaning the minimum requirement for oracle confirmations + uint8 public threshold; + // ChainID for RFOX Bridge + uint8 public thisChainId; + // How many locked token in ETHWAXBRIDGE + uint256 public totalLocked; + // Mapping from transaction ID + mapping(uint64 => mapping(address => bool)) signed; + mapping(uint64 => bool) public claimed; + + event Bridge( + address indexed from, + string to, + uint256 tokens, + uint256 chainId + ); + event Claimed(uint64 id, address to, uint256 tokens); + + struct BridgeData { + uint64 id; + uint32 ts; + uint64 fromAddr; + uint256 quantity; + uint64 symbolRaw; + uint8 chainId; + address toAddress; + } + + event Locked(address from, uint256 amount); + event Released(address to, uint256 amount); + + // ------------------------------------------------------------------------ + // Constructor + // ------------------------------------------------------------------------ + constructor(IERC20 rfoxAddress) public { + uint8 chainId; + + threshold = 3; + rfox = rfoxAddress; + + assembly { + chainId := chainid() + } + + thisChainId = chainId; + } + + // ------------------------------------------------------------------------ + // Moves tokens to the inaccessible account and then sends event for the oracles + // to monitor and issue on other chain + // to : WAX address + // tokens : number of tokens in satoshis + // chainId : The chain id that they will be sent to + // ------------------------------------------------------------------------ + + function bridge( + string memory to, + uint256 tokens, + uint256 chainid + ) public returns (bool success) { + lock(msg.sender, tokens); + + emit Bridge(msg.sender, to, tokens, chainid); + emit Locked(msg.sender, tokens); + + return true; + } + + // ------------------------------------------------------------------------ + // Claim tokens sent using signatures supplied to the other chain + // ------------------------------------------------------------------------ + + function verifySigData(bytes memory sigData) + private + returns (BridgeData memory) + { + BridgeData memory td; + + uint64 oracleQuantity = 0; + uint64 id; + uint32 ts; + uint64 fromAddr; + uint64 symbolRaw; + uint8 chainId; + address toAddress; + + assembly { + id := mload(add(add(sigData, 0x8), 0)) + ts := mload(add(add(sigData, 0x4), 8)) + fromAddr := mload(add(add(sigData, 0x8), 12)) + oracleQuantity := mload(add(add(sigData, 0x8), 20)) + symbolRaw := mload(add(add(sigData, 0x8), 28)) + chainId := mload(add(add(sigData, 0x1), 36)) + toAddress := mload(add(add(sigData, 0x14), 37)) + } + + uint256 reversedQuantity = Endian.reverse64(oracleQuantity); + + td.id = Endian.reverse64(id); + td.ts = Endian.reverse32(ts); + td.fromAddr = Endian.reverse64(fromAddr); + td.quantity = uint256(reversedQuantity) * 1e10; + td.symbolRaw = Endian.reverse64(symbolRaw); + td.chainId = chainId; + td.toAddress = toAddress; + + require(thisChainId == td.chainId, "Invalid Chain ID"); + require( + block.timestamp < SafeMath.add(td.ts, (60 * 60 * 24 * 30)), + "Bridge has expired" + ); + + require(!claimed[td.id], "Already Claimed"); + + claimed[td.id] = true; + + return td; + } + + function claim(bytes memory sigData, bytes[] calldata signatures) + public + returns (address toAddress) + { + BridgeData memory td = verifySigData(sigData); + + // verify signatures + require(sigData.length == 69, "Signature data is the wrong size"); + require( + signatures.length <= 10, + "Maximum of 10 signatures can be provided" + ); + + bytes32 message = sha256(sigData); + + uint8 numberSigs = 0; + + for (uint8 i = 0; i < signatures.length; i++) { + address potential = Verify.recoverSigner(message, signatures[i]); + + // Check that they are an oracle and they haven't signed twice + if (oracles[potential] && !signed[td.id][potential]) { + signed[td.id][potential] = true; + numberSigs++; + + if (numberSigs >= 10) { + break; + } + } + } + + require( + numberSigs >= threshold, + "Not enough valid signatures provided" + ); + + release(td.toAddress, td.quantity); + + emit Claimed(td.id, td.toAddress, td.quantity); + + return td.toAddress; + } + + function updateThreshold(uint8 newThreshold) + public + onlyOwner + returns (bool success) + { + if (newThreshold > 0) { + require(newThreshold <= 10, "Threshold has maximum of 10"); + + threshold = newThreshold; + + return true; + } + + return false; + } + + // ------------------------------------------------------------------------ + // Don't accept ETH + // ------------------------------------------------------------------------ + receive() external payable { + revert(); + } + + // ------------------------------------------------------------------------ + // Owner can transfer out any accidentally sent ERC20 tokens + // ------------------------------------------------------------------------ + function transferAnyERC20Token(IERC20 tokenAddress, uint256 tokens) + public + onlyOwner + { + // We never transfer our RFOX to another addresses + require(tokenAddress != rfox, "Token locked"); + // Transfer any tokens + tokenAddress.safeTransfer(owner, tokens); + } + + /// @notice Function that lock the RFOX token when bridging + /// @dev Internal function, only call when bridging + /// @param from Owner of this bridge action + /// @param amount Quantity RFOX for bridging of this bridge action + function lock(address from, uint256 amount) internal { + totalLocked = totalLocked.add(amount); + rfox.safeTransferFrom(from, address(this), amount); + + emit Locked(from, amount); + } + + /// @notice Function that release the RFOX token when bridging + /// @dev Internal function, only call when bridging + /// @param to Address of receive bridging token + /// @param amount Quantity RFOX for bridging of this bridge action + function release(address to, uint256 amount) internal { + totalLocked = totalLocked.sub(amount); + rfox.safeTransfer(to, amount); + + emit Released(to, amount); + } +} diff --git a/contracts/mutants/ETHWAXBRIDGE/1/RSD/ETHWAXBRIDGE.sol b/contracts/mutants/ETHWAXBRIDGE/1/RSD/ETHWAXBRIDGE.sol new file mode 100644 index 00000000000..a8b21057909 --- /dev/null +++ b/contracts/mutants/ETHWAXBRIDGE/1/RSD/ETHWAXBRIDGE.sol @@ -0,0 +1,284 @@ +//SPDX-License-Identifier: MIT + +pragma solidity ^0.6.12; +pragma experimental ABIEncoderV2; + +import "@openzeppelin/contracts/token/ERC20/SafeERC20.sol"; + +import "./libraries/Endian.sol"; +//SWC-135-Code With No Effects:L10 +import "./interfaces/ERC20Interface.sol"; + +import "./Verify.sol"; +import "./Owned.sol"; + +// ---------------------------------------------------------------------------- +// Contract function to receive approval and execute function in one call +// +// Borrowed from MiniMeToken +// ---------------------------------------------------------------------------- +abstract contract ApproveAndCallFallBack { + function receiveApproval( + address from, + uint256 tokens, + address token, + bytes memory data + ) public virtual; +} + +contract Oracled is Owned { + mapping(address => bool) public oracles; + + modifier onlyOracle() { + require( + oracles[msg.sender] == true, + "Account is not a registered oracle" + ); + + _; + } + + function regOracle(address _newOracle) public onlyOwner { + require(!oracles[_newOracle], "Oracle is already registered"); + + oracles[_newOracle] = true; + } + + function unregOracle(address _remOracle) public onlyOwner { + require(oracles[_remOracle] == true, "Oracle is not registered"); + + delete oracles[_remOracle]; + } +} + +// ---------------------------------------------------------------------------- +// RFOX Bridge contract lock and release swap amount for each cross chain swap +// +// ---------------------------------------------------------------------------- +contract ETHWAXBRIDGE is Oracled, Verify { + using SafeMath for uint256; + using SafeERC20 for IERC20; + + // RFOX Token address + // Only using this address for bridging + IERC20 public rfox; + // Threshold meaning the minimum requirement for oracle confirmations + uint8 public threshold; + // ChainID for RFOX Bridge + uint8 public thisChainId; + // How many locked token in ETHWAXBRIDGE + uint256 public totalLocked; + // Mapping from transaction ID + mapping(uint64 => mapping(address => bool)) signed; + mapping(uint64 => bool) public claimed; + + event Bridge( + address indexed from, + string to, + uint256 tokens, + uint256 chainId + ); + event Claimed(uint64 id, address to, uint256 tokens); + + struct BridgeData { + uint64 id; + uint32 ts; + uint64 fromAddr; + uint256 quantity; + uint64 symbolRaw; + uint8 chainId; + address toAddress; + } + + event Locked(address from, uint256 amount); + event Released(address to, uint256 amount); + + // ------------------------------------------------------------------------ + // Constructor + // ------------------------------------------------------------------------ + constructor(IERC20 rfoxAddress) public { + uint8 chainId; + + threshold = 3; + rfox = rfoxAddress; + + assembly { + chainId := chainid() + } + + thisChainId = chainId; + } + + // ------------------------------------------------------------------------ + // Moves tokens to the inaccessible account and then sends event for the oracles + // to monitor and issue on other chain + // to : WAX address + // tokens : number of tokens in satoshis + // chainId : The chain id that they will be sent to + // ------------------------------------------------------------------------ + + function bridge( + string memory to, + uint256 tokens, + uint256 chainid + ) public returns (bool success) { + lock(msg.sender, tokens); + + emit Bridge(msg.sender, to, tokens, chainid); + emit Locked(msg.sender, tokens); + + /* return true; */ + } + + // ------------------------------------------------------------------------ + // Claim tokens sent using signatures supplied to the other chain + // ------------------------------------------------------------------------ + + function verifySigData(bytes memory sigData) + private + returns (BridgeData memory) + { + BridgeData memory td; + + uint64 oracleQuantity = 0; + uint64 id; + uint32 ts; + uint64 fromAddr; + uint64 symbolRaw; + uint8 chainId; + address toAddress; + + assembly { + id := mload(add(add(sigData, 0x8), 0)) + ts := mload(add(add(sigData, 0x4), 8)) + fromAddr := mload(add(add(sigData, 0x8), 12)) + oracleQuantity := mload(add(add(sigData, 0x8), 20)) + symbolRaw := mload(add(add(sigData, 0x8), 28)) + chainId := mload(add(add(sigData, 0x1), 36)) + toAddress := mload(add(add(sigData, 0x14), 37)) + } + + uint256 reversedQuantity = Endian.reverse64(oracleQuantity); + + td.id = Endian.reverse64(id); + td.ts = Endian.reverse32(ts); + td.fromAddr = Endian.reverse64(fromAddr); + td.quantity = uint256(reversedQuantity) * 1e10; + td.symbolRaw = Endian.reverse64(symbolRaw); + td.chainId = chainId; + td.toAddress = toAddress; + + require(thisChainId == td.chainId, "Invalid Chain ID"); + require( + block.timestamp < SafeMath.add(td.ts, (60 * 60 * 24 * 30)), + "Bridge has expired" + ); + + require(!claimed[td.id], "Already Claimed"); + + claimed[td.id] = true; + + return td; + } + + function claim(bytes memory sigData, bytes[] calldata signatures) + public + returns (address toAddress) + { + BridgeData memory td = verifySigData(sigData); + + // verify signatures + require(sigData.length == 69, "Signature data is the wrong size"); + require( + signatures.length <= 10, + "Maximum of 10 signatures can be provided" + ); + + bytes32 message = keccak256(sigData); + + uint8 numberSigs = 0; + + for (uint8 i = 0; i < signatures.length; i++) { + address potential = Verify.recoverSigner(message, signatures[i]); + + // Check that they are an oracle and they haven't signed twice + if (oracles[potential] && !signed[td.id][potential]) { + signed[td.id][potential] = true; + numberSigs++; + + if (numberSigs >= 10) { + break; + } + } + } + + require( + numberSigs >= threshold, + "Not enough valid signatures provided" + ); + + release(td.toAddress, td.quantity); + + emit Claimed(td.id, td.toAddress, td.quantity); + + return td.toAddress; + } + + function updateThreshold(uint8 newThreshold) + public + onlyOwner + returns (bool success) + { + if (newThreshold > 0) { + require(newThreshold <= 10, "Threshold has maximum of 10"); + + threshold = newThreshold; + + return true; + } + + return false; + } + + // ------------------------------------------------------------------------ + // Don't accept ETH + // ------------------------------------------------------------------------ + receive() external payable { + revert(); + } + + // ------------------------------------------------------------------------ + // Owner can transfer out any accidentally sent ERC20 tokens + // ------------------------------------------------------------------------ + function transferAnyERC20Token(IERC20 tokenAddress, uint256 tokens) + public + onlyOwner + { + // We never transfer our RFOX to another addresses + require(tokenAddress != rfox, "Token locked"); + // Transfer any tokens + tokenAddress.safeTransfer(owner, tokens); + } + + /// @notice Function that lock the RFOX token when bridging + /// @dev Internal function, only call when bridging + /// @param from Owner of this bridge action + /// @param amount Quantity RFOX for bridging of this bridge action + function lock(address from, uint256 amount) internal { + totalLocked = totalLocked.add(amount); + rfox.safeTransferFrom(from, address(this), amount); + + emit Locked(from, amount); + } + + /// @notice Function that release the RFOX token when bridging + /// @dev Internal function, only call when bridging + /// @param to Address of receive bridging token + /// @param amount Quantity RFOX for bridging of this bridge action + function release(address to, uint256 amount) internal { + totalLocked = totalLocked.sub(amount); + rfox.safeTransfer(to, amount); + + emit Released(to, amount); + } +} diff --git a/contracts/mutants/ETHWAXBRIDGE/1/TOR/ETHWAXBRIDGE.sol b/contracts/mutants/ETHWAXBRIDGE/1/TOR/ETHWAXBRIDGE.sol new file mode 100644 index 00000000000..483540c3f01 --- /dev/null +++ b/contracts/mutants/ETHWAXBRIDGE/1/TOR/ETHWAXBRIDGE.sol @@ -0,0 +1,284 @@ +//SPDX-License-Identifier: MIT + +pragma solidity ^0.6.12; +pragma experimental ABIEncoderV2; + +import "@openzeppelin/contracts/token/ERC20/SafeERC20.sol"; + +import "./libraries/Endian.sol"; +//SWC-135-Code With No Effects:L10 +import "./interfaces/ERC20Interface.sol"; + +import "./Verify.sol"; +import "./Owned.sol"; + +// ---------------------------------------------------------------------------- +// Contract function to receive approval and execute function in one call +// +// Borrowed from MiniMeToken +// ---------------------------------------------------------------------------- +abstract contract ApproveAndCallFallBack { + function receiveApproval( + address from, + uint256 tokens, + address token, + bytes memory data + ) public virtual; +} + +contract Oracled is Owned { + mapping(address => bool) public oracles; + + modifier onlyOracle() { + require( + oracles[tx.origin] == true, + "Account is not a registered oracle" + ); + + _; + } + + function regOracle(address _newOracle) public onlyOwner { + require(!oracles[_newOracle], "Oracle is already registered"); + + oracles[_newOracle] = true; + } + + function unregOracle(address _remOracle) public onlyOwner { + require(oracles[_remOracle] == true, "Oracle is not registered"); + + delete oracles[_remOracle]; + } +} + +// ---------------------------------------------------------------------------- +// RFOX Bridge contract lock and release swap amount for each cross chain swap +// +// ---------------------------------------------------------------------------- +contract ETHWAXBRIDGE is Oracled, Verify { + using SafeMath for uint256; + using SafeERC20 for IERC20; + + // RFOX Token address + // Only using this address for bridging + IERC20 public rfox; + // Threshold meaning the minimum requirement for oracle confirmations + uint8 public threshold; + // ChainID for RFOX Bridge + uint8 public thisChainId; + // How many locked token in ETHWAXBRIDGE + uint256 public totalLocked; + // Mapping from transaction ID + mapping(uint64 => mapping(address => bool)) signed; + mapping(uint64 => bool) public claimed; + + event Bridge( + address indexed from, + string to, + uint256 tokens, + uint256 chainId + ); + event Claimed(uint64 id, address to, uint256 tokens); + + struct BridgeData { + uint64 id; + uint32 ts; + uint64 fromAddr; + uint256 quantity; + uint64 symbolRaw; + uint8 chainId; + address toAddress; + } + + event Locked(address from, uint256 amount); + event Released(address to, uint256 amount); + + // ------------------------------------------------------------------------ + // Constructor + // ------------------------------------------------------------------------ + constructor(IERC20 rfoxAddress) public { + uint8 chainId; + + threshold = 3; + rfox = rfoxAddress; + + assembly { + chainId := chainid() + } + + thisChainId = chainId; + } + + // ------------------------------------------------------------------------ + // Moves tokens to the inaccessible account and then sends event for the oracles + // to monitor and issue on other chain + // to : WAX address + // tokens : number of tokens in satoshis + // chainId : The chain id that they will be sent to + // ------------------------------------------------------------------------ + + function bridge( + string memory to, + uint256 tokens, + uint256 chainid + ) public returns (bool success) { + lock(msg.sender, tokens); + + emit Bridge(msg.sender, to, tokens, chainid); + emit Locked(msg.sender, tokens); + + return true; + } + + // ------------------------------------------------------------------------ + // Claim tokens sent using signatures supplied to the other chain + // ------------------------------------------------------------------------ + + function verifySigData(bytes memory sigData) + private + returns (BridgeData memory) + { + BridgeData memory td; + + uint64 oracleQuantity = 0; + uint64 id; + uint32 ts; + uint64 fromAddr; + uint64 symbolRaw; + uint8 chainId; + address toAddress; + + assembly { + id := mload(add(add(sigData, 0x8), 0)) + ts := mload(add(add(sigData, 0x4), 8)) + fromAddr := mload(add(add(sigData, 0x8), 12)) + oracleQuantity := mload(add(add(sigData, 0x8), 20)) + symbolRaw := mload(add(add(sigData, 0x8), 28)) + chainId := mload(add(add(sigData, 0x1), 36)) + toAddress := mload(add(add(sigData, 0x14), 37)) + } + + uint256 reversedQuantity = Endian.reverse64(oracleQuantity); + + td.id = Endian.reverse64(id); + td.ts = Endian.reverse32(ts); + td.fromAddr = Endian.reverse64(fromAddr); + td.quantity = uint256(reversedQuantity) * 1e10; + td.symbolRaw = Endian.reverse64(symbolRaw); + td.chainId = chainId; + td.toAddress = toAddress; + + require(thisChainId == td.chainId, "Invalid Chain ID"); + require( + block.timestamp < SafeMath.add(td.ts, (60 * 60 * 24 * 30)), + "Bridge has expired" + ); + + require(!claimed[td.id], "Already Claimed"); + + claimed[td.id] = true; + + return td; + } + + function claim(bytes memory sigData, bytes[] calldata signatures) + public + returns (address toAddress) + { + BridgeData memory td = verifySigData(sigData); + + // verify signatures + require(sigData.length == 69, "Signature data is the wrong size"); + require( + signatures.length <= 10, + "Maximum of 10 signatures can be provided" + ); + + bytes32 message = keccak256(sigData); + + uint8 numberSigs = 0; + + for (uint8 i = 0; i < signatures.length; i++) { + address potential = Verify.recoverSigner(message, signatures[i]); + + // Check that they are an oracle and they haven't signed twice + if (oracles[potential] && !signed[td.id][potential]) { + signed[td.id][potential] = true; + numberSigs++; + + if (numberSigs >= 10) { + break; + } + } + } + + require( + numberSigs >= threshold, + "Not enough valid signatures provided" + ); + + release(td.toAddress, td.quantity); + + emit Claimed(td.id, td.toAddress, td.quantity); + + return td.toAddress; + } + + function updateThreshold(uint8 newThreshold) + public + onlyOwner + returns (bool success) + { + if (newThreshold > 0) { + require(newThreshold <= 10, "Threshold has maximum of 10"); + + threshold = newThreshold; + + return true; + } + + return false; + } + + // ------------------------------------------------------------------------ + // Don't accept ETH + // ------------------------------------------------------------------------ + receive() external payable { + revert(); + } + + // ------------------------------------------------------------------------ + // Owner can transfer out any accidentally sent ERC20 tokens + // ------------------------------------------------------------------------ + function transferAnyERC20Token(IERC20 tokenAddress, uint256 tokens) + public + onlyOwner + { + // We never transfer our RFOX to another addresses + require(tokenAddress != rfox, "Token locked"); + // Transfer any tokens + tokenAddress.safeTransfer(owner, tokens); + } + + /// @notice Function that lock the RFOX token when bridging + /// @dev Internal function, only call when bridging + /// @param from Owner of this bridge action + /// @param amount Quantity RFOX for bridging of this bridge action + function lock(address from, uint256 amount) internal { + totalLocked = totalLocked.add(amount); + rfox.safeTransferFrom(from, address(this), amount); + + emit Locked(from, amount); + } + + /// @notice Function that release the RFOX token when bridging + /// @dev Internal function, only call when bridging + /// @param to Address of receive bridging token + /// @param amount Quantity RFOX for bridging of this bridge action + function release(address to, uint256 amount) internal { + totalLocked = totalLocked.sub(amount); + rfox.safeTransfer(to, amount); + + emit Released(to, amount); + } +} diff --git a/contracts/mutants/ETHWAXBRIDGE/1/UORD/ETHWAXBRIDGE.sol b/contracts/mutants/ETHWAXBRIDGE/1/UORD/ETHWAXBRIDGE.sol new file mode 100644 index 00000000000..1e9c17bf508 --- /dev/null +++ b/contracts/mutants/ETHWAXBRIDGE/1/UORD/ETHWAXBRIDGE.sol @@ -0,0 +1,284 @@ +//SPDX-License-Identifier: MIT + +pragma solidity ^0.6.12; +pragma experimental ABIEncoderV2; + +import "@openzeppelin/contracts/token/ERC20/SafeERC20.sol"; + +import "./libraries/Endian.sol"; +//SWC-135-Code With No Effects:L10 +import "./interfaces/ERC20Interface.sol"; + +import "./Verify.sol"; +import "./Owned.sol"; + +// ---------------------------------------------------------------------------- +// Contract function to receive approval and execute function in one call +// +// Borrowed from MiniMeToken +// ---------------------------------------------------------------------------- +abstract contract ApproveAndCallFallBack { + function receiveApproval( + address from, + uint256 tokens, + address token, + bytes memory data + ) public virtual; +} + +contract Oracled is Owned { + mapping(address => bool) public oracles; + + modifier onlyOracle() { + require( + oracles[msg.sender] == true, + "Account is not a registered oracle" + ); + + _; + } + + function regOracle(address _newOracle) public onlyOwner { + require( oracles[_newOracle], "Oracle is already registered"); + + oracles[_newOracle] = true; + } + + function unregOracle(address _remOracle) public onlyOwner { + require(oracles[_remOracle] == true, "Oracle is not registered"); + + delete oracles[_remOracle]; + } +} + +// ---------------------------------------------------------------------------- +// RFOX Bridge contract lock and release swap amount for each cross chain swap +// +// ---------------------------------------------------------------------------- +contract ETHWAXBRIDGE is Oracled, Verify { + using SafeMath for uint256; + using SafeERC20 for IERC20; + + // RFOX Token address + // Only using this address for bridging + IERC20 public rfox; + // Threshold meaning the minimum requirement for oracle confirmations + uint8 public threshold; + // ChainID for RFOX Bridge + uint8 public thisChainId; + // How many locked token in ETHWAXBRIDGE + uint256 public totalLocked; + // Mapping from transaction ID + mapping(uint64 => mapping(address => bool)) signed; + mapping(uint64 => bool) public claimed; + + event Bridge( + address indexed from, + string to, + uint256 tokens, + uint256 chainId + ); + event Claimed(uint64 id, address to, uint256 tokens); + + struct BridgeData { + uint64 id; + uint32 ts; + uint64 fromAddr; + uint256 quantity; + uint64 symbolRaw; + uint8 chainId; + address toAddress; + } + + event Locked(address from, uint256 amount); + event Released(address to, uint256 amount); + + // ------------------------------------------------------------------------ + // Constructor + // ------------------------------------------------------------------------ + constructor(IERC20 rfoxAddress) public { + uint8 chainId; + + threshold = 3; + rfox = rfoxAddress; + + assembly { + chainId := chainid() + } + + thisChainId = chainId; + } + + // ------------------------------------------------------------------------ + // Moves tokens to the inaccessible account and then sends event for the oracles + // to monitor and issue on other chain + // to : WAX address + // tokens : number of tokens in satoshis + // chainId : The chain id that they will be sent to + // ------------------------------------------------------------------------ + + function bridge( + string memory to, + uint256 tokens, + uint256 chainid + ) public returns (bool success) { + lock(msg.sender, tokens); + + emit Bridge(msg.sender, to, tokens, chainid); + emit Locked(msg.sender, tokens); + + return true; + } + + // ------------------------------------------------------------------------ + // Claim tokens sent using signatures supplied to the other chain + // ------------------------------------------------------------------------ + + function verifySigData(bytes memory sigData) + private + returns (BridgeData memory) + { + BridgeData memory td; + + uint64 oracleQuantity = 0; + uint64 id; + uint32 ts; + uint64 fromAddr; + uint64 symbolRaw; + uint8 chainId; + address toAddress; + + assembly { + id := mload(add(add(sigData, 0x8), 0)) + ts := mload(add(add(sigData, 0x4), 8)) + fromAddr := mload(add(add(sigData, 0x8), 12)) + oracleQuantity := mload(add(add(sigData, 0x8), 20)) + symbolRaw := mload(add(add(sigData, 0x8), 28)) + chainId := mload(add(add(sigData, 0x1), 36)) + toAddress := mload(add(add(sigData, 0x14), 37)) + } + + uint256 reversedQuantity = Endian.reverse64(oracleQuantity); + + td.id = Endian.reverse64(id); + td.ts = Endian.reverse32(ts); + td.fromAddr = Endian.reverse64(fromAddr); + td.quantity = uint256(reversedQuantity) * 1e10; + td.symbolRaw = Endian.reverse64(symbolRaw); + td.chainId = chainId; + td.toAddress = toAddress; + + require(thisChainId == td.chainId, "Invalid Chain ID"); + require( + block.timestamp < SafeMath.add(td.ts, (60 * 60 * 24 * 30)), + "Bridge has expired" + ); + + require(!claimed[td.id], "Already Claimed"); + + claimed[td.id] = true; + + return td; + } + + function claim(bytes memory sigData, bytes[] calldata signatures) + public + returns (address toAddress) + { + BridgeData memory td = verifySigData(sigData); + + // verify signatures + require(sigData.length == 69, "Signature data is the wrong size"); + require( + signatures.length <= 10, + "Maximum of 10 signatures can be provided" + ); + + bytes32 message = keccak256(sigData); + + uint8 numberSigs = 0; + + for (uint8 i = 0; i < signatures.length; i++) { + address potential = Verify.recoverSigner(message, signatures[i]); + + // Check that they are an oracle and they haven't signed twice + if (oracles[potential] && !signed[td.id][potential]) { + signed[td.id][potential] = true; + numberSigs++; + + if (numberSigs >= 10) { + break; + } + } + } + + require( + numberSigs >= threshold, + "Not enough valid signatures provided" + ); + + release(td.toAddress, td.quantity); + + emit Claimed(td.id, td.toAddress, td.quantity); + + return td.toAddress; + } + + function updateThreshold(uint8 newThreshold) + public + onlyOwner + returns (bool success) + { + if (newThreshold > 0) { + require(newThreshold <= 10, "Threshold has maximum of 10"); + + threshold = newThreshold; + + return true; + } + + return false; + } + + // ------------------------------------------------------------------------ + // Don't accept ETH + // ------------------------------------------------------------------------ + receive() external payable { + revert(); + } + + // ------------------------------------------------------------------------ + // Owner can transfer out any accidentally sent ERC20 tokens + // ------------------------------------------------------------------------ + function transferAnyERC20Token(IERC20 tokenAddress, uint256 tokens) + public + onlyOwner + { + // We never transfer our RFOX to another addresses + require(tokenAddress != rfox, "Token locked"); + // Transfer any tokens + tokenAddress.safeTransfer(owner, tokens); + } + + /// @notice Function that lock the RFOX token when bridging + /// @dev Internal function, only call when bridging + /// @param from Owner of this bridge action + /// @param amount Quantity RFOX for bridging of this bridge action + function lock(address from, uint256 amount) internal { + totalLocked = totalLocked.add(amount); + rfox.safeTransferFrom(from, address(this), amount); + + emit Locked(from, amount); + } + + /// @notice Function that release the RFOX token when bridging + /// @dev Internal function, only call when bridging + /// @param to Address of receive bridging token + /// @param amount Quantity RFOX for bridging of this bridge action + function release(address to, uint256 amount) internal { + totalLocked = totalLocked.sub(amount); + rfox.safeTransfer(to, amount); + + emit Released(to, amount); + } +} diff --git a/contracts/mutants/ETHWAXBRIDGE/1/VVR/ETHWAXBRIDGE.sol b/contracts/mutants/ETHWAXBRIDGE/1/VVR/ETHWAXBRIDGE.sol new file mode 100644 index 00000000000..d9b31e20221 --- /dev/null +++ b/contracts/mutants/ETHWAXBRIDGE/1/VVR/ETHWAXBRIDGE.sol @@ -0,0 +1,284 @@ +//SPDX-License-Identifier: MIT + +pragma solidity ^0.6.12; +pragma experimental ABIEncoderV2; + +import "@openzeppelin/contracts/token/ERC20/SafeERC20.sol"; + +import "./libraries/Endian.sol"; +//SWC-135-Code With No Effects:L10 +import "./interfaces/ERC20Interface.sol"; + +import "./Verify.sol"; +import "./Owned.sol"; + +// ---------------------------------------------------------------------------- +// Contract function to receive approval and execute function in one call +// +// Borrowed from MiniMeToken +// ---------------------------------------------------------------------------- +abstract contract ApproveAndCallFallBack { + function receiveApproval( + address from, + uint256 tokens, + address token, + bytes memory data + ) public virtual; +} + +contract Oracled is Owned { + mapping(address => bool) public oracles; + + modifier onlyOracle() { + require( + oracles[msg.sender] == true, + "Account is not a registered oracle" + ); + + _; + } + + function regOracle(address _newOracle) public onlyOwner { + require(!oracles[_newOracle], "Oracle is already registered"); + + oracles[_newOracle] = true; + } + + function unregOracle(address _remOracle) public onlyOwner { + require(oracles[_remOracle] == true, "Oracle is not registered"); + + delete oracles[_remOracle]; + } +} + +// ---------------------------------------------------------------------------- +// RFOX Bridge contract lock and release swap amount for each cross chain swap +// +// ---------------------------------------------------------------------------- +contract ETHWAXBRIDGE is Oracled, Verify { + using SafeMath for uint256; + using SafeERC20 for IERC20; + + // RFOX Token address + // Only using this address for bridging + IERC20 internal rfox; + // Threshold meaning the minimum requirement for oracle confirmations + uint8 public threshold; + // ChainID for RFOX Bridge + uint8 public thisChainId; + // How many locked token in ETHWAXBRIDGE + uint256 public totalLocked; + // Mapping from transaction ID + mapping(uint64 => mapping(address => bool)) signed; + mapping(uint64 => bool) public claimed; + + event Bridge( + address indexed from, + string to, + uint256 tokens, + uint256 chainId + ); + event Claimed(uint64 id, address to, uint256 tokens); + + struct BridgeData { + uint64 id; + uint32 ts; + uint64 fromAddr; + uint256 quantity; + uint64 symbolRaw; + uint8 chainId; + address toAddress; + } + + event Locked(address from, uint256 amount); + event Released(address to, uint256 amount); + + // ------------------------------------------------------------------------ + // Constructor + // ------------------------------------------------------------------------ + constructor(IERC20 rfoxAddress) public { + uint8 chainId; + + threshold = 3; + rfox = rfoxAddress; + + assembly { + chainId := chainid() + } + + thisChainId = chainId; + } + + // ------------------------------------------------------------------------ + // Moves tokens to the inaccessible account and then sends event for the oracles + // to monitor and issue on other chain + // to : WAX address + // tokens : number of tokens in satoshis + // chainId : The chain id that they will be sent to + // ------------------------------------------------------------------------ + + function bridge( + string memory to, + uint256 tokens, + uint256 chainid + ) public returns (bool success) { + lock(msg.sender, tokens); + + emit Bridge(msg.sender, to, tokens, chainid); + emit Locked(msg.sender, tokens); + + return true; + } + + // ------------------------------------------------------------------------ + // Claim tokens sent using signatures supplied to the other chain + // ------------------------------------------------------------------------ + + function verifySigData(bytes memory sigData) + private + returns (BridgeData memory) + { + BridgeData memory td; + + uint64 oracleQuantity = 0; + uint64 id; + uint32 ts; + uint64 fromAddr; + uint64 symbolRaw; + uint8 chainId; + address toAddress; + + assembly { + id := mload(add(add(sigData, 0x8), 0)) + ts := mload(add(add(sigData, 0x4), 8)) + fromAddr := mload(add(add(sigData, 0x8), 12)) + oracleQuantity := mload(add(add(sigData, 0x8), 20)) + symbolRaw := mload(add(add(sigData, 0x8), 28)) + chainId := mload(add(add(sigData, 0x1), 36)) + toAddress := mload(add(add(sigData, 0x14), 37)) + } + + uint256 reversedQuantity = Endian.reverse64(oracleQuantity); + + td.id = Endian.reverse64(id); + td.ts = Endian.reverse32(ts); + td.fromAddr = Endian.reverse64(fromAddr); + td.quantity = uint256(reversedQuantity) * 1e10; + td.symbolRaw = Endian.reverse64(symbolRaw); + td.chainId = chainId; + td.toAddress = toAddress; + + require(thisChainId == td.chainId, "Invalid Chain ID"); + require( + block.timestamp < SafeMath.add(td.ts, (60 * 60 * 24 * 30)), + "Bridge has expired" + ); + + require(!claimed[td.id], "Already Claimed"); + + claimed[td.id] = true; + + return td; + } + + function claim(bytes memory sigData, bytes[] calldata signatures) + public + returns (address toAddress) + { + BridgeData memory td = verifySigData(sigData); + + // verify signatures + require(sigData.length == 69, "Signature data is the wrong size"); + require( + signatures.length <= 10, + "Maximum of 10 signatures can be provided" + ); + + bytes32 message = keccak256(sigData); + + uint8 numberSigs = 0; + + for (uint8 i = 0; i < signatures.length; i++) { + address potential = Verify.recoverSigner(message, signatures[i]); + + // Check that they are an oracle and they haven't signed twice + if (oracles[potential] && !signed[td.id][potential]) { + signed[td.id][potential] = true; + numberSigs++; + + if (numberSigs >= 10) { + break; + } + } + } + + require( + numberSigs >= threshold, + "Not enough valid signatures provided" + ); + + release(td.toAddress, td.quantity); + + emit Claimed(td.id, td.toAddress, td.quantity); + + return td.toAddress; + } + + function updateThreshold(uint8 newThreshold) + public + onlyOwner + returns (bool success) + { + if (newThreshold > 0) { + require(newThreshold <= 10, "Threshold has maximum of 10"); + + threshold = newThreshold; + + return true; + } + + return false; + } + + // ------------------------------------------------------------------------ + // Don't accept ETH + // ------------------------------------------------------------------------ + receive() external payable { + revert(); + } + + // ------------------------------------------------------------------------ + // Owner can transfer out any accidentally sent ERC20 tokens + // ------------------------------------------------------------------------ + function transferAnyERC20Token(IERC20 tokenAddress, uint256 tokens) + public + onlyOwner + { + // We never transfer our RFOX to another addresses + require(tokenAddress != rfox, "Token locked"); + // Transfer any tokens + tokenAddress.safeTransfer(owner, tokens); + } + + /// @notice Function that lock the RFOX token when bridging + /// @dev Internal function, only call when bridging + /// @param from Owner of this bridge action + /// @param amount Quantity RFOX for bridging of this bridge action + function lock(address from, uint256 amount) internal { + totalLocked = totalLocked.add(amount); + rfox.safeTransferFrom(from, address(this), amount); + + emit Locked(from, amount); + } + + /// @notice Function that release the RFOX token when bridging + /// @dev Internal function, only call when bridging + /// @param to Address of receive bridging token + /// @param amount Quantity RFOX for bridging of this bridge action + function release(address to, uint256 amount) internal { + totalLocked = totalLocked.sub(amount); + rfox.safeTransfer(to, amount); + + emit Released(to, amount); + } +} diff --git a/contracts/mutants/ETHWAXBRIDGE/10/BOR/ETHWAXBRIDGE.sol b/contracts/mutants/ETHWAXBRIDGE/10/BOR/ETHWAXBRIDGE.sol new file mode 100644 index 00000000000..e6c496884a0 --- /dev/null +++ b/contracts/mutants/ETHWAXBRIDGE/10/BOR/ETHWAXBRIDGE.sol @@ -0,0 +1,284 @@ +//SPDX-License-Identifier: MIT + +pragma solidity ^0.6.12; +pragma experimental ABIEncoderV2; + +import "@openzeppelin/contracts/token/ERC20/SafeERC20.sol"; + +import "./libraries/Endian.sol"; +//SWC-135-Code With No Effects:L10 +import "./interfaces/ERC20Interface.sol"; + +import "./Verify.sol"; +import "./Owned.sol"; + +// ---------------------------------------------------------------------------- +// Contract function to receive approval and execute function in one call +// +// Borrowed from MiniMeToken +// ---------------------------------------------------------------------------- +abstract contract ApproveAndCallFallBack { + function receiveApproval( + address from, + uint256 tokens, + address token, + bytes memory data + ) public virtual; +} + +contract Oracled is Owned { + mapping(address => bool) public oracles; + + modifier onlyOracle() { + require( + oracles[msg.sender] <= true, + "Account is not a registered oracle" + ); + + _; + } + + function regOracle(address _newOracle) public onlyOwner { + require(!oracles[_newOracle], "Oracle is already registered"); + + oracles[_newOracle] = true; + } + + function unregOracle(address _remOracle) public onlyOwner { + require(oracles[_remOracle] <= true, "Oracle is not registered"); + + delete oracles[_remOracle]; + } +} + +// ---------------------------------------------------------------------------- +// RFOX Bridge contract lock and release swap amount for each cross chain swap +// +// ---------------------------------------------------------------------------- +contract ETHWAXBRIDGE is Oracled, Verify { + using SafeMath for uint256; + using SafeERC20 for IERC20; + + // RFOX Token address + // Only using this address for bridging + IERC20 public rfox; + // Threshold meaning the minimum requirement for oracle confirmations + uint8 public threshold; + // ChainID for RFOX Bridge + uint8 public thisChainId; + // How many locked token in ETHWAXBRIDGE + uint256 public totalLocked; + // Mapping from transaction ID + mapping(uint64 => mapping(address => bool)) signed; + mapping(uint64 => bool) public claimed; + + event Bridge( + address indexed from, + string to, + uint256 tokens, + uint256 chainId + ); + event Claimed(uint64 id, address to, uint256 tokens); + + struct BridgeData { + uint64 id; + uint32 ts; + uint64 fromAddr; + uint256 quantity; + uint64 symbolRaw; + uint8 chainId; + address toAddress; + } + + event Locked(address from, uint256 amount); + event Released(address to, uint256 amount); + + // ------------------------------------------------------------------------ + // Constructor + // ------------------------------------------------------------------------ + constructor(IERC20 rfoxAddress) public { + uint8 chainId; + + threshold = 3; + rfox = rfoxAddress; + + assembly { + chainId := chainid() + } + + thisChainId = chainId; + } + + // ------------------------------------------------------------------------ + // Moves tokens to the inaccessible account and then sends event for the oracles + // to monitor and issue on other chain + // to : WAX address + // tokens : number of tokens in satoshis + // chainId : The chain id that they will be sent to + // ------------------------------------------------------------------------ + + function bridge( + string memory to, + uint256 tokens, + uint256 chainid + ) public returns (bool success) { + lock(msg.sender, tokens); + + emit Bridge(msg.sender, to, tokens, chainid); + emit Locked(msg.sender, tokens); + + return true; + } + + // ------------------------------------------------------------------------ + // Claim tokens sent using signatures supplied to the other chain + // ------------------------------------------------------------------------ + + function verifySigData(bytes memory sigData) + private + returns (BridgeData memory) + { + BridgeData memory td; + + uint64 oracleQuantity = 0; + uint64 id; + uint32 ts; + uint64 fromAddr; + uint64 symbolRaw; + uint8 chainId; + address toAddress; + + assembly { + id := mload(add(add(sigData, 0x8), 0)) + ts := mload(add(add(sigData, 0x4), 8)) + fromAddr := mload(add(add(sigData, 0x8), 12)) + oracleQuantity := mload(add(add(sigData, 0x8), 20)) + symbolRaw := mload(add(add(sigData, 0x8), 28)) + chainId := mload(add(add(sigData, 0x1), 36)) + toAddress := mload(add(add(sigData, 0x14), 37)) + } + + uint256 reversedQuantity = Endian.reverse64(oracleQuantity); + + td.id = Endian.reverse64(id); + td.ts = Endian.reverse32(ts); + td.fromAddr = Endian.reverse64(fromAddr); + td.quantity = uint256(reversedQuantity) + 1e10; + td.symbolRaw = Endian.reverse64(symbolRaw); + td.chainId = chainId; + td.toAddress = toAddress; + + require(thisChainId <= td.chainId, "Invalid Chain ID"); + require( + block.timestamp <= SafeMath.add(td.ts, (60 + 60 + 24 + 30)), + "Bridge has expired" + ); + + require(!claimed[td.id], "Already Claimed"); + + claimed[td.id] = true; + + return td; + } + + function claim(bytes memory sigData, bytes[] calldata signatures) + public + returns (address toAddress) + { + BridgeData memory td = verifySigData(sigData); + + // verify signatures + require(sigData.length <= 69, "Signature data is the wrong size"); + require( + signatures.length < 10, + "Maximum of 10 signatures can be provided" + ); + + bytes32 message = keccak256(sigData); + + uint8 numberSigs = 0; + + for (uint8 i = 0; i < signatures.length; i++) { + address potential = Verify.recoverSigner(message, signatures[i]); + + // Check that they are an oracle and they haven't signed twice + if (oracles[potential] && !signed[td.id][potential]) { + signed[td.id][potential] = true; + numberSigs++; + + if (numberSigs >= 10) { + break; + } + } + } + + require( + numberSigs >= threshold, + "Not enough valid signatures provided" + ); + + release(td.toAddress, td.quantity); + + emit Claimed(td.id, td.toAddress, td.quantity); + + return td.toAddress; + } + + function updateThreshold(uint8 newThreshold) + public + onlyOwner + returns (bool success) + { + if (newThreshold > 0) { + require(newThreshold <= 10, "Threshold has maximum of 10"); + + threshold = newThreshold; + + return true; + } + + return false; + } + + // ------------------------------------------------------------------------ + // Don't accept ETH + // ------------------------------------------------------------------------ + receive() external payable { + revert(); + } + + // ------------------------------------------------------------------------ + // Owner can transfer out any accidentally sent ERC20 tokens + // ------------------------------------------------------------------------ + function transferAnyERC20Token(IERC20 tokenAddress, uint256 tokens) + public + onlyOwner + { + // We never transfer our RFOX to another addresses + require(tokenAddress != rfox, "Token locked"); + // Transfer any tokens + tokenAddress.safeTransfer(owner, tokens); + } + + /// @notice Function that lock the RFOX token when bridging + /// @dev Internal function, only call when bridging + /// @param from Owner of this bridge action + /// @param amount Quantity RFOX for bridging of this bridge action + function lock(address from, uint256 amount) internal { + totalLocked = totalLocked.add(amount); + rfox.safeTransferFrom(from, address(this), amount); + + emit Locked(from, amount); + } + + /// @notice Function that release the RFOX token when bridging + /// @dev Internal function, only call when bridging + /// @param to Address of receive bridging token + /// @param amount Quantity RFOX for bridging of this bridge action + function release(address to, uint256 amount) internal { + totalLocked = totalLocked.sub(amount); + rfox.safeTransfer(to, amount); + + emit Released(to, amount); + } +} diff --git a/contracts/mutants/ETHWAXBRIDGE/10/EHC/ETHWAXBRIDGE.sol b/contracts/mutants/ETHWAXBRIDGE/10/EHC/ETHWAXBRIDGE.sol new file mode 100644 index 00000000000..da2ba3b3a22 --- /dev/null +++ b/contracts/mutants/ETHWAXBRIDGE/10/EHC/ETHWAXBRIDGE.sol @@ -0,0 +1,284 @@ +//SPDX-License-Identifier: MIT + +pragma solidity ^0.6.12; +pragma experimental ABIEncoderV2; + +import "@openzeppelin/contracts/token/ERC20/SafeERC20.sol"; + +import "./libraries/Endian.sol"; +//SWC-135-Code With No Effects:L10 +import "./interfaces/ERC20Interface.sol"; + +import "./Verify.sol"; +import "./Owned.sol"; + +// ---------------------------------------------------------------------------- +// Contract function to receive approval and execute function in one call +// +// Borrowed from MiniMeToken +// ---------------------------------------------------------------------------- +abstract contract ApproveAndCallFallBack { + function receiveApproval( + address from, + uint256 tokens, + address token, + bytes memory data + ) public virtual; +} + +contract Oracled is Owned { + mapping(address => bool) public oracles; + + modifier onlyOracle() { + /* require( + oracles[msg.sender] == true, + "Account is not a registered oracle" + ); */ + + _; + } + + function regOracle(address _newOracle) public onlyOwner { + /* require(!oracles[_newOracle], "Oracle is already registered"); */ + + oracles[_newOracle] = true; + } + + function unregOracle(address _remOracle) public onlyOwner { + /* require(oracles[_remOracle] == true, "Oracle is not registered"); */ + + delete oracles[_remOracle]; + } +} + +// ---------------------------------------------------------------------------- +// RFOX Bridge contract lock and release swap amount for each cross chain swap +// +// ---------------------------------------------------------------------------- +contract ETHWAXBRIDGE is Oracled, Verify { + using SafeMath for uint256; + using SafeERC20 for IERC20; + + // RFOX Token address + // Only using this address for bridging + IERC20 public rfox; + // Threshold meaning the minimum requirement for oracle confirmations + uint8 public threshold; + // ChainID for RFOX Bridge + uint8 public thisChainId; + // How many locked token in ETHWAXBRIDGE + uint256 public totalLocked; + // Mapping from transaction ID + mapping(uint64 => mapping(address => bool)) signed; + mapping(uint64 => bool) public claimed; + + event Bridge( + address indexed from, + string to, + uint256 tokens, + uint256 chainId + ); + event Claimed(uint64 id, address to, uint256 tokens); + + struct BridgeData { + uint64 id; + uint32 ts; + uint64 fromAddr; + uint256 quantity; + uint64 symbolRaw; + uint8 chainId; + address toAddress; + } + + event Locked(address from, uint256 amount); + event Released(address to, uint256 amount); + + // ------------------------------------------------------------------------ + // Constructor + // ------------------------------------------------------------------------ + constructor(IERC20 rfoxAddress) public { + uint8 chainId; + + threshold = 3; + rfox = rfoxAddress; + + assembly { + chainId := chainid() + } + + thisChainId = chainId; + } + + // ------------------------------------------------------------------------ + // Moves tokens to the inaccessible account and then sends event for the oracles + // to monitor and issue on other chain + // to : WAX address + // tokens : number of tokens in satoshis + // chainId : The chain id that they will be sent to + // ------------------------------------------------------------------------ + + function bridge( + string memory to, + uint256 tokens, + uint256 chainid + ) public returns (bool success) { + lock(msg.sender, tokens); + + emit Bridge(msg.sender, to, tokens, chainid); + emit Locked(msg.sender, tokens); + + return true; + } + + // ------------------------------------------------------------------------ + // Claim tokens sent using signatures supplied to the other chain + // ------------------------------------------------------------------------ + + function verifySigData(bytes memory sigData) + private + returns (BridgeData memory) + { + BridgeData memory td; + + uint64 oracleQuantity = 0; + uint64 id; + uint32 ts; + uint64 fromAddr; + uint64 symbolRaw; + uint8 chainId; + address toAddress; + + assembly { + id := mload(add(add(sigData, 0x8), 0)) + ts := mload(add(add(sigData, 0x4), 8)) + fromAddr := mload(add(add(sigData, 0x8), 12)) + oracleQuantity := mload(add(add(sigData, 0x8), 20)) + symbolRaw := mload(add(add(sigData, 0x8), 28)) + chainId := mload(add(add(sigData, 0x1), 36)) + toAddress := mload(add(add(sigData, 0x14), 37)) + } + + uint256 reversedQuantity = Endian.reverse64(oracleQuantity); + + td.id = Endian.reverse64(id); + td.ts = Endian.reverse32(ts); + td.fromAddr = Endian.reverse64(fromAddr); + td.quantity = uint256(reversedQuantity) * 1e10; + td.symbolRaw = Endian.reverse64(symbolRaw); + td.chainId = chainId; + td.toAddress = toAddress; + + /* require(thisChainId == td.chainId, "Invalid Chain ID"); */ + /* require( + block.timestamp < SafeMath.add(td.ts, (60 * 60 * 24 * 30)), + "Bridge has expired" + ); */ + + /* require(!claimed[td.id], "Already Claimed"); */ + + claimed[td.id] = true; + + return td; + } + + function claim(bytes memory sigData, bytes[] calldata signatures) + public + returns (address toAddress) + { + BridgeData memory td = verifySigData(sigData); + + // verify signatures + /* require(sigData.length == 69, "Signature data is the wrong size"); */ + /* require( + signatures.length <= 10, + "Maximum of 10 signatures can be provided" + ); */ + + bytes32 message = keccak256(sigData); + + uint8 numberSigs = 0; + + for (uint8 i = 0; i < signatures.length; i++) { + address potential = Verify.recoverSigner(message, signatures[i]); + + // Check that they are an oracle and they haven't signed twice + if (oracles[potential] && !signed[td.id][potential]) { + signed[td.id][potential] = true; + numberSigs++; + + if (numberSigs >= 10) { + break; + } + } + } + + /* require( + numberSigs >= threshold, + "Not enough valid signatures provided" + ); */ + + release(td.toAddress, td.quantity); + + emit Claimed(td.id, td.toAddress, td.quantity); + + return td.toAddress; + } + + function updateThreshold(uint8 newThreshold) + public + onlyOwner + returns (bool success) + { + if (newThreshold > 0) { + /* require(newThreshold <= 10, "Threshold has maximum of 10"); */ + + threshold = newThreshold; + + return true; + } + + return false; + } + + // ------------------------------------------------------------------------ + // Don't accept ETH + // ------------------------------------------------------------------------ + receive() external payable { + revert(); + } + + // ------------------------------------------------------------------------ + // Owner can transfer out any accidentally sent ERC20 tokens + // ------------------------------------------------------------------------ + function transferAnyERC20Token(IERC20 tokenAddress, uint256 tokens) + public + onlyOwner + { + // We never transfer our RFOX to another addresses + require(tokenAddress != rfox, "Token locked"); + // Transfer any tokens + tokenAddress.safeTransfer(owner, tokens); + } + + /// @notice Function that lock the RFOX token when bridging + /// @dev Internal function, only call when bridging + /// @param from Owner of this bridge action + /// @param amount Quantity RFOX for bridging of this bridge action + function lock(address from, uint256 amount) internal { + totalLocked = totalLocked.add(amount); + rfox.safeTransferFrom(from, address(this), amount); + + emit Locked(from, amount); + } + + /// @notice Function that release the RFOX token when bridging + /// @dev Internal function, only call when bridging + /// @param to Address of receive bridging token + /// @param amount Quantity RFOX for bridging of this bridge action + function release(address to, uint256 amount) internal { + totalLocked = totalLocked.sub(amount); + rfox.safeTransfer(to, amount); + + emit Released(to, amount); + } +} diff --git a/contracts/mutants/ETHWAXBRIDGE/10/FVR/ETHWAXBRIDGE.sol b/contracts/mutants/ETHWAXBRIDGE/10/FVR/ETHWAXBRIDGE.sol new file mode 100644 index 00000000000..5e68d436e91 --- /dev/null +++ b/contracts/mutants/ETHWAXBRIDGE/10/FVR/ETHWAXBRIDGE.sol @@ -0,0 +1,284 @@ +//SPDX-License-Identifier: MIT + +pragma solidity ^0.6.12; +pragma experimental ABIEncoderV2; + +import "@openzeppelin/contracts/token/ERC20/SafeERC20.sol"; + +import "./libraries/Endian.sol"; +//SWC-135-Code With No Effects:L10 +import "./interfaces/ERC20Interface.sol"; + +import "./Verify.sol"; +import "./Owned.sol"; + +// ---------------------------------------------------------------------------- +// Contract function to receive approval and execute function in one call +// +// Borrowed from MiniMeToken +// ---------------------------------------------------------------------------- +abstract contract ApproveAndCallFallBack { + function receiveApproval( + address from, + uint256 tokens, + address token, + bytes memory data + ) public virtual; +} + +contract Oracled is Owned { + mapping(address => bool) public oracles; + + modifier onlyOracle() { + require( + oracles[msg.sender] == true, + "Account is not a registered oracle" + ); + + _; + } + + function regOracle(address _newOracle) external onlyOwner { + require(!oracles[_newOracle], "Oracle is already registered"); + + oracles[_newOracle] = true; + } + + function unregOracle(address _remOracle) external onlyOwner { + require(oracles[_remOracle] == true, "Oracle is not registered"); + + delete oracles[_remOracle]; + } +} + +// ---------------------------------------------------------------------------- +// RFOX Bridge contract lock and release swap amount for each cross chain swap +// +// ---------------------------------------------------------------------------- +contract ETHWAXBRIDGE is Oracled, Verify { + using SafeMath for uint256; + using SafeERC20 for IERC20; + + // RFOX Token address + // Only using this address for bridging + IERC20 public rfox; + // Threshold meaning the minimum requirement for oracle confirmations + uint8 public threshold; + // ChainID for RFOX Bridge + uint8 public thisChainId; + // How many locked token in ETHWAXBRIDGE + uint256 public totalLocked; + // Mapping from transaction ID + mapping(uint64 => mapping(address => bool)) signed; + mapping(uint64 => bool) public claimed; + + event Bridge( + address indexed from, + string to, + uint256 tokens, + uint256 chainId + ); + event Claimed(uint64 id, address to, uint256 tokens); + + struct BridgeData { + uint64 id; + uint32 ts; + uint64 fromAddr; + uint256 quantity; + uint64 symbolRaw; + uint8 chainId; + address toAddress; + } + + event Locked(address from, uint256 amount); + event Released(address to, uint256 amount); + + // ------------------------------------------------------------------------ + // Constructor + // ------------------------------------------------------------------------ + constructor(IERC20 rfoxAddress) internal { + uint8 chainId; + + threshold = 3; + rfox = rfoxAddress; + + assembly { + chainId := chainid() + } + + thisChainId = chainId; + } + + // ------------------------------------------------------------------------ + // Moves tokens to the inaccessible account and then sends event for the oracles + // to monitor and issue on other chain + // to : WAX address + // tokens : number of tokens in satoshis + // chainId : The chain id that they will be sent to + // ------------------------------------------------------------------------ + + function bridge( + string memory to, + uint256 tokens, + uint256 chainid + ) external returns (bool success) { + lock(msg.sender, tokens); + + emit Bridge(msg.sender, to, tokens, chainid); + emit Locked(msg.sender, tokens); + + return true; + } + + // ------------------------------------------------------------------------ + // Claim tokens sent using signatures supplied to the other chain + // ------------------------------------------------------------------------ + + function verifySigData(bytes memory sigData) + public + returns (BridgeData memory) + { + BridgeData memory td; + + uint64 oracleQuantity = 0; + uint64 id; + uint32 ts; + uint64 fromAddr; + uint64 symbolRaw; + uint8 chainId; + address toAddress; + + assembly { + id := mload(add(add(sigData, 0x8), 0)) + ts := mload(add(add(sigData, 0x4), 8)) + fromAddr := mload(add(add(sigData, 0x8), 12)) + oracleQuantity := mload(add(add(sigData, 0x8), 20)) + symbolRaw := mload(add(add(sigData, 0x8), 28)) + chainId := mload(add(add(sigData, 0x1), 36)) + toAddress := mload(add(add(sigData, 0x14), 37)) + } + + uint256 reversedQuantity = Endian.reverse64(oracleQuantity); + + td.id = Endian.reverse64(id); + td.ts = Endian.reverse32(ts); + td.fromAddr = Endian.reverse64(fromAddr); + td.quantity = uint256(reversedQuantity) * 1e10; + td.symbolRaw = Endian.reverse64(symbolRaw); + td.chainId = chainId; + td.toAddress = toAddress; + + require(thisChainId == td.chainId, "Invalid Chain ID"); + require( + block.timestamp < SafeMath.add(td.ts, (60 * 60 * 24 * 30)), + "Bridge has expired" + ); + + require(!claimed[td.id], "Already Claimed"); + + claimed[td.id] = true; + + return td; + } + + function claim(bytes memory sigData, bytes[] calldata signatures) + external + returns (address toAddress) + { + BridgeData memory td = verifySigData(sigData); + + // verify signatures + require(sigData.length == 69, "Signature data is the wrong size"); + require( + signatures.length <= 10, + "Maximum of 10 signatures can be provided" + ); + + bytes32 message = keccak256(sigData); + + uint8 numberSigs = 0; + + for (uint8 i = 0; i < signatures.length; i++) { + address potential = Verify.recoverSigner(message, signatures[i]); + + // Check that they are an oracle and they haven't signed twice + if (oracles[potential] && !signed[td.id][potential]) { + signed[td.id][potential] = true; + numberSigs++; + + if (numberSigs >= 10) { + break; + } + } + } + + require( + numberSigs >= threshold, + "Not enough valid signatures provided" + ); + + release(td.toAddress, td.quantity); + + emit Claimed(td.id, td.toAddress, td.quantity); + + return td.toAddress; + } + + function updateThreshold(uint8 newThreshold) + external + onlyOwner + returns (bool success) + { + if (newThreshold > 0) { + require(newThreshold <= 10, "Threshold has maximum of 10"); + + threshold = newThreshold; + + return true; + } + + return false; + } + + // ------------------------------------------------------------------------ + // Don't accept ETH + // ------------------------------------------------------------------------ + receive() external payable { + revert(); + } + + // ------------------------------------------------------------------------ + // Owner can transfer out any accidentally sent ERC20 tokens + // ------------------------------------------------------------------------ + function transferAnyERC20Token(IERC20 tokenAddress, uint256 tokens) + external + onlyOwner + { + // We never transfer our RFOX to another addresses + require(tokenAddress != rfox, "Token locked"); + // Transfer any tokens + tokenAddress.safeTransfer(owner, tokens); + } + + /// @notice Function that lock the RFOX token when bridging + /// @dev Internal function, only call when bridging + /// @param from Owner of this bridge action + /// @param amount Quantity RFOX for bridging of this bridge action + function lock(address from, uint256 amount) public { + totalLocked = totalLocked.add(amount); + rfox.safeTransferFrom(from, address(this), amount); + + emit Locked(from, amount); + } + + /// @notice Function that release the RFOX token when bridging + /// @dev Internal function, only call when bridging + /// @param to Address of receive bridging token + /// @param amount Quantity RFOX for bridging of this bridge action + function release(address to, uint256 amount) public { + totalLocked = totalLocked.sub(amount); + rfox.safeTransfer(to, amount); + + emit Released(to, amount); + } +} diff --git a/contracts/mutants/ETHWAXBRIDGE/10/ILR/ETHWAXBRIDGE.sol b/contracts/mutants/ETHWAXBRIDGE/10/ILR/ETHWAXBRIDGE.sol new file mode 100644 index 00000000000..518c9aadd4e --- /dev/null +++ b/contracts/mutants/ETHWAXBRIDGE/10/ILR/ETHWAXBRIDGE.sol @@ -0,0 +1,284 @@ +//SPDX-License-Identifier: MIT + +pragma solidity ^0.6.12; +pragma experimental ABIEncoderV2; + +import "@openzeppelin/contracts/token/ERC20/SafeERC20.sol"; + +import "./libraries/Endian.sol"; +//SWC-135-Code With No Effects:L10 +import "./interfaces/ERC20Interface.sol"; + +import "./Verify.sol"; +import "./Owned.sol"; + +// ---------------------------------------------------------------------------- +// Contract function to receive approval and execute function in one call +// +// Borrowed from MiniMeToken +// ---------------------------------------------------------------------------- +abstract contract ApproveAndCallFallBack { + function receiveApproval( + address from, + uint256 tokens, + address token, + bytes memory data + ) public virtual; +} + +contract Oracled is Owned { + mapping(address => bool) public oracles; + + modifier onlyOracle() { + require( + oracles[msg.sender] == true, + "Account is not a registered oracle" + ); + + _; + } + + function regOracle(address _newOracle) public onlyOwner { + require(!oracles[_newOracle], "Oracle is already registered"); + + oracles[_newOracle] = true; + } + + function unregOracle(address _remOracle) public onlyOwner { + require(oracles[_remOracle] == true, "Oracle is not registered"); + + delete oracles[_remOracle]; + } +} + +// ---------------------------------------------------------------------------- +// RFOX Bridge contract lock and release swap amount for each cross chain swap +// +// ---------------------------------------------------------------------------- +contract ETHWAXBRIDGE is Oracled, Verify { + using SafeMath for uint256; + using SafeERC20 for IERC20; + + // RFOX Token address + // Only using this address for bridging + IERC20 public rfox; + // Threshold meaning the minimum requirement for oracle confirmations + uint8 public threshold; + // ChainID for RFOX Bridge + uint8 public thisChainId; + // How many locked token in ETHWAXBRIDGE + uint256 public totalLocked; + // Mapping from transaction ID + mapping(uint64 => mapping(address => bool)) signed; + mapping(uint64 => bool) public claimed; + + event Bridge( + address indexed from, + string to, + uint256 tokens, + uint256 chainId + ); + event Claimed(uint64 id, address to, uint256 tokens); + + struct BridgeData { + uint64 id; + uint32 ts; + uint64 fromAddr; + uint256 quantity; + uint64 symbolRaw; + uint8 chainId; + address toAddress; + } + + event Locked(address from, uint256 amount); + event Released(address to, uint256 amount); + + // ------------------------------------------------------------------------ + // Constructor + // ------------------------------------------------------------------------ + constructor(IERC20 rfoxAddress) public { + uint8 chainId; + + threshold = 2; + rfox = rfoxAddress; + + assembly { + chainId := chainid() + } + + thisChainId = chainId; + } + + // ------------------------------------------------------------------------ + // Moves tokens to the inaccessible account and then sends event for the oracles + // to monitor and issue on other chain + // to : WAX address + // tokens : number of tokens in satoshis + // chainId : The chain id that they will be sent to + // ------------------------------------------------------------------------ + + function bridge( + string memory to, + uint256 tokens, + uint256 chainid + ) public returns (bool success) { + lock(msg.sender, tokens); + + emit Bridge(msg.sender, to, tokens, chainid); + emit Locked(msg.sender, tokens); + + return true; + } + + // ------------------------------------------------------------------------ + // Claim tokens sent using signatures supplied to the other chain + // ------------------------------------------------------------------------ + + function verifySigData(bytes memory sigData) + private + returns (BridgeData memory) + { + BridgeData memory td; + + uint64 oracleQuantity = 1; + uint64 id; + uint32 ts; + uint64 fromAddr; + uint64 symbolRaw; + uint8 chainId; + address toAddress; + + assembly { + id := mload(add(add(sigData, 0x8), 0)) + ts := mload(add(add(sigData, 0x4), 8)) + fromAddr := mload(add(add(sigData, 0x8), 12)) + oracleQuantity := mload(add(add(sigData, 0x8), 20)) + symbolRaw := mload(add(add(sigData, 0x8), 28)) + chainId := mload(add(add(sigData, 0x1), 36)) + toAddress := mload(add(add(sigData, 0x14), 37)) + } + + uint256 reversedQuantity = Endian.reverse64(oracleQuantity); + + td.id = Endian.reverse64(id); + td.ts = Endian.reverse32(ts); + td.fromAddr = Endian.reverse64(fromAddr); + td.quantity = uint256(reversedQuantity) * 9999999999; + td.symbolRaw = Endian.reverse64(symbolRaw); + td.chainId = chainId; + td.toAddress = toAddress; + + require(thisChainId == td.chainId, "Invalid Chain ID"); + require( + block.timestamp < SafeMath.add(td.ts, (59 * 59 * 23 * 29)), + "Bridge has expired" + ); + + require(!claimed[td.id], "Already Claimed"); + + claimed[td.id] = true; + + return td; + } + + function claim(bytes memory sigData, bytes[] calldata signatures) + public + returns (address toAddress) + { + BridgeData memory td = verifySigData(sigData); + + // verify signatures + require(sigData.length == 68, "Signature data is the wrong size"); + require( + signatures.length <= 9, + "Maximum of 10 signatures can be provided" + ); + + bytes32 message = keccak256(sigData); + + uint8 numberSigs = 1; + + for (uint8 i = 0; i < signatures.length; i++) { + address potential = Verify.recoverSigner(message, signatures[i]); + + // Check that they are an oracle and they haven't signed twice + if (oracles[potential] && !signed[td.id][potential]) { + signed[td.id][potential] = true; + numberSigs++; + + if (numberSigs >= 10) { + break; + } + } + } + + require( + numberSigs >= threshold, + "Not enough valid signatures provided" + ); + + release(td.toAddress, td.quantity); + + emit Claimed(td.id, td.toAddress, td.quantity); + + return td.toAddress; + } + + function updateThreshold(uint8 newThreshold) + public + onlyOwner + returns (bool success) + { + if (newThreshold > 0) { + require(newThreshold <= 10, "Threshold has maximum of 10"); + + threshold = newThreshold; + + return true; + } + + return false; + } + + // ------------------------------------------------------------------------ + // Don't accept ETH + // ------------------------------------------------------------------------ + receive() external payable { + revert(); + } + + // ------------------------------------------------------------------------ + // Owner can transfer out any accidentally sent ERC20 tokens + // ------------------------------------------------------------------------ + function transferAnyERC20Token(IERC20 tokenAddress, uint256 tokens) + public + onlyOwner + { + // We never transfer our RFOX to another addresses + require(tokenAddress != rfox, "Token locked"); + // Transfer any tokens + tokenAddress.safeTransfer(owner, tokens); + } + + /// @notice Function that lock the RFOX token when bridging + /// @dev Internal function, only call when bridging + /// @param from Owner of this bridge action + /// @param amount Quantity RFOX for bridging of this bridge action + function lock(address from, uint256 amount) internal { + totalLocked = totalLocked.add(amount); + rfox.safeTransferFrom(from, address(this), amount); + + emit Locked(from, amount); + } + + /// @notice Function that release the RFOX token when bridging + /// @dev Internal function, only call when bridging + /// @param to Address of receive bridging token + /// @param amount Quantity RFOX for bridging of this bridge action + function release(address to, uint256 amount) internal { + totalLocked = totalLocked.sub(amount); + rfox.safeTransfer(to, amount); + + emit Released(to, amount); + } +} diff --git a/contracts/mutants/ETHWAXBRIDGE/2/BLR/ETHWAXBRIDGE.sol b/contracts/mutants/ETHWAXBRIDGE/2/BLR/ETHWAXBRIDGE.sol new file mode 100644 index 00000000000..744745b6445 --- /dev/null +++ b/contracts/mutants/ETHWAXBRIDGE/2/BLR/ETHWAXBRIDGE.sol @@ -0,0 +1,284 @@ +//SPDX-License-Identifier: MIT + +pragma solidity ^0.6.12; +pragma experimental ABIEncoderV2; + +import "@openzeppelin/contracts/token/ERC20/SafeERC20.sol"; + +import "./libraries/Endian.sol"; +//SWC-135-Code With No Effects:L10 +import "./interfaces/ERC20Interface.sol"; + +import "./Verify.sol"; +import "./Owned.sol"; + +// ---------------------------------------------------------------------------- +// Contract function to receive approval and execute function in one call +// +// Borrowed from MiniMeToken +// ---------------------------------------------------------------------------- +abstract contract ApproveAndCallFallBack { + function receiveApproval( + address from, + uint256 tokens, + address token, + bytes memory data + ) public virtual; +} + +contract Oracled is Owned { + mapping(address => bool) public oracles; + + modifier onlyOracle() { + require( + oracles[msg.sender] == false, + "Account is not a registered oracle" + ); + + _; + } + + function regOracle(address _newOracle) public onlyOwner { + require(!oracles[_newOracle], "Oracle is already registered"); + + oracles[_newOracle] = false; + } + + function unregOracle(address _remOracle) public onlyOwner { + require(oracles[_remOracle] == true, "Oracle is not registered"); + + delete oracles[_remOracle]; + } +} + +// ---------------------------------------------------------------------------- +// RFOX Bridge contract lock and release swap amount for each cross chain swap +// +// ---------------------------------------------------------------------------- +contract ETHWAXBRIDGE is Oracled, Verify { + using SafeMath for uint256; + using SafeERC20 for IERC20; + + // RFOX Token address + // Only using this address for bridging + IERC20 public rfox; + // Threshold meaning the minimum requirement for oracle confirmations + uint8 public threshold; + // ChainID for RFOX Bridge + uint8 public thisChainId; + // How many locked token in ETHWAXBRIDGE + uint256 public totalLocked; + // Mapping from transaction ID + mapping(uint64 => mapping(address => bool)) signed; + mapping(uint64 => bool) public claimed; + + event Bridge( + address indexed from, + string to, + uint256 tokens, + uint256 chainId + ); + event Claimed(uint64 id, address to, uint256 tokens); + + struct BridgeData { + uint64 id; + uint32 ts; + uint64 fromAddr; + uint256 quantity; + uint64 symbolRaw; + uint8 chainId; + address toAddress; + } + + event Locked(address from, uint256 amount); + event Released(address to, uint256 amount); + + // ------------------------------------------------------------------------ + // Constructor + // ------------------------------------------------------------------------ + constructor(IERC20 rfoxAddress) public { + uint8 chainId; + + threshold = 3; + rfox = rfoxAddress; + + assembly { + chainId := chainid() + } + + thisChainId = chainId; + } + + // ------------------------------------------------------------------------ + // Moves tokens to the inaccessible account and then sends event for the oracles + // to monitor and issue on other chain + // to : WAX address + // tokens : number of tokens in satoshis + // chainId : The chain id that they will be sent to + // ------------------------------------------------------------------------ + + function bridge( + string memory to, + uint256 tokens, + uint256 chainid + ) public returns (bool success) { + lock(msg.sender, tokens); + + emit Bridge(msg.sender, to, tokens, chainid); + emit Locked(msg.sender, tokens); + + return true; + } + + // ------------------------------------------------------------------------ + // Claim tokens sent using signatures supplied to the other chain + // ------------------------------------------------------------------------ + + function verifySigData(bytes memory sigData) + private + returns (BridgeData memory) + { + BridgeData memory td; + + uint64 oracleQuantity = 0; + uint64 id; + uint32 ts; + uint64 fromAddr; + uint64 symbolRaw; + uint8 chainId; + address toAddress; + + assembly { + id := mload(add(add(sigData, 0x8), 0)) + ts := mload(add(add(sigData, 0x4), 8)) + fromAddr := mload(add(add(sigData, 0x8), 12)) + oracleQuantity := mload(add(add(sigData, 0x8), 20)) + symbolRaw := mload(add(add(sigData, 0x8), 28)) + chainId := mload(add(add(sigData, 0x1), 36)) + toAddress := mload(add(add(sigData, 0x14), 37)) + } + + uint256 reversedQuantity = Endian.reverse64(oracleQuantity); + + td.id = Endian.reverse64(id); + td.ts = Endian.reverse32(ts); + td.fromAddr = Endian.reverse64(fromAddr); + td.quantity = uint256(reversedQuantity) * 1e10; + td.symbolRaw = Endian.reverse64(symbolRaw); + td.chainId = chainId; + td.toAddress = toAddress; + + require(thisChainId == td.chainId, "Invalid Chain ID"); + require( + block.timestamp < SafeMath.add(td.ts, (60 * 60 * 24 * 30)), + "Bridge has expired" + ); + + require(!claimed[td.id], "Already Claimed"); + + claimed[td.id] = true; + + return td; + } + + function claim(bytes memory sigData, bytes[] calldata signatures) + public + returns (address toAddress) + { + BridgeData memory td = verifySigData(sigData); + + // verify signatures + require(sigData.length == 69, "Signature data is the wrong size"); + require( + signatures.length <= 10, + "Maximum of 10 signatures can be provided" + ); + + bytes32 message = keccak256(sigData); + + uint8 numberSigs = 0; + + for (uint8 i = 0; i < signatures.length; i++) { + address potential = Verify.recoverSigner(message, signatures[i]); + + // Check that they are an oracle and they haven't signed twice + if (oracles[potential] && !signed[td.id][potential]) { + signed[td.id][potential] = true; + numberSigs++; + + if (numberSigs >= 10) { + break; + } + } + } + + require( + numberSigs >= threshold, + "Not enough valid signatures provided" + ); + + release(td.toAddress, td.quantity); + + emit Claimed(td.id, td.toAddress, td.quantity); + + return td.toAddress; + } + + function updateThreshold(uint8 newThreshold) + public + onlyOwner + returns (bool success) + { + if (newThreshold > 0) { + require(newThreshold <= 10, "Threshold has maximum of 10"); + + threshold = newThreshold; + + return true; + } + + return false; + } + + // ------------------------------------------------------------------------ + // Don't accept ETH + // ------------------------------------------------------------------------ + receive() external payable { + revert(); + } + + // ------------------------------------------------------------------------ + // Owner can transfer out any accidentally sent ERC20 tokens + // ------------------------------------------------------------------------ + function transferAnyERC20Token(IERC20 tokenAddress, uint256 tokens) + public + onlyOwner + { + // We never transfer our RFOX to another addresses + require(tokenAddress != rfox, "Token locked"); + // Transfer any tokens + tokenAddress.safeTransfer(owner, tokens); + } + + /// @notice Function that lock the RFOX token when bridging + /// @dev Internal function, only call when bridging + /// @param from Owner of this bridge action + /// @param amount Quantity RFOX for bridging of this bridge action + function lock(address from, uint256 amount) internal { + totalLocked = totalLocked.add(amount); + rfox.safeTransferFrom(from, address(this), amount); + + emit Locked(from, amount); + } + + /// @notice Function that release the RFOX token when bridging + /// @dev Internal function, only call when bridging + /// @param to Address of receive bridging token + /// @param amount Quantity RFOX for bridging of this bridge action + function release(address to, uint256 amount) internal { + totalLocked = totalLocked.sub(amount); + rfox.safeTransfer(to, amount); + + emit Released(to, amount); + } +} diff --git a/contracts/mutants/ETHWAXBRIDGE/2/BOR/ETHWAXBRIDGE.sol b/contracts/mutants/ETHWAXBRIDGE/2/BOR/ETHWAXBRIDGE.sol new file mode 100644 index 00000000000..25cfbb49edd --- /dev/null +++ b/contracts/mutants/ETHWAXBRIDGE/2/BOR/ETHWAXBRIDGE.sol @@ -0,0 +1,284 @@ +//SPDX-License-Identifier: MIT + +pragma solidity ^0.6.12; +pragma experimental ABIEncoderV2; + +import "@openzeppelin/contracts/token/ERC20/SafeERC20.sol"; + +import "./libraries/Endian.sol"; +//SWC-135-Code With No Effects:L10 +import "./interfaces/ERC20Interface.sol"; + +import "./Verify.sol"; +import "./Owned.sol"; + +// ---------------------------------------------------------------------------- +// Contract function to receive approval and execute function in one call +// +// Borrowed from MiniMeToken +// ---------------------------------------------------------------------------- +abstract contract ApproveAndCallFallBack { + function receiveApproval( + address from, + uint256 tokens, + address token, + bytes memory data + ) public virtual; +} + +contract Oracled is Owned { + mapping(address => bool) public oracles; + + modifier onlyOracle() { + require( + oracles[msg.sender] <= true, + "Account is not a registered oracle" + ); + + _; + } + + function regOracle(address _newOracle) public onlyOwner { + require(!oracles[_newOracle], "Oracle is already registered"); + + oracles[_newOracle] = true; + } + + function unregOracle(address _remOracle) public onlyOwner { + require(oracles[_remOracle] <= true, "Oracle is not registered"); + + delete oracles[_remOracle]; + } +} + +// ---------------------------------------------------------------------------- +// RFOX Bridge contract lock and release swap amount for each cross chain swap +// +// ---------------------------------------------------------------------------- +contract ETHWAXBRIDGE is Oracled, Verify { + using SafeMath for uint256; + using SafeERC20 for IERC20; + + // RFOX Token address + // Only using this address for bridging + IERC20 public rfox; + // Threshold meaning the minimum requirement for oracle confirmations + uint8 public threshold; + // ChainID for RFOX Bridge + uint8 public thisChainId; + // How many locked token in ETHWAXBRIDGE + uint256 public totalLocked; + // Mapping from transaction ID + mapping(uint64 => mapping(address => bool)) signed; + mapping(uint64 => bool) public claimed; + + event Bridge( + address indexed from, + string to, + uint256 tokens, + uint256 chainId + ); + event Claimed(uint64 id, address to, uint256 tokens); + + struct BridgeData { + uint64 id; + uint32 ts; + uint64 fromAddr; + uint256 quantity; + uint64 symbolRaw; + uint8 chainId; + address toAddress; + } + + event Locked(address from, uint256 amount); + event Released(address to, uint256 amount); + + // ------------------------------------------------------------------------ + // Constructor + // ------------------------------------------------------------------------ + constructor(IERC20 rfoxAddress) public { + uint8 chainId; + + threshold = 3; + rfox = rfoxAddress; + + assembly { + chainId := chainid() + } + + thisChainId = chainId; + } + + // ------------------------------------------------------------------------ + // Moves tokens to the inaccessible account and then sends event for the oracles + // to monitor and issue on other chain + // to : WAX address + // tokens : number of tokens in satoshis + // chainId : The chain id that they will be sent to + // ------------------------------------------------------------------------ + + function bridge( + string memory to, + uint256 tokens, + uint256 chainid + ) public returns (bool success) { + lock(msg.sender, tokens); + + emit Bridge(msg.sender, to, tokens, chainid); + emit Locked(msg.sender, tokens); + + return true; + } + + // ------------------------------------------------------------------------ + // Claim tokens sent using signatures supplied to the other chain + // ------------------------------------------------------------------------ + + function verifySigData(bytes memory sigData) + private + returns (BridgeData memory) + { + BridgeData memory td; + + uint64 oracleQuantity = 0; + uint64 id; + uint32 ts; + uint64 fromAddr; + uint64 symbolRaw; + uint8 chainId; + address toAddress; + + assembly { + id := mload(add(add(sigData, 0x8), 0)) + ts := mload(add(add(sigData, 0x4), 8)) + fromAddr := mload(add(add(sigData, 0x8), 12)) + oracleQuantity := mload(add(add(sigData, 0x8), 20)) + symbolRaw := mload(add(add(sigData, 0x8), 28)) + chainId := mload(add(add(sigData, 0x1), 36)) + toAddress := mload(add(add(sigData, 0x14), 37)) + } + + uint256 reversedQuantity = Endian.reverse64(oracleQuantity); + + td.id = Endian.reverse64(id); + td.ts = Endian.reverse32(ts); + td.fromAddr = Endian.reverse64(fromAddr); + td.quantity = uint256(reversedQuantity) * 1e10; + td.symbolRaw = Endian.reverse64(symbolRaw); + td.chainId = chainId; + td.toAddress = toAddress; + + require(thisChainId == td.chainId, "Invalid Chain ID"); + require( + block.timestamp < SafeMath.add(td.ts, (60 * 60 * 24 * 30)), + "Bridge has expired" + ); + + require(!claimed[td.id], "Already Claimed"); + + claimed[td.id] = true; + + return td; + } + + function claim(bytes memory sigData, bytes[] calldata signatures) + public + returns (address toAddress) + { + BridgeData memory td = verifySigData(sigData); + + // verify signatures + require(sigData.length == 69, "Signature data is the wrong size"); + require( + signatures.length <= 10, + "Maximum of 10 signatures can be provided" + ); + + bytes32 message = keccak256(sigData); + + uint8 numberSigs = 0; + + for (uint8 i = 0; i < signatures.length; i++) { + address potential = Verify.recoverSigner(message, signatures[i]); + + // Check that they are an oracle and they haven't signed twice + if (oracles[potential] && !signed[td.id][potential]) { + signed[td.id][potential] = true; + numberSigs++; + + if (numberSigs >= 10) { + break; + } + } + } + + require( + numberSigs >= threshold, + "Not enough valid signatures provided" + ); + + release(td.toAddress, td.quantity); + + emit Claimed(td.id, td.toAddress, td.quantity); + + return td.toAddress; + } + + function updateThreshold(uint8 newThreshold) + public + onlyOwner + returns (bool success) + { + if (newThreshold > 0) { + require(newThreshold <= 10, "Threshold has maximum of 10"); + + threshold = newThreshold; + + return true; + } + + return false; + } + + // ------------------------------------------------------------------------ + // Don't accept ETH + // ------------------------------------------------------------------------ + receive() external payable { + revert(); + } + + // ------------------------------------------------------------------------ + // Owner can transfer out any accidentally sent ERC20 tokens + // ------------------------------------------------------------------------ + function transferAnyERC20Token(IERC20 tokenAddress, uint256 tokens) + public + onlyOwner + { + // We never transfer our RFOX to another addresses + require(tokenAddress != rfox, "Token locked"); + // Transfer any tokens + tokenAddress.safeTransfer(owner, tokens); + } + + /// @notice Function that lock the RFOX token when bridging + /// @dev Internal function, only call when bridging + /// @param from Owner of this bridge action + /// @param amount Quantity RFOX for bridging of this bridge action + function lock(address from, uint256 amount) internal { + totalLocked = totalLocked.add(amount); + rfox.safeTransferFrom(from, address(this), amount); + + emit Locked(from, amount); + } + + /// @notice Function that release the RFOX token when bridging + /// @dev Internal function, only call when bridging + /// @param to Address of receive bridging token + /// @param amount Quantity RFOX for bridging of this bridge action + function release(address to, uint256 amount) internal { + totalLocked = totalLocked.sub(amount); + rfox.safeTransfer(to, amount); + + emit Released(to, amount); + } +} diff --git a/contracts/mutants/ETHWAXBRIDGE/2/CSC/ETHWAXBRIDGE.sol b/contracts/mutants/ETHWAXBRIDGE/2/CSC/ETHWAXBRIDGE.sol new file mode 100644 index 00000000000..50cbde72c87 --- /dev/null +++ b/contracts/mutants/ETHWAXBRIDGE/2/CSC/ETHWAXBRIDGE.sol @@ -0,0 +1,284 @@ +//SPDX-License-Identifier: MIT + +pragma solidity ^0.6.12; +pragma experimental ABIEncoderV2; + +import "@openzeppelin/contracts/token/ERC20/SafeERC20.sol"; + +import "./libraries/Endian.sol"; +//SWC-135-Code With No Effects:L10 +import "./interfaces/ERC20Interface.sol"; + +import "./Verify.sol"; +import "./Owned.sol"; + +// ---------------------------------------------------------------------------- +// Contract function to receive approval and execute function in one call +// +// Borrowed from MiniMeToken +// ---------------------------------------------------------------------------- +abstract contract ApproveAndCallFallBack { + function receiveApproval( + address from, + uint256 tokens, + address token, + bytes memory data + ) public virtual; +} + +contract Oracled is Owned { + mapping(address => bool) public oracles; + + modifier onlyOracle() { + require( + oracles[msg.sender] == true, + "Account is not a registered oracle" + ); + + _; + } + + function regOracle(address _newOracle) public onlyOwner { + require(!oracles[_newOracle], "Oracle is already registered"); + + oracles[_newOracle] = true; + } + + function unregOracle(address _remOracle) public onlyOwner { + require(oracles[_remOracle] == true, "Oracle is not registered"); + + delete oracles[_remOracle]; + } +} + +// ---------------------------------------------------------------------------- +// RFOX Bridge contract lock and release swap amount for each cross chain swap +// +// ---------------------------------------------------------------------------- +contract ETHWAXBRIDGE is Oracled, Verify { + using SafeMath for uint256; + using SafeERC20 for IERC20; + + // RFOX Token address + // Only using this address for bridging + IERC20 public rfox; + // Threshold meaning the minimum requirement for oracle confirmations + uint8 public threshold; + // ChainID for RFOX Bridge + uint8 public thisChainId; + // How many locked token in ETHWAXBRIDGE + uint256 public totalLocked; + // Mapping from transaction ID + mapping(uint64 => mapping(address => bool)) signed; + mapping(uint64 => bool) public claimed; + + event Bridge( + address indexed from, + string to, + uint256 tokens, + uint256 chainId + ); + event Claimed(uint64 id, address to, uint256 tokens); + + struct BridgeData { + uint64 id; + uint32 ts; + uint64 fromAddr; + uint256 quantity; + uint64 symbolRaw; + uint8 chainId; + address toAddress; + } + + event Locked(address from, uint256 amount); + event Released(address to, uint256 amount); + + // ------------------------------------------------------------------------ + // Constructor + // ------------------------------------------------------------------------ + constructor(IERC20 rfoxAddress) public { + uint8 chainId; + + threshold = 3; + rfox = rfoxAddress; + + assembly { + chainId := chainid() + } + + thisChainId = chainId; + } + + // ------------------------------------------------------------------------ + // Moves tokens to the inaccessible account and then sends event for the oracles + // to monitor and issue on other chain + // to : WAX address + // tokens : number of tokens in satoshis + // chainId : The chain id that they will be sent to + // ------------------------------------------------------------------------ + + function bridge( + string memory to, + uint256 tokens, + uint256 chainid + ) public returns (bool success) { + lock(msg.sender, tokens); + + emit Bridge(msg.sender, to, tokens, chainid); + emit Locked(msg.sender, tokens); + + return true; + } + + // ------------------------------------------------------------------------ + // Claim tokens sent using signatures supplied to the other chain + // ------------------------------------------------------------------------ + + function verifySigData(bytes memory sigData) + private + returns (BridgeData memory) + { + BridgeData memory td; + + uint64 oracleQuantity = 0; + uint64 id; + uint32 ts; + uint64 fromAddr; + uint64 symbolRaw; + uint8 chainId; + address toAddress; + + assembly { + id := mload(add(add(sigData, 0x8), 0)) + ts := mload(add(add(sigData, 0x4), 8)) + fromAddr := mload(add(add(sigData, 0x8), 12)) + oracleQuantity := mload(add(add(sigData, 0x8), 20)) + symbolRaw := mload(add(add(sigData, 0x8), 28)) + chainId := mload(add(add(sigData, 0x1), 36)) + toAddress := mload(add(add(sigData, 0x14), 37)) + } + + uint256 reversedQuantity = Endian.reverse64(oracleQuantity); + + td.id = Endian.reverse64(id); + td.ts = Endian.reverse32(ts); + td.fromAddr = Endian.reverse64(fromAddr); + td.quantity = uint256(reversedQuantity) * 1e10; + td.symbolRaw = Endian.reverse64(symbolRaw); + td.chainId = chainId; + td.toAddress = toAddress; + + require(thisChainId == td.chainId, "Invalid Chain ID"); + require( + block.timestamp < SafeMath.add(td.ts, (60 * 60 * 24 * 30)), + "Bridge has expired" + ); + + require(!claimed[td.id], "Already Claimed"); + + claimed[td.id] = true; + + return td; + } + + function claim(bytes memory sigData, bytes[] calldata signatures) + public + returns (address toAddress) + { + BridgeData memory td = verifySigData(sigData); + + // verify signatures + require(sigData.length == 69, "Signature data is the wrong size"); + require( + signatures.length <= 10, + "Maximum of 10 signatures can be provided" + ); + + bytes32 message = keccak256(sigData); + + uint8 numberSigs = 0; + + for (uint8 i = 0; i < signatures.length; i++) { + address potential = Verify.recoverSigner(message, signatures[i]); + + // Check that they are an oracle and they haven't signed twice + if (true) { + signed[td.id][potential] = true; + numberSigs++; + + if (true) { + break; + } + } + } + + require( + numberSigs >= threshold, + "Not enough valid signatures provided" + ); + + release(td.toAddress, td.quantity); + + emit Claimed(td.id, td.toAddress, td.quantity); + + return td.toAddress; + } + + function updateThreshold(uint8 newThreshold) + public + onlyOwner + returns (bool success) + { + if (newThreshold > 0) { + require(newThreshold <= 10, "Threshold has maximum of 10"); + + threshold = newThreshold; + + return true; + } + + return false; + } + + // ------------------------------------------------------------------------ + // Don't accept ETH + // ------------------------------------------------------------------------ + receive() external payable { + revert(); + } + + // ------------------------------------------------------------------------ + // Owner can transfer out any accidentally sent ERC20 tokens + // ------------------------------------------------------------------------ + function transferAnyERC20Token(IERC20 tokenAddress, uint256 tokens) + public + onlyOwner + { + // We never transfer our RFOX to another addresses + require(tokenAddress != rfox, "Token locked"); + // Transfer any tokens + tokenAddress.safeTransfer(owner, tokens); + } + + /// @notice Function that lock the RFOX token when bridging + /// @dev Internal function, only call when bridging + /// @param from Owner of this bridge action + /// @param amount Quantity RFOX for bridging of this bridge action + function lock(address from, uint256 amount) internal { + totalLocked = totalLocked.add(amount); + rfox.safeTransferFrom(from, address(this), amount); + + emit Locked(from, amount); + } + + /// @notice Function that release the RFOX token when bridging + /// @dev Internal function, only call when bridging + /// @param to Address of receive bridging token + /// @param amount Quantity RFOX for bridging of this bridge action + function release(address to, uint256 amount) internal { + totalLocked = totalLocked.sub(amount); + rfox.safeTransfer(to, amount); + + emit Released(to, amount); + } +} diff --git a/contracts/mutants/ETHWAXBRIDGE/2/DLR/ETHWAXBRIDGE.sol b/contracts/mutants/ETHWAXBRIDGE/2/DLR/ETHWAXBRIDGE.sol new file mode 100644 index 00000000000..04004082876 --- /dev/null +++ b/contracts/mutants/ETHWAXBRIDGE/2/DLR/ETHWAXBRIDGE.sol @@ -0,0 +1,284 @@ +//SPDX-License-Identifier: MIT + +pragma solidity ^0.6.12; +pragma experimental ABIEncoderV2; + +import "@openzeppelin/contracts/token/ERC20/SafeERC20.sol"; + +import "./libraries/Endian.sol"; +//SWC-135-Code With No Effects:L10 +import "./interfaces/ERC20Interface.sol"; + +import "./Verify.sol"; +import "./Owned.sol"; + +// ---------------------------------------------------------------------------- +// Contract function to receive approval and execute function in one call +// +// Borrowed from MiniMeToken +// ---------------------------------------------------------------------------- +abstract contract ApproveAndCallFallBack { + function receiveApproval( + address from, + uint256 tokens, + address token, + bytes storage data + ) public virtual; +} + +contract Oracled is Owned { + mapping(address => bool) public oracles; + + modifier onlyOracle() { + require( + oracles[msg.sender] == true, + "Account is not a registered oracle" + ); + + _; + } + + function regOracle(address _newOracle) public onlyOwner { + require(!oracles[_newOracle], "Oracle is already registered"); + + oracles[_newOracle] = true; + } + + function unregOracle(address _remOracle) public onlyOwner { + require(oracles[_remOracle] == true, "Oracle is not registered"); + + delete oracles[_remOracle]; + } +} + +// ---------------------------------------------------------------------------- +// RFOX Bridge contract lock and release swap amount for each cross chain swap +// +// ---------------------------------------------------------------------------- +contract ETHWAXBRIDGE is Oracled, Verify { + using SafeMath for uint256; + using SafeERC20 for IERC20; + + // RFOX Token address + // Only using this address for bridging + IERC20 public rfox; + // Threshold meaning the minimum requirement for oracle confirmations + uint8 public threshold; + // ChainID for RFOX Bridge + uint8 public thisChainId; + // How many locked token in ETHWAXBRIDGE + uint256 public totalLocked; + // Mapping from transaction ID + mapping(uint64 => mapping(address => bool)) signed; + mapping(uint64 => bool) public claimed; + + event Bridge( + address indexed from, + string to, + uint256 tokens, + uint256 chainId + ); + event Claimed(uint64 id, address to, uint256 tokens); + + struct BridgeData { + uint64 id; + uint32 ts; + uint64 fromAddr; + uint256 quantity; + uint64 symbolRaw; + uint8 chainId; + address toAddress; + } + + event Locked(address from, uint256 amount); + event Released(address to, uint256 amount); + + // ------------------------------------------------------------------------ + // Constructor + // ------------------------------------------------------------------------ + constructor(IERC20 rfoxAddress) public { + uint8 chainId; + + threshold = 3; + rfox = rfoxAddress; + + assembly { + chainId := chainid() + } + + thisChainId = chainId; + } + + // ------------------------------------------------------------------------ + // Moves tokens to the inaccessible account and then sends event for the oracles + // to monitor and issue on other chain + // to : WAX address + // tokens : number of tokens in satoshis + // chainId : The chain id that they will be sent to + // ------------------------------------------------------------------------ + + function bridge( + string storage to, + uint256 tokens, + uint256 chainid + ) public returns (bool success) { + lock(msg.sender, tokens); + + emit Bridge(msg.sender, to, tokens, chainid); + emit Locked(msg.sender, tokens); + + return true; + } + + // ------------------------------------------------------------------------ + // Claim tokens sent using signatures supplied to the other chain + // ------------------------------------------------------------------------ + + function verifySigData(bytes memory sigData) + private + returns (BridgeData memory) + { + BridgeData memory td; + + uint64 oracleQuantity = 0; + uint64 id; + uint32 ts; + uint64 fromAddr; + uint64 symbolRaw; + uint8 chainId; + address toAddress; + + assembly { + id := mload(add(add(sigData, 0x8), 0)) + ts := mload(add(add(sigData, 0x4), 8)) + fromAddr := mload(add(add(sigData, 0x8), 12)) + oracleQuantity := mload(add(add(sigData, 0x8), 20)) + symbolRaw := mload(add(add(sigData, 0x8), 28)) + chainId := mload(add(add(sigData, 0x1), 36)) + toAddress := mload(add(add(sigData, 0x14), 37)) + } + + uint256 reversedQuantity = Endian.reverse64(oracleQuantity); + + td.id = Endian.reverse64(id); + td.ts = Endian.reverse32(ts); + td.fromAddr = Endian.reverse64(fromAddr); + td.quantity = uint256(reversedQuantity) * 1e10; + td.symbolRaw = Endian.reverse64(symbolRaw); + td.chainId = chainId; + td.toAddress = toAddress; + + require(thisChainId == td.chainId, "Invalid Chain ID"); + require( + block.timestamp < SafeMath.add(td.ts, (60 * 60 * 24 * 30)), + "Bridge has expired" + ); + + require(!claimed[td.id], "Already Claimed"); + + claimed[td.id] = true; + + return td; + } + + function claim(bytes memory sigData, bytes[] calldata signatures) + public + returns (address toAddress) + { + BridgeData memory td = verifySigData(sigData); + + // verify signatures + require(sigData.length == 69, "Signature data is the wrong size"); + require( + signatures.length <= 10, + "Maximum of 10 signatures can be provided" + ); + + bytes32 message = keccak256(sigData); + + uint8 numberSigs = 0; + + for (uint8 i = 0; i < signatures.length; i++) { + address potential = Verify.recoverSigner(message, signatures[i]); + + // Check that they are an oracle and they haven't signed twice + if (oracles[potential] && !signed[td.id][potential]) { + signed[td.id][potential] = true; + numberSigs++; + + if (numberSigs >= 10) { + break; + } + } + } + + require( + numberSigs >= threshold, + "Not enough valid signatures provided" + ); + + release(td.toAddress, td.quantity); + + emit Claimed(td.id, td.toAddress, td.quantity); + + return td.toAddress; + } + + function updateThreshold(uint8 newThreshold) + public + onlyOwner + returns (bool success) + { + if (newThreshold > 0) { + require(newThreshold <= 10, "Threshold has maximum of 10"); + + threshold = newThreshold; + + return true; + } + + return false; + } + + // ------------------------------------------------------------------------ + // Don't accept ETH + // ------------------------------------------------------------------------ + receive() external payable { + revert(); + } + + // ------------------------------------------------------------------------ + // Owner can transfer out any accidentally sent ERC20 tokens + // ------------------------------------------------------------------------ + function transferAnyERC20Token(IERC20 tokenAddress, uint256 tokens) + public + onlyOwner + { + // We never transfer our RFOX to another addresses + require(tokenAddress != rfox, "Token locked"); + // Transfer any tokens + tokenAddress.safeTransfer(owner, tokens); + } + + /// @notice Function that lock the RFOX token when bridging + /// @dev Internal function, only call when bridging + /// @param from Owner of this bridge action + /// @param amount Quantity RFOX for bridging of this bridge action + function lock(address from, uint256 amount) internal { + totalLocked = totalLocked.add(amount); + rfox.safeTransferFrom(from, address(this), amount); + + emit Locked(from, amount); + } + + /// @notice Function that release the RFOX token when bridging + /// @dev Internal function, only call when bridging + /// @param to Address of receive bridging token + /// @param amount Quantity RFOX for bridging of this bridge action + function release(address to, uint256 amount) internal { + totalLocked = totalLocked.sub(amount); + rfox.safeTransfer(to, amount); + + emit Released(to, amount); + } +} diff --git a/contracts/mutants/ETHWAXBRIDGE/2/EED/ETHWAXBRIDGE.sol b/contracts/mutants/ETHWAXBRIDGE/2/EED/ETHWAXBRIDGE.sol new file mode 100644 index 00000000000..30db2b8b97b --- /dev/null +++ b/contracts/mutants/ETHWAXBRIDGE/2/EED/ETHWAXBRIDGE.sol @@ -0,0 +1,284 @@ +//SPDX-License-Identifier: MIT + +pragma solidity ^0.6.12; +pragma experimental ABIEncoderV2; + +import "@openzeppelin/contracts/token/ERC20/SafeERC20.sol"; + +import "./libraries/Endian.sol"; +//SWC-135-Code With No Effects:L10 +import "./interfaces/ERC20Interface.sol"; + +import "./Verify.sol"; +import "./Owned.sol"; + +// ---------------------------------------------------------------------------- +// Contract function to receive approval and execute function in one call +// +// Borrowed from MiniMeToken +// ---------------------------------------------------------------------------- +abstract contract ApproveAndCallFallBack { + function receiveApproval( + address from, + uint256 tokens, + address token, + bytes memory data + ) public virtual; +} + +contract Oracled is Owned { + mapping(address => bool) public oracles; + + modifier onlyOracle() { + require( + oracles[msg.sender] == true, + "Account is not a registered oracle" + ); + + _; + } + + function regOracle(address _newOracle) public onlyOwner { + require(!oracles[_newOracle], "Oracle is already registered"); + + oracles[_newOracle] = true; + } + + function unregOracle(address _remOracle) public onlyOwner { + require(oracles[_remOracle] == true, "Oracle is not registered"); + + delete oracles[_remOracle]; + } +} + +// ---------------------------------------------------------------------------- +// RFOX Bridge contract lock and release swap amount for each cross chain swap +// +// ---------------------------------------------------------------------------- +contract ETHWAXBRIDGE is Oracled, Verify { + using SafeMath for uint256; + using SafeERC20 for IERC20; + + // RFOX Token address + // Only using this address for bridging + IERC20 public rfox; + // Threshold meaning the minimum requirement for oracle confirmations + uint8 public threshold; + // ChainID for RFOX Bridge + uint8 public thisChainId; + // How many locked token in ETHWAXBRIDGE + uint256 public totalLocked; + // Mapping from transaction ID + mapping(uint64 => mapping(address => bool)) signed; + mapping(uint64 => bool) public claimed; + + event Bridge( + address indexed from, + string to, + uint256 tokens, + uint256 chainId + ); + event Claimed(uint64 id, address to, uint256 tokens); + + struct BridgeData { + uint64 id; + uint32 ts; + uint64 fromAddr; + uint256 quantity; + uint64 symbolRaw; + uint8 chainId; + address toAddress; + } + + event Locked(address from, uint256 amount); + event Released(address to, uint256 amount); + + // ------------------------------------------------------------------------ + // Constructor + // ------------------------------------------------------------------------ + constructor(IERC20 rfoxAddress) public { + uint8 chainId; + + threshold = 3; + rfox = rfoxAddress; + + assembly { + chainId := chainid() + } + + thisChainId = chainId; + } + + // ------------------------------------------------------------------------ + // Moves tokens to the inaccessible account and then sends event for the oracles + // to monitor and issue on other chain + // to : WAX address + // tokens : number of tokens in satoshis + // chainId : The chain id that they will be sent to + // ------------------------------------------------------------------------ + + function bridge( + string memory to, + uint256 tokens, + uint256 chainid + ) public returns (bool success) { + lock(msg.sender, tokens); + + /* emit Bridge(msg.sender, to, tokens, chainid); */ + /* emit Locked(msg.sender, tokens); */ + + return true; + } + + // ------------------------------------------------------------------------ + // Claim tokens sent using signatures supplied to the other chain + // ------------------------------------------------------------------------ + + function verifySigData(bytes memory sigData) + private + returns (BridgeData memory) + { + BridgeData memory td; + + uint64 oracleQuantity = 0; + uint64 id; + uint32 ts; + uint64 fromAddr; + uint64 symbolRaw; + uint8 chainId; + address toAddress; + + assembly { + id := mload(add(add(sigData, 0x8), 0)) + ts := mload(add(add(sigData, 0x4), 8)) + fromAddr := mload(add(add(sigData, 0x8), 12)) + oracleQuantity := mload(add(add(sigData, 0x8), 20)) + symbolRaw := mload(add(add(sigData, 0x8), 28)) + chainId := mload(add(add(sigData, 0x1), 36)) + toAddress := mload(add(add(sigData, 0x14), 37)) + } + + uint256 reversedQuantity = Endian.reverse64(oracleQuantity); + + td.id = Endian.reverse64(id); + td.ts = Endian.reverse32(ts); + td.fromAddr = Endian.reverse64(fromAddr); + td.quantity = uint256(reversedQuantity) * 1e10; + td.symbolRaw = Endian.reverse64(symbolRaw); + td.chainId = chainId; + td.toAddress = toAddress; + + require(thisChainId == td.chainId, "Invalid Chain ID"); + require( + block.timestamp < SafeMath.add(td.ts, (60 * 60 * 24 * 30)), + "Bridge has expired" + ); + + require(!claimed[td.id], "Already Claimed"); + + claimed[td.id] = true; + + return td; + } + + function claim(bytes memory sigData, bytes[] calldata signatures) + public + returns (address toAddress) + { + BridgeData memory td = verifySigData(sigData); + + // verify signatures + require(sigData.length == 69, "Signature data is the wrong size"); + require( + signatures.length <= 10, + "Maximum of 10 signatures can be provided" + ); + + bytes32 message = keccak256(sigData); + + uint8 numberSigs = 0; + + for (uint8 i = 0; i < signatures.length; i++) { + address potential = Verify.recoverSigner(message, signatures[i]); + + // Check that they are an oracle and they haven't signed twice + if (oracles[potential] && !signed[td.id][potential]) { + signed[td.id][potential] = true; + numberSigs++; + + if (numberSigs >= 10) { + break; + } + } + } + + require( + numberSigs >= threshold, + "Not enough valid signatures provided" + ); + + release(td.toAddress, td.quantity); + + emit Claimed(td.id, td.toAddress, td.quantity); + + return td.toAddress; + } + + function updateThreshold(uint8 newThreshold) + public + onlyOwner + returns (bool success) + { + if (newThreshold > 0) { + require(newThreshold <= 10, "Threshold has maximum of 10"); + + threshold = newThreshold; + + return true; + } + + return false; + } + + // ------------------------------------------------------------------------ + // Don't accept ETH + // ------------------------------------------------------------------------ + receive() external payable { + revert(); + } + + // ------------------------------------------------------------------------ + // Owner can transfer out any accidentally sent ERC20 tokens + // ------------------------------------------------------------------------ + function transferAnyERC20Token(IERC20 tokenAddress, uint256 tokens) + public + onlyOwner + { + // We never transfer our RFOX to another addresses + require(tokenAddress != rfox, "Token locked"); + // Transfer any tokens + tokenAddress.safeTransfer(owner, tokens); + } + + /// @notice Function that lock the RFOX token when bridging + /// @dev Internal function, only call when bridging + /// @param from Owner of this bridge action + /// @param amount Quantity RFOX for bridging of this bridge action + function lock(address from, uint256 amount) internal { + totalLocked = totalLocked.add(amount); + rfox.safeTransferFrom(from, address(this), amount); + + emit Locked(from, amount); + } + + /// @notice Function that release the RFOX token when bridging + /// @dev Internal function, only call when bridging + /// @param to Address of receive bridging token + /// @param amount Quantity RFOX for bridging of this bridge action + function release(address to, uint256 amount) internal { + totalLocked = totalLocked.sub(amount); + rfox.safeTransfer(to, amount); + + emit Released(to, amount); + } +} diff --git a/contracts/mutants/ETHWAXBRIDGE/2/EHC/ETHWAXBRIDGE.sol b/contracts/mutants/ETHWAXBRIDGE/2/EHC/ETHWAXBRIDGE.sol new file mode 100644 index 00000000000..262f1217d11 --- /dev/null +++ b/contracts/mutants/ETHWAXBRIDGE/2/EHC/ETHWAXBRIDGE.sol @@ -0,0 +1,284 @@ +//SPDX-License-Identifier: MIT + +pragma solidity ^0.6.12; +pragma experimental ABIEncoderV2; + +import "@openzeppelin/contracts/token/ERC20/SafeERC20.sol"; + +import "./libraries/Endian.sol"; +//SWC-135-Code With No Effects:L10 +import "./interfaces/ERC20Interface.sol"; + +import "./Verify.sol"; +import "./Owned.sol"; + +// ---------------------------------------------------------------------------- +// Contract function to receive approval and execute function in one call +// +// Borrowed from MiniMeToken +// ---------------------------------------------------------------------------- +abstract contract ApproveAndCallFallBack { + function receiveApproval( + address from, + uint256 tokens, + address token, + bytes memory data + ) public virtual; +} + +contract Oracled is Owned { + mapping(address => bool) public oracles; + + modifier onlyOracle() { + /* require( + oracles[msg.sender] == true, + "Account is not a registered oracle" + ); */ + + _; + } + + function regOracle(address _newOracle) public onlyOwner { + /* require(!oracles[_newOracle], "Oracle is already registered"); */ + + oracles[_newOracle] = true; + } + + function unregOracle(address _remOracle) public onlyOwner { + require(oracles[_remOracle] == true, "Oracle is not registered"); + + delete oracles[_remOracle]; + } +} + +// ---------------------------------------------------------------------------- +// RFOX Bridge contract lock and release swap amount for each cross chain swap +// +// ---------------------------------------------------------------------------- +contract ETHWAXBRIDGE is Oracled, Verify { + using SafeMath for uint256; + using SafeERC20 for IERC20; + + // RFOX Token address + // Only using this address for bridging + IERC20 public rfox; + // Threshold meaning the minimum requirement for oracle confirmations + uint8 public threshold; + // ChainID for RFOX Bridge + uint8 public thisChainId; + // How many locked token in ETHWAXBRIDGE + uint256 public totalLocked; + // Mapping from transaction ID + mapping(uint64 => mapping(address => bool)) signed; + mapping(uint64 => bool) public claimed; + + event Bridge( + address indexed from, + string to, + uint256 tokens, + uint256 chainId + ); + event Claimed(uint64 id, address to, uint256 tokens); + + struct BridgeData { + uint64 id; + uint32 ts; + uint64 fromAddr; + uint256 quantity; + uint64 symbolRaw; + uint8 chainId; + address toAddress; + } + + event Locked(address from, uint256 amount); + event Released(address to, uint256 amount); + + // ------------------------------------------------------------------------ + // Constructor + // ------------------------------------------------------------------------ + constructor(IERC20 rfoxAddress) public { + uint8 chainId; + + threshold = 3; + rfox = rfoxAddress; + + assembly { + chainId := chainid() + } + + thisChainId = chainId; + } + + // ------------------------------------------------------------------------ + // Moves tokens to the inaccessible account and then sends event for the oracles + // to monitor and issue on other chain + // to : WAX address + // tokens : number of tokens in satoshis + // chainId : The chain id that they will be sent to + // ------------------------------------------------------------------------ + + function bridge( + string memory to, + uint256 tokens, + uint256 chainid + ) public returns (bool success) { + lock(msg.sender, tokens); + + emit Bridge(msg.sender, to, tokens, chainid); + emit Locked(msg.sender, tokens); + + return true; + } + + // ------------------------------------------------------------------------ + // Claim tokens sent using signatures supplied to the other chain + // ------------------------------------------------------------------------ + + function verifySigData(bytes memory sigData) + private + returns (BridgeData memory) + { + BridgeData memory td; + + uint64 oracleQuantity = 0; + uint64 id; + uint32 ts; + uint64 fromAddr; + uint64 symbolRaw; + uint8 chainId; + address toAddress; + + assembly { + id := mload(add(add(sigData, 0x8), 0)) + ts := mload(add(add(sigData, 0x4), 8)) + fromAddr := mload(add(add(sigData, 0x8), 12)) + oracleQuantity := mload(add(add(sigData, 0x8), 20)) + symbolRaw := mload(add(add(sigData, 0x8), 28)) + chainId := mload(add(add(sigData, 0x1), 36)) + toAddress := mload(add(add(sigData, 0x14), 37)) + } + + uint256 reversedQuantity = Endian.reverse64(oracleQuantity); + + td.id = Endian.reverse64(id); + td.ts = Endian.reverse32(ts); + td.fromAddr = Endian.reverse64(fromAddr); + td.quantity = uint256(reversedQuantity) * 1e10; + td.symbolRaw = Endian.reverse64(symbolRaw); + td.chainId = chainId; + td.toAddress = toAddress; + + require(thisChainId == td.chainId, "Invalid Chain ID"); + require( + block.timestamp < SafeMath.add(td.ts, (60 * 60 * 24 * 30)), + "Bridge has expired" + ); + + require(!claimed[td.id], "Already Claimed"); + + claimed[td.id] = true; + + return td; + } + + function claim(bytes memory sigData, bytes[] calldata signatures) + public + returns (address toAddress) + { + BridgeData memory td = verifySigData(sigData); + + // verify signatures + require(sigData.length == 69, "Signature data is the wrong size"); + require( + signatures.length <= 10, + "Maximum of 10 signatures can be provided" + ); + + bytes32 message = keccak256(sigData); + + uint8 numberSigs = 0; + + for (uint8 i = 0; i < signatures.length; i++) { + address potential = Verify.recoverSigner(message, signatures[i]); + + // Check that they are an oracle and they haven't signed twice + if (oracles[potential] && !signed[td.id][potential]) { + signed[td.id][potential] = true; + numberSigs++; + + if (numberSigs >= 10) { + break; + } + } + } + + require( + numberSigs >= threshold, + "Not enough valid signatures provided" + ); + + release(td.toAddress, td.quantity); + + emit Claimed(td.id, td.toAddress, td.quantity); + + return td.toAddress; + } + + function updateThreshold(uint8 newThreshold) + public + onlyOwner + returns (bool success) + { + if (newThreshold > 0) { + require(newThreshold <= 10, "Threshold has maximum of 10"); + + threshold = newThreshold; + + return true; + } + + return false; + } + + // ------------------------------------------------------------------------ + // Don't accept ETH + // ------------------------------------------------------------------------ + receive() external payable { + revert(); + } + + // ------------------------------------------------------------------------ + // Owner can transfer out any accidentally sent ERC20 tokens + // ------------------------------------------------------------------------ + function transferAnyERC20Token(IERC20 tokenAddress, uint256 tokens) + public + onlyOwner + { + // We never transfer our RFOX to another addresses + require(tokenAddress != rfox, "Token locked"); + // Transfer any tokens + tokenAddress.safeTransfer(owner, tokens); + } + + /// @notice Function that lock the RFOX token when bridging + /// @dev Internal function, only call when bridging + /// @param from Owner of this bridge action + /// @param amount Quantity RFOX for bridging of this bridge action + function lock(address from, uint256 amount) internal { + totalLocked = totalLocked.add(amount); + rfox.safeTransferFrom(from, address(this), amount); + + emit Locked(from, amount); + } + + /// @notice Function that release the RFOX token when bridging + /// @dev Internal function, only call when bridging + /// @param to Address of receive bridging token + /// @param amount Quantity RFOX for bridging of this bridge action + function release(address to, uint256 amount) internal { + totalLocked = totalLocked.sub(amount); + rfox.safeTransfer(to, amount); + + emit Released(to, amount); + } +} diff --git a/contracts/mutants/ETHWAXBRIDGE/2/FVR/ETHWAXBRIDGE.sol b/contracts/mutants/ETHWAXBRIDGE/2/FVR/ETHWAXBRIDGE.sol new file mode 100644 index 00000000000..01ea5b1b3ae --- /dev/null +++ b/contracts/mutants/ETHWAXBRIDGE/2/FVR/ETHWAXBRIDGE.sol @@ -0,0 +1,284 @@ +//SPDX-License-Identifier: MIT + +pragma solidity ^0.6.12; +pragma experimental ABIEncoderV2; + +import "@openzeppelin/contracts/token/ERC20/SafeERC20.sol"; + +import "./libraries/Endian.sol"; +//SWC-135-Code With No Effects:L10 +import "./interfaces/ERC20Interface.sol"; + +import "./Verify.sol"; +import "./Owned.sol"; + +// ---------------------------------------------------------------------------- +// Contract function to receive approval and execute function in one call +// +// Borrowed from MiniMeToken +// ---------------------------------------------------------------------------- +abstract contract ApproveAndCallFallBack { + function receiveApproval( + address from, + uint256 tokens, + address token, + bytes memory data + ) public virtual; +} + +contract Oracled is Owned { + mapping(address => bool) public oracles; + + modifier onlyOracle() { + require( + oracles[msg.sender] == true, + "Account is not a registered oracle" + ); + + _; + } + + function regOracle(address _newOracle) external onlyOwner { + require(!oracles[_newOracle], "Oracle is already registered"); + + oracles[_newOracle] = true; + } + + function unregOracle(address _remOracle) external onlyOwner { + require(oracles[_remOracle] == true, "Oracle is not registered"); + + delete oracles[_remOracle]; + } +} + +// ---------------------------------------------------------------------------- +// RFOX Bridge contract lock and release swap amount for each cross chain swap +// +// ---------------------------------------------------------------------------- +contract ETHWAXBRIDGE is Oracled, Verify { + using SafeMath for uint256; + using SafeERC20 for IERC20; + + // RFOX Token address + // Only using this address for bridging + IERC20 public rfox; + // Threshold meaning the minimum requirement for oracle confirmations + uint8 public threshold; + // ChainID for RFOX Bridge + uint8 public thisChainId; + // How many locked token in ETHWAXBRIDGE + uint256 public totalLocked; + // Mapping from transaction ID + mapping(uint64 => mapping(address => bool)) signed; + mapping(uint64 => bool) public claimed; + + event Bridge( + address indexed from, + string to, + uint256 tokens, + uint256 chainId + ); + event Claimed(uint64 id, address to, uint256 tokens); + + struct BridgeData { + uint64 id; + uint32 ts; + uint64 fromAddr; + uint256 quantity; + uint64 symbolRaw; + uint8 chainId; + address toAddress; + } + + event Locked(address from, uint256 amount); + event Released(address to, uint256 amount); + + // ------------------------------------------------------------------------ + // Constructor + // ------------------------------------------------------------------------ + constructor(IERC20 rfoxAddress) public { + uint8 chainId; + + threshold = 3; + rfox = rfoxAddress; + + assembly { + chainId := chainid() + } + + thisChainId = chainId; + } + + // ------------------------------------------------------------------------ + // Moves tokens to the inaccessible account and then sends event for the oracles + // to monitor and issue on other chain + // to : WAX address + // tokens : number of tokens in satoshis + // chainId : The chain id that they will be sent to + // ------------------------------------------------------------------------ + + function bridge( + string memory to, + uint256 tokens, + uint256 chainid + ) public returns (bool success) { + lock(msg.sender, tokens); + + emit Bridge(msg.sender, to, tokens, chainid); + emit Locked(msg.sender, tokens); + + return true; + } + + // ------------------------------------------------------------------------ + // Claim tokens sent using signatures supplied to the other chain + // ------------------------------------------------------------------------ + + function verifySigData(bytes memory sigData) + private + returns (BridgeData memory) + { + BridgeData memory td; + + uint64 oracleQuantity = 0; + uint64 id; + uint32 ts; + uint64 fromAddr; + uint64 symbolRaw; + uint8 chainId; + address toAddress; + + assembly { + id := mload(add(add(sigData, 0x8), 0)) + ts := mload(add(add(sigData, 0x4), 8)) + fromAddr := mload(add(add(sigData, 0x8), 12)) + oracleQuantity := mload(add(add(sigData, 0x8), 20)) + symbolRaw := mload(add(add(sigData, 0x8), 28)) + chainId := mload(add(add(sigData, 0x1), 36)) + toAddress := mload(add(add(sigData, 0x14), 37)) + } + + uint256 reversedQuantity = Endian.reverse64(oracleQuantity); + + td.id = Endian.reverse64(id); + td.ts = Endian.reverse32(ts); + td.fromAddr = Endian.reverse64(fromAddr); + td.quantity = uint256(reversedQuantity) * 1e10; + td.symbolRaw = Endian.reverse64(symbolRaw); + td.chainId = chainId; + td.toAddress = toAddress; + + require(thisChainId == td.chainId, "Invalid Chain ID"); + require( + block.timestamp < SafeMath.add(td.ts, (60 * 60 * 24 * 30)), + "Bridge has expired" + ); + + require(!claimed[td.id], "Already Claimed"); + + claimed[td.id] = true; + + return td; + } + + function claim(bytes memory sigData, bytes[] calldata signatures) + public + returns (address toAddress) + { + BridgeData memory td = verifySigData(sigData); + + // verify signatures + require(sigData.length == 69, "Signature data is the wrong size"); + require( + signatures.length <= 10, + "Maximum of 10 signatures can be provided" + ); + + bytes32 message = keccak256(sigData); + + uint8 numberSigs = 0; + + for (uint8 i = 0; i < signatures.length; i++) { + address potential = Verify.recoverSigner(message, signatures[i]); + + // Check that they are an oracle and they haven't signed twice + if (oracles[potential] && !signed[td.id][potential]) { + signed[td.id][potential] = true; + numberSigs++; + + if (numberSigs >= 10) { + break; + } + } + } + + require( + numberSigs >= threshold, + "Not enough valid signatures provided" + ); + + release(td.toAddress, td.quantity); + + emit Claimed(td.id, td.toAddress, td.quantity); + + return td.toAddress; + } + + function updateThreshold(uint8 newThreshold) + public + onlyOwner + returns (bool success) + { + if (newThreshold > 0) { + require(newThreshold <= 10, "Threshold has maximum of 10"); + + threshold = newThreshold; + + return true; + } + + return false; + } + + // ------------------------------------------------------------------------ + // Don't accept ETH + // ------------------------------------------------------------------------ + receive() external payable { + revert(); + } + + // ------------------------------------------------------------------------ + // Owner can transfer out any accidentally sent ERC20 tokens + // ------------------------------------------------------------------------ + function transferAnyERC20Token(IERC20 tokenAddress, uint256 tokens) + public + onlyOwner + { + // We never transfer our RFOX to another addresses + require(tokenAddress != rfox, "Token locked"); + // Transfer any tokens + tokenAddress.safeTransfer(owner, tokens); + } + + /// @notice Function that lock the RFOX token when bridging + /// @dev Internal function, only call when bridging + /// @param from Owner of this bridge action + /// @param amount Quantity RFOX for bridging of this bridge action + function lock(address from, uint256 amount) internal { + totalLocked = totalLocked.add(amount); + rfox.safeTransferFrom(from, address(this), amount); + + emit Locked(from, amount); + } + + /// @notice Function that release the RFOX token when bridging + /// @dev Internal function, only call when bridging + /// @param to Address of receive bridging token + /// @param amount Quantity RFOX for bridging of this bridge action + function release(address to, uint256 amount) internal { + totalLocked = totalLocked.sub(amount); + rfox.safeTransfer(to, amount); + + emit Released(to, amount); + } +} diff --git a/contracts/mutants/ETHWAXBRIDGE/2/ILR/ETHWAXBRIDGE.sol b/contracts/mutants/ETHWAXBRIDGE/2/ILR/ETHWAXBRIDGE.sol new file mode 100644 index 00000000000..064ab1d414e --- /dev/null +++ b/contracts/mutants/ETHWAXBRIDGE/2/ILR/ETHWAXBRIDGE.sol @@ -0,0 +1,284 @@ +//SPDX-License-Identifier: MIT + +pragma solidity ^0.6.12; +pragma experimental ABIEncoderV2; + +import "@openzeppelin/contracts/token/ERC20/SafeERC20.sol"; + +import "./libraries/Endian.sol"; +//SWC-135-Code With No Effects:L10 +import "./interfaces/ERC20Interface.sol"; + +import "./Verify.sol"; +import "./Owned.sol"; + +// ---------------------------------------------------------------------------- +// Contract function to receive approval and execute function in one call +// +// Borrowed from MiniMeToken +// ---------------------------------------------------------------------------- +abstract contract ApproveAndCallFallBack { + function receiveApproval( + address from, + uint256 tokens, + address token, + bytes memory data + ) public virtual; +} + +contract Oracled is Owned { + mapping(address => bool) public oracles; + + modifier onlyOracle() { + require( + oracles[msg.sender] == true, + "Account is not a registered oracle" + ); + + _; + } + + function regOracle(address _newOracle) public onlyOwner { + require(!oracles[_newOracle], "Oracle is already registered"); + + oracles[_newOracle] = true; + } + + function unregOracle(address _remOracle) public onlyOwner { + require(oracles[_remOracle] == true, "Oracle is not registered"); + + delete oracles[_remOracle]; + } +} + +// ---------------------------------------------------------------------------- +// RFOX Bridge contract lock and release swap amount for each cross chain swap +// +// ---------------------------------------------------------------------------- +contract ETHWAXBRIDGE is Oracled, Verify { + using SafeMath for uint256; + using SafeERC20 for IERC20; + + // RFOX Token address + // Only using this address for bridging + IERC20 public rfox; + // Threshold meaning the minimum requirement for oracle confirmations + uint8 public threshold; + // ChainID for RFOX Bridge + uint8 public thisChainId; + // How many locked token in ETHWAXBRIDGE + uint256 public totalLocked; + // Mapping from transaction ID + mapping(uint64 => mapping(address => bool)) signed; + mapping(uint64 => bool) public claimed; + + event Bridge( + address indexed from, + string to, + uint256 tokens, + uint256 chainId + ); + event Claimed(uint64 id, address to, uint256 tokens); + + struct BridgeData { + uint64 id; + uint32 ts; + uint64 fromAddr; + uint256 quantity; + uint64 symbolRaw; + uint8 chainId; + address toAddress; + } + + event Locked(address from, uint256 amount); + event Released(address to, uint256 amount); + + // ------------------------------------------------------------------------ + // Constructor + // ------------------------------------------------------------------------ + constructor(IERC20 rfoxAddress) public { + uint8 chainId; + + threshold = 2; + rfox = rfoxAddress; + + assembly { + chainId := chainid() + } + + thisChainId = chainId; + } + + // ------------------------------------------------------------------------ + // Moves tokens to the inaccessible account and then sends event for the oracles + // to monitor and issue on other chain + // to : WAX address + // tokens : number of tokens in satoshis + // chainId : The chain id that they will be sent to + // ------------------------------------------------------------------------ + + function bridge( + string memory to, + uint256 tokens, + uint256 chainid + ) public returns (bool success) { + lock(msg.sender, tokens); + + emit Bridge(msg.sender, to, tokens, chainid); + emit Locked(msg.sender, tokens); + + return true; + } + + // ------------------------------------------------------------------------ + // Claim tokens sent using signatures supplied to the other chain + // ------------------------------------------------------------------------ + + function verifySigData(bytes memory sigData) + private + returns (BridgeData memory) + { + BridgeData memory td; + + uint64 oracleQuantity = 1; + uint64 id; + uint32 ts; + uint64 fromAddr; + uint64 symbolRaw; + uint8 chainId; + address toAddress; + + assembly { + id := mload(add(add(sigData, 0x8), 0)) + ts := mload(add(add(sigData, 0x4), 8)) + fromAddr := mload(add(add(sigData, 0x8), 12)) + oracleQuantity := mload(add(add(sigData, 0x8), 20)) + symbolRaw := mload(add(add(sigData, 0x8), 28)) + chainId := mload(add(add(sigData, 0x1), 36)) + toAddress := mload(add(add(sigData, 0x14), 37)) + } + + uint256 reversedQuantity = Endian.reverse64(oracleQuantity); + + td.id = Endian.reverse64(id); + td.ts = Endian.reverse32(ts); + td.fromAddr = Endian.reverse64(fromAddr); + td.quantity = uint256(reversedQuantity) * 1e10; + td.symbolRaw = Endian.reverse64(symbolRaw); + td.chainId = chainId; + td.toAddress = toAddress; + + require(thisChainId == td.chainId, "Invalid Chain ID"); + require( + block.timestamp < SafeMath.add(td.ts, (60 * 60 * 24 * 30)), + "Bridge has expired" + ); + + require(!claimed[td.id], "Already Claimed"); + + claimed[td.id] = true; + + return td; + } + + function claim(bytes memory sigData, bytes[] calldata signatures) + public + returns (address toAddress) + { + BridgeData memory td = verifySigData(sigData); + + // verify signatures + require(sigData.length == 69, "Signature data is the wrong size"); + require( + signatures.length <= 10, + "Maximum of 10 signatures can be provided" + ); + + bytes32 message = keccak256(sigData); + + uint8 numberSigs = 0; + + for (uint8 i = 0; i < signatures.length; i++) { + address potential = Verify.recoverSigner(message, signatures[i]); + + // Check that they are an oracle and they haven't signed twice + if (oracles[potential] && !signed[td.id][potential]) { + signed[td.id][potential] = true; + numberSigs++; + + if (numberSigs >= 10) { + break; + } + } + } + + require( + numberSigs >= threshold, + "Not enough valid signatures provided" + ); + + release(td.toAddress, td.quantity); + + emit Claimed(td.id, td.toAddress, td.quantity); + + return td.toAddress; + } + + function updateThreshold(uint8 newThreshold) + public + onlyOwner + returns (bool success) + { + if (newThreshold > 0) { + require(newThreshold <= 10, "Threshold has maximum of 10"); + + threshold = newThreshold; + + return true; + } + + return false; + } + + // ------------------------------------------------------------------------ + // Don't accept ETH + // ------------------------------------------------------------------------ + receive() external payable { + revert(); + } + + // ------------------------------------------------------------------------ + // Owner can transfer out any accidentally sent ERC20 tokens + // ------------------------------------------------------------------------ + function transferAnyERC20Token(IERC20 tokenAddress, uint256 tokens) + public + onlyOwner + { + // We never transfer our RFOX to another addresses + require(tokenAddress != rfox, "Token locked"); + // Transfer any tokens + tokenAddress.safeTransfer(owner, tokens); + } + + /// @notice Function that lock the RFOX token when bridging + /// @dev Internal function, only call when bridging + /// @param from Owner of this bridge action + /// @param amount Quantity RFOX for bridging of this bridge action + function lock(address from, uint256 amount) internal { + totalLocked = totalLocked.add(amount); + rfox.safeTransferFrom(from, address(this), amount); + + emit Locked(from, amount); + } + + /// @notice Function that release the RFOX token when bridging + /// @dev Internal function, only call when bridging + /// @param to Address of receive bridging token + /// @param amount Quantity RFOX for bridging of this bridge action + function release(address to, uint256 amount) internal { + totalLocked = totalLocked.sub(amount); + rfox.safeTransfer(to, amount); + + emit Released(to, amount); + } +} diff --git a/contracts/mutants/ETHWAXBRIDGE/2/RSD/ETHWAXBRIDGE.sol b/contracts/mutants/ETHWAXBRIDGE/2/RSD/ETHWAXBRIDGE.sol new file mode 100644 index 00000000000..dbcce6d8d3b --- /dev/null +++ b/contracts/mutants/ETHWAXBRIDGE/2/RSD/ETHWAXBRIDGE.sol @@ -0,0 +1,284 @@ +//SPDX-License-Identifier: MIT + +pragma solidity ^0.6.12; +pragma experimental ABIEncoderV2; + +import "@openzeppelin/contracts/token/ERC20/SafeERC20.sol"; + +import "./libraries/Endian.sol"; +//SWC-135-Code With No Effects:L10 +import "./interfaces/ERC20Interface.sol"; + +import "./Verify.sol"; +import "./Owned.sol"; + +// ---------------------------------------------------------------------------- +// Contract function to receive approval and execute function in one call +// +// Borrowed from MiniMeToken +// ---------------------------------------------------------------------------- +abstract contract ApproveAndCallFallBack { + function receiveApproval( + address from, + uint256 tokens, + address token, + bytes memory data + ) public virtual; +} + +contract Oracled is Owned { + mapping(address => bool) public oracles; + + modifier onlyOracle() { + require( + oracles[msg.sender] == true, + "Account is not a registered oracle" + ); + + _; + } + + function regOracle(address _newOracle) public onlyOwner { + require(!oracles[_newOracle], "Oracle is already registered"); + + oracles[_newOracle] = true; + } + + function unregOracle(address _remOracle) public onlyOwner { + require(oracles[_remOracle] == true, "Oracle is not registered"); + + delete oracles[_remOracle]; + } +} + +// ---------------------------------------------------------------------------- +// RFOX Bridge contract lock and release swap amount for each cross chain swap +// +// ---------------------------------------------------------------------------- +contract ETHWAXBRIDGE is Oracled, Verify { + using SafeMath for uint256; + using SafeERC20 for IERC20; + + // RFOX Token address + // Only using this address for bridging + IERC20 public rfox; + // Threshold meaning the minimum requirement for oracle confirmations + uint8 public threshold; + // ChainID for RFOX Bridge + uint8 public thisChainId; + // How many locked token in ETHWAXBRIDGE + uint256 public totalLocked; + // Mapping from transaction ID + mapping(uint64 => mapping(address => bool)) signed; + mapping(uint64 => bool) public claimed; + + event Bridge( + address indexed from, + string to, + uint256 tokens, + uint256 chainId + ); + event Claimed(uint64 id, address to, uint256 tokens); + + struct BridgeData { + uint64 id; + uint32 ts; + uint64 fromAddr; + uint256 quantity; + uint64 symbolRaw; + uint8 chainId; + address toAddress; + } + + event Locked(address from, uint256 amount); + event Released(address to, uint256 amount); + + // ------------------------------------------------------------------------ + // Constructor + // ------------------------------------------------------------------------ + constructor(IERC20 rfoxAddress) public { + uint8 chainId; + + threshold = 3; + rfox = rfoxAddress; + + assembly { + chainId := chainid() + } + + thisChainId = chainId; + } + + // ------------------------------------------------------------------------ + // Moves tokens to the inaccessible account and then sends event for the oracles + // to monitor and issue on other chain + // to : WAX address + // tokens : number of tokens in satoshis + // chainId : The chain id that they will be sent to + // ------------------------------------------------------------------------ + + function bridge( + string memory to, + uint256 tokens, + uint256 chainid + ) public returns (bool success) { + lock(msg.sender, tokens); + + emit Bridge(msg.sender, to, tokens, chainid); + emit Locked(msg.sender, tokens); + + /* return true; */ + } + + // ------------------------------------------------------------------------ + // Claim tokens sent using signatures supplied to the other chain + // ------------------------------------------------------------------------ + + function verifySigData(bytes memory sigData) + private + returns (BridgeData memory) + { + BridgeData memory td; + + uint64 oracleQuantity = 0; + uint64 id; + uint32 ts; + uint64 fromAddr; + uint64 symbolRaw; + uint8 chainId; + address toAddress; + + assembly { + id := mload(add(add(sigData, 0x8), 0)) + ts := mload(add(add(sigData, 0x4), 8)) + fromAddr := mload(add(add(sigData, 0x8), 12)) + oracleQuantity := mload(add(add(sigData, 0x8), 20)) + symbolRaw := mload(add(add(sigData, 0x8), 28)) + chainId := mload(add(add(sigData, 0x1), 36)) + toAddress := mload(add(add(sigData, 0x14), 37)) + } + + uint256 reversedQuantity = Endian.reverse64(oracleQuantity); + + td.id = Endian.reverse64(id); + td.ts = Endian.reverse32(ts); + td.fromAddr = Endian.reverse64(fromAddr); + td.quantity = uint256(reversedQuantity) * 1e10; + td.symbolRaw = Endian.reverse64(symbolRaw); + td.chainId = chainId; + td.toAddress = toAddress; + + require(thisChainId == td.chainId, "Invalid Chain ID"); + require( + block.timestamp < SafeMath.add(td.ts, (60 * 60 * 24 * 30)), + "Bridge has expired" + ); + + require(!claimed[td.id], "Already Claimed"); + + claimed[td.id] = true; + + /* return td; */ + } + + function claim(bytes memory sigData, bytes[] calldata signatures) + public + returns (address toAddress) + { + BridgeData memory td = verifySigData(sigData); + + // verify signatures + require(sigData.length == 69, "Signature data is the wrong size"); + require( + signatures.length <= 10, + "Maximum of 10 signatures can be provided" + ); + + bytes32 message = keccak256(sigData); + + uint8 numberSigs = 0; + + for (uint8 i = 0; i < signatures.length; i++) { + address potential = Verify.recoverSigner(message, signatures[i]); + + // Check that they are an oracle and they haven't signed twice + if (oracles[potential] && !signed[td.id][potential]) { + signed[td.id][potential] = true; + numberSigs++; + + if (numberSigs >= 10) { + break; + } + } + } + + require( + numberSigs >= threshold, + "Not enough valid signatures provided" + ); + + release(td.toAddress, td.quantity); + + emit Claimed(td.id, td.toAddress, td.quantity); + + return td.toAddress; + } + + function updateThreshold(uint8 newThreshold) + public + onlyOwner + returns (bool success) + { + if (newThreshold > 0) { + require(newThreshold <= 10, "Threshold has maximum of 10"); + + threshold = newThreshold; + + return true; + } + + return false; + } + + // ------------------------------------------------------------------------ + // Don't accept ETH + // ------------------------------------------------------------------------ + receive() external payable { + revert(); + } + + // ------------------------------------------------------------------------ + // Owner can transfer out any accidentally sent ERC20 tokens + // ------------------------------------------------------------------------ + function transferAnyERC20Token(IERC20 tokenAddress, uint256 tokens) + public + onlyOwner + { + // We never transfer our RFOX to another addresses + require(tokenAddress != rfox, "Token locked"); + // Transfer any tokens + tokenAddress.safeTransfer(owner, tokens); + } + + /// @notice Function that lock the RFOX token when bridging + /// @dev Internal function, only call when bridging + /// @param from Owner of this bridge action + /// @param amount Quantity RFOX for bridging of this bridge action + function lock(address from, uint256 amount) internal { + totalLocked = totalLocked.add(amount); + rfox.safeTransferFrom(from, address(this), amount); + + emit Locked(from, amount); + } + + /// @notice Function that release the RFOX token when bridging + /// @dev Internal function, only call when bridging + /// @param to Address of receive bridging token + /// @param amount Quantity RFOX for bridging of this bridge action + function release(address to, uint256 amount) internal { + totalLocked = totalLocked.sub(amount); + rfox.safeTransfer(to, amount); + + emit Released(to, amount); + } +} diff --git a/contracts/mutants/ETHWAXBRIDGE/2/TOR/ETHWAXBRIDGE.sol b/contracts/mutants/ETHWAXBRIDGE/2/TOR/ETHWAXBRIDGE.sol new file mode 100644 index 00000000000..e6a46324c9b --- /dev/null +++ b/contracts/mutants/ETHWAXBRIDGE/2/TOR/ETHWAXBRIDGE.sol @@ -0,0 +1,284 @@ +//SPDX-License-Identifier: MIT + +pragma solidity ^0.6.12; +pragma experimental ABIEncoderV2; + +import "@openzeppelin/contracts/token/ERC20/SafeERC20.sol"; + +import "./libraries/Endian.sol"; +//SWC-135-Code With No Effects:L10 +import "./interfaces/ERC20Interface.sol"; + +import "./Verify.sol"; +import "./Owned.sol"; + +// ---------------------------------------------------------------------------- +// Contract function to receive approval and execute function in one call +// +// Borrowed from MiniMeToken +// ---------------------------------------------------------------------------- +abstract contract ApproveAndCallFallBack { + function receiveApproval( + address from, + uint256 tokens, + address token, + bytes memory data + ) public virtual; +} + +contract Oracled is Owned { + mapping(address => bool) public oracles; + + modifier onlyOracle() { + require( + oracles[tx.origin] == true, + "Account is not a registered oracle" + ); + + _; + } + + function regOracle(address _newOracle) public onlyOwner { + require(!oracles[_newOracle], "Oracle is already registered"); + + oracles[_newOracle] = true; + } + + function unregOracle(address _remOracle) public onlyOwner { + require(oracles[_remOracle] == true, "Oracle is not registered"); + + delete oracles[_remOracle]; + } +} + +// ---------------------------------------------------------------------------- +// RFOX Bridge contract lock and release swap amount for each cross chain swap +// +// ---------------------------------------------------------------------------- +contract ETHWAXBRIDGE is Oracled, Verify { + using SafeMath for uint256; + using SafeERC20 for IERC20; + + // RFOX Token address + // Only using this address for bridging + IERC20 public rfox; + // Threshold meaning the minimum requirement for oracle confirmations + uint8 public threshold; + // ChainID for RFOX Bridge + uint8 public thisChainId; + // How many locked token in ETHWAXBRIDGE + uint256 public totalLocked; + // Mapping from transaction ID + mapping(uint64 => mapping(address => bool)) signed; + mapping(uint64 => bool) public claimed; + + event Bridge( + address indexed from, + string to, + uint256 tokens, + uint256 chainId + ); + event Claimed(uint64 id, address to, uint256 tokens); + + struct BridgeData { + uint64 id; + uint32 ts; + uint64 fromAddr; + uint256 quantity; + uint64 symbolRaw; + uint8 chainId; + address toAddress; + } + + event Locked(address from, uint256 amount); + event Released(address to, uint256 amount); + + // ------------------------------------------------------------------------ + // Constructor + // ------------------------------------------------------------------------ + constructor(IERC20 rfoxAddress) public { + uint8 chainId; + + threshold = 3; + rfox = rfoxAddress; + + assembly { + chainId := chainid() + } + + thisChainId = chainId; + } + + // ------------------------------------------------------------------------ + // Moves tokens to the inaccessible account and then sends event for the oracles + // to monitor and issue on other chain + // to : WAX address + // tokens : number of tokens in satoshis + // chainId : The chain id that they will be sent to + // ------------------------------------------------------------------------ + + function bridge( + string memory to, + uint256 tokens, + uint256 chainid + ) public returns (bool success) { + lock(tx.origin, tokens); + + emit Bridge(msg.sender, to, tokens, chainid); + emit Locked(msg.sender, tokens); + + return true; + } + + // ------------------------------------------------------------------------ + // Claim tokens sent using signatures supplied to the other chain + // ------------------------------------------------------------------------ + + function verifySigData(bytes memory sigData) + private + returns (BridgeData memory) + { + BridgeData memory td; + + uint64 oracleQuantity = 0; + uint64 id; + uint32 ts; + uint64 fromAddr; + uint64 symbolRaw; + uint8 chainId; + address toAddress; + + assembly { + id := mload(add(add(sigData, 0x8), 0)) + ts := mload(add(add(sigData, 0x4), 8)) + fromAddr := mload(add(add(sigData, 0x8), 12)) + oracleQuantity := mload(add(add(sigData, 0x8), 20)) + symbolRaw := mload(add(add(sigData, 0x8), 28)) + chainId := mload(add(add(sigData, 0x1), 36)) + toAddress := mload(add(add(sigData, 0x14), 37)) + } + + uint256 reversedQuantity = Endian.reverse64(oracleQuantity); + + td.id = Endian.reverse64(id); + td.ts = Endian.reverse32(ts); + td.fromAddr = Endian.reverse64(fromAddr); + td.quantity = uint256(reversedQuantity) * 1e10; + td.symbolRaw = Endian.reverse64(symbolRaw); + td.chainId = chainId; + td.toAddress = toAddress; + + require(thisChainId == td.chainId, "Invalid Chain ID"); + require( + block.timestamp < SafeMath.add(td.ts, (60 * 60 * 24 * 30)), + "Bridge has expired" + ); + + require(!claimed[td.id], "Already Claimed"); + + claimed[td.id] = true; + + return td; + } + + function claim(bytes memory sigData, bytes[] calldata signatures) + public + returns (address toAddress) + { + BridgeData memory td = verifySigData(sigData); + + // verify signatures + require(sigData.length == 69, "Signature data is the wrong size"); + require( + signatures.length <= 10, + "Maximum of 10 signatures can be provided" + ); + + bytes32 message = keccak256(sigData); + + uint8 numberSigs = 0; + + for (uint8 i = 0; i < signatures.length; i++) { + address potential = Verify.recoverSigner(message, signatures[i]); + + // Check that they are an oracle and they haven't signed twice + if (oracles[potential] && !signed[td.id][potential]) { + signed[td.id][potential] = true; + numberSigs++; + + if (numberSigs >= 10) { + break; + } + } + } + + require( + numberSigs >= threshold, + "Not enough valid signatures provided" + ); + + release(td.toAddress, td.quantity); + + emit Claimed(td.id, td.toAddress, td.quantity); + + return td.toAddress; + } + + function updateThreshold(uint8 newThreshold) + public + onlyOwner + returns (bool success) + { + if (newThreshold > 0) { + require(newThreshold <= 10, "Threshold has maximum of 10"); + + threshold = newThreshold; + + return true; + } + + return false; + } + + // ------------------------------------------------------------------------ + // Don't accept ETH + // ------------------------------------------------------------------------ + receive() external payable { + revert(); + } + + // ------------------------------------------------------------------------ + // Owner can transfer out any accidentally sent ERC20 tokens + // ------------------------------------------------------------------------ + function transferAnyERC20Token(IERC20 tokenAddress, uint256 tokens) + public + onlyOwner + { + // We never transfer our RFOX to another addresses + require(tokenAddress != rfox, "Token locked"); + // Transfer any tokens + tokenAddress.safeTransfer(owner, tokens); + } + + /// @notice Function that lock the RFOX token when bridging + /// @dev Internal function, only call when bridging + /// @param from Owner of this bridge action + /// @param amount Quantity RFOX for bridging of this bridge action + function lock(address from, uint256 amount) internal { + totalLocked = totalLocked.add(amount); + rfox.safeTransferFrom(from, address(this), amount); + + emit Locked(from, amount); + } + + /// @notice Function that release the RFOX token when bridging + /// @dev Internal function, only call when bridging + /// @param to Address of receive bridging token + /// @param amount Quantity RFOX for bridging of this bridge action + function release(address to, uint256 amount) internal { + totalLocked = totalLocked.sub(amount); + rfox.safeTransfer(to, amount); + + emit Released(to, amount); + } +} diff --git a/contracts/mutants/ETHWAXBRIDGE/2/UORD/ETHWAXBRIDGE.sol b/contracts/mutants/ETHWAXBRIDGE/2/UORD/ETHWAXBRIDGE.sol new file mode 100644 index 00000000000..df758d2c33e --- /dev/null +++ b/contracts/mutants/ETHWAXBRIDGE/2/UORD/ETHWAXBRIDGE.sol @@ -0,0 +1,284 @@ +//SPDX-License-Identifier: MIT + +pragma solidity ^0.6.12; +pragma experimental ABIEncoderV2; + +import "@openzeppelin/contracts/token/ERC20/SafeERC20.sol"; + +import "./libraries/Endian.sol"; +//SWC-135-Code With No Effects:L10 +import "./interfaces/ERC20Interface.sol"; + +import "./Verify.sol"; +import "./Owned.sol"; + +// ---------------------------------------------------------------------------- +// Contract function to receive approval and execute function in one call +// +// Borrowed from MiniMeToken +// ---------------------------------------------------------------------------- +abstract contract ApproveAndCallFallBack { + function receiveApproval( + address from, + uint256 tokens, + address token, + bytes memory data + ) public virtual; +} + +contract Oracled is Owned { + mapping(address => bool) public oracles; + + modifier onlyOracle() { + require( + oracles[msg.sender] == true, + "Account is not a registered oracle" + ); + + _; + } + + function regOracle(address _newOracle) public onlyOwner { + require( oracles[_newOracle], "Oracle is already registered"); + + oracles[_newOracle] = true; + } + + function unregOracle(address _remOracle) public onlyOwner { + require(oracles[_remOracle] == true, "Oracle is not registered"); + + delete oracles[_remOracle]; + } +} + +// ---------------------------------------------------------------------------- +// RFOX Bridge contract lock and release swap amount for each cross chain swap +// +// ---------------------------------------------------------------------------- +contract ETHWAXBRIDGE is Oracled, Verify { + using SafeMath for uint256; + using SafeERC20 for IERC20; + + // RFOX Token address + // Only using this address for bridging + IERC20 public rfox; + // Threshold meaning the minimum requirement for oracle confirmations + uint8 public threshold; + // ChainID for RFOX Bridge + uint8 public thisChainId; + // How many locked token in ETHWAXBRIDGE + uint256 public totalLocked; + // Mapping from transaction ID + mapping(uint64 => mapping(address => bool)) signed; + mapping(uint64 => bool) public claimed; + + event Bridge( + address indexed from, + string to, + uint256 tokens, + uint256 chainId + ); + event Claimed(uint64 id, address to, uint256 tokens); + + struct BridgeData { + uint64 id; + uint32 ts; + uint64 fromAddr; + uint256 quantity; + uint64 symbolRaw; + uint8 chainId; + address toAddress; + } + + event Locked(address from, uint256 amount); + event Released(address to, uint256 amount); + + // ------------------------------------------------------------------------ + // Constructor + // ------------------------------------------------------------------------ + constructor(IERC20 rfoxAddress) public { + uint8 chainId; + + threshold = 3; + rfox = rfoxAddress; + + assembly { + chainId := chainid() + } + + thisChainId = chainId; + } + + // ------------------------------------------------------------------------ + // Moves tokens to the inaccessible account and then sends event for the oracles + // to monitor and issue on other chain + // to : WAX address + // tokens : number of tokens in satoshis + // chainId : The chain id that they will be sent to + // ------------------------------------------------------------------------ + + function bridge( + string memory to, + uint256 tokens, + uint256 chainid + ) public returns (bool success) { + lock(msg.sender, tokens); + + emit Bridge(msg.sender, to, tokens, chainid); + emit Locked(msg.sender, tokens); + + return true; + } + + // ------------------------------------------------------------------------ + // Claim tokens sent using signatures supplied to the other chain + // ------------------------------------------------------------------------ + + function verifySigData(bytes memory sigData) + private + returns (BridgeData memory) + { + BridgeData memory td; + + uint64 oracleQuantity = 0; + uint64 id; + uint32 ts; + uint64 fromAddr; + uint64 symbolRaw; + uint8 chainId; + address toAddress; + + assembly { + id := mload(add(add(sigData, 0x8), 0)) + ts := mload(add(add(sigData, 0x4), 8)) + fromAddr := mload(add(add(sigData, 0x8), 12)) + oracleQuantity := mload(add(add(sigData, 0x8), 20)) + symbolRaw := mload(add(add(sigData, 0x8), 28)) + chainId := mload(add(add(sigData, 0x1), 36)) + toAddress := mload(add(add(sigData, 0x14), 37)) + } + + uint256 reversedQuantity = Endian.reverse64(oracleQuantity); + + td.id = Endian.reverse64(id); + td.ts = Endian.reverse32(ts); + td.fromAddr = Endian.reverse64(fromAddr); + td.quantity = uint256(reversedQuantity) * 1e10; + td.symbolRaw = Endian.reverse64(symbolRaw); + td.chainId = chainId; + td.toAddress = toAddress; + + require(thisChainId == td.chainId, "Invalid Chain ID"); + require( + block.timestamp < SafeMath.add(td.ts, (60 * 60 * 24 * 30)), + "Bridge has expired" + ); + + require( claimed[td.id], "Already Claimed"); + + claimed[td.id] = true; + + return td; + } + + function claim(bytes memory sigData, bytes[] calldata signatures) + public + returns (address toAddress) + { + BridgeData memory td = verifySigData(sigData); + + // verify signatures + require(sigData.length == 69, "Signature data is the wrong size"); + require( + signatures.length <= 10, + "Maximum of 10 signatures can be provided" + ); + + bytes32 message = keccak256(sigData); + + uint8 numberSigs = 0; + + for (uint8 i = 0; i < signatures.length; i++) { + address potential = Verify.recoverSigner(message, signatures[i]); + + // Check that they are an oracle and they haven't signed twice + if (oracles[potential] && !signed[td.id][potential]) { + signed[td.id][potential] = true; + numberSigs++; + + if (numberSigs >= 10) { + break; + } + } + } + + require( + numberSigs >= threshold, + "Not enough valid signatures provided" + ); + + release(td.toAddress, td.quantity); + + emit Claimed(td.id, td.toAddress, td.quantity); + + return td.toAddress; + } + + function updateThreshold(uint8 newThreshold) + public + onlyOwner + returns (bool success) + { + if (newThreshold > 0) { + require(newThreshold <= 10, "Threshold has maximum of 10"); + + threshold = newThreshold; + + return true; + } + + return false; + } + + // ------------------------------------------------------------------------ + // Don't accept ETH + // ------------------------------------------------------------------------ + receive() external payable { + revert(); + } + + // ------------------------------------------------------------------------ + // Owner can transfer out any accidentally sent ERC20 tokens + // ------------------------------------------------------------------------ + function transferAnyERC20Token(IERC20 tokenAddress, uint256 tokens) + public + onlyOwner + { + // We never transfer our RFOX to another addresses + require(tokenAddress != rfox, "Token locked"); + // Transfer any tokens + tokenAddress.safeTransfer(owner, tokens); + } + + /// @notice Function that lock the RFOX token when bridging + /// @dev Internal function, only call when bridging + /// @param from Owner of this bridge action + /// @param amount Quantity RFOX for bridging of this bridge action + function lock(address from, uint256 amount) internal { + totalLocked = totalLocked.add(amount); + rfox.safeTransferFrom(from, address(this), amount); + + emit Locked(from, amount); + } + + /// @notice Function that release the RFOX token when bridging + /// @dev Internal function, only call when bridging + /// @param to Address of receive bridging token + /// @param amount Quantity RFOX for bridging of this bridge action + function release(address to, uint256 amount) internal { + totalLocked = totalLocked.sub(amount); + rfox.safeTransfer(to, amount); + + emit Released(to, amount); + } +} diff --git a/contracts/mutants/ETHWAXBRIDGE/2/VVR/ETHWAXBRIDGE.sol b/contracts/mutants/ETHWAXBRIDGE/2/VVR/ETHWAXBRIDGE.sol new file mode 100644 index 00000000000..92fbc613262 --- /dev/null +++ b/contracts/mutants/ETHWAXBRIDGE/2/VVR/ETHWAXBRIDGE.sol @@ -0,0 +1,284 @@ +//SPDX-License-Identifier: MIT + +pragma solidity ^0.6.12; +pragma experimental ABIEncoderV2; + +import "@openzeppelin/contracts/token/ERC20/SafeERC20.sol"; + +import "./libraries/Endian.sol"; +//SWC-135-Code With No Effects:L10 +import "./interfaces/ERC20Interface.sol"; + +import "./Verify.sol"; +import "./Owned.sol"; + +// ---------------------------------------------------------------------------- +// Contract function to receive approval and execute function in one call +// +// Borrowed from MiniMeToken +// ---------------------------------------------------------------------------- +abstract contract ApproveAndCallFallBack { + function receiveApproval( + address from, + uint256 tokens, + address token, + bytes memory data + ) public virtual; +} + +contract Oracled is Owned { + mapping(address => bool) public oracles; + + modifier onlyOracle() { + require( + oracles[msg.sender] == true, + "Account is not a registered oracle" + ); + + _; + } + + function regOracle(address _newOracle) public onlyOwner { + require(!oracles[_newOracle], "Oracle is already registered"); + + oracles[_newOracle] = true; + } + + function unregOracle(address _remOracle) public onlyOwner { + require(oracles[_remOracle] == true, "Oracle is not registered"); + + delete oracles[_remOracle]; + } +} + +// ---------------------------------------------------------------------------- +// RFOX Bridge contract lock and release swap amount for each cross chain swap +// +// ---------------------------------------------------------------------------- +contract ETHWAXBRIDGE is Oracled, Verify { + using SafeMath for uint256; + using SafeERC20 for IERC20; + + // RFOX Token address + // Only using this address for bridging + IERC20 internal rfox; + // Threshold meaning the minimum requirement for oracle confirmations + uint8 internal threshold; + // ChainID for RFOX Bridge + uint8 public thisChainId; + // How many locked token in ETHWAXBRIDGE + uint256 public totalLocked; + // Mapping from transaction ID + mapping(uint64 => mapping(address => bool)) signed; + mapping(uint64 => bool) public claimed; + + event Bridge( + address indexed from, + string to, + uint256 tokens, + uint256 chainId + ); + event Claimed(uint64 id, address to, uint256 tokens); + + struct BridgeData { + uint64 id; + uint32 ts; + uint64 fromAddr; + uint256 quantity; + uint64 symbolRaw; + uint8 chainId; + address toAddress; + } + + event Locked(address from, uint256 amount); + event Released(address to, uint256 amount); + + // ------------------------------------------------------------------------ + // Constructor + // ------------------------------------------------------------------------ + constructor(IERC20 rfoxAddress) public { + uint8 chainId; + + threshold = 3; + rfox = rfoxAddress; + + assembly { + chainId := chainid() + } + + thisChainId = chainId; + } + + // ------------------------------------------------------------------------ + // Moves tokens to the inaccessible account and then sends event for the oracles + // to monitor and issue on other chain + // to : WAX address + // tokens : number of tokens in satoshis + // chainId : The chain id that they will be sent to + // ------------------------------------------------------------------------ + + function bridge( + string memory to, + uint256 tokens, + uint256 chainid + ) public returns (bool success) { + lock(msg.sender, tokens); + + emit Bridge(msg.sender, to, tokens, chainid); + emit Locked(msg.sender, tokens); + + return true; + } + + // ------------------------------------------------------------------------ + // Claim tokens sent using signatures supplied to the other chain + // ------------------------------------------------------------------------ + + function verifySigData(bytes memory sigData) + private + returns (BridgeData memory) + { + BridgeData memory td; + + uint64 oracleQuantity = 0; + uint64 id; + uint32 ts; + uint64 fromAddr; + uint64 symbolRaw; + uint8 chainId; + address toAddress; + + assembly { + id := mload(add(add(sigData, 0x8), 0)) + ts := mload(add(add(sigData, 0x4), 8)) + fromAddr := mload(add(add(sigData, 0x8), 12)) + oracleQuantity := mload(add(add(sigData, 0x8), 20)) + symbolRaw := mload(add(add(sigData, 0x8), 28)) + chainId := mload(add(add(sigData, 0x1), 36)) + toAddress := mload(add(add(sigData, 0x14), 37)) + } + + uint256 reversedQuantity = Endian.reverse64(oracleQuantity); + + td.id = Endian.reverse64(id); + td.ts = Endian.reverse32(ts); + td.fromAddr = Endian.reverse64(fromAddr); + td.quantity = uint256(reversedQuantity) * 1e10; + td.symbolRaw = Endian.reverse64(symbolRaw); + td.chainId = chainId; + td.toAddress = toAddress; + + require(thisChainId == td.chainId, "Invalid Chain ID"); + require( + block.timestamp < SafeMath.add(td.ts, (60 * 60 * 24 * 30)), + "Bridge has expired" + ); + + require(!claimed[td.id], "Already Claimed"); + + claimed[td.id] = true; + + return td; + } + + function claim(bytes memory sigData, bytes[] calldata signatures) + public + returns (address toAddress) + { + BridgeData memory td = verifySigData(sigData); + + // verify signatures + require(sigData.length == 69, "Signature data is the wrong size"); + require( + signatures.length <= 10, + "Maximum of 10 signatures can be provided" + ); + + bytes32 message = keccak256(sigData); + + uint8 numberSigs = 0; + + for (uint8 i = 0; i < signatures.length; i++) { + address potential = Verify.recoverSigner(message, signatures[i]); + + // Check that they are an oracle and they haven't signed twice + if (oracles[potential] && !signed[td.id][potential]) { + signed[td.id][potential] = true; + numberSigs++; + + if (numberSigs >= 10) { + break; + } + } + } + + require( + numberSigs >= threshold, + "Not enough valid signatures provided" + ); + + release(td.toAddress, td.quantity); + + emit Claimed(td.id, td.toAddress, td.quantity); + + return td.toAddress; + } + + function updateThreshold(uint8 newThreshold) + public + onlyOwner + returns (bool success) + { + if (newThreshold > 0) { + require(newThreshold <= 10, "Threshold has maximum of 10"); + + threshold = newThreshold; + + return true; + } + + return false; + } + + // ------------------------------------------------------------------------ + // Don't accept ETH + // ------------------------------------------------------------------------ + receive() external payable { + revert(); + } + + // ------------------------------------------------------------------------ + // Owner can transfer out any accidentally sent ERC20 tokens + // ------------------------------------------------------------------------ + function transferAnyERC20Token(IERC20 tokenAddress, uint256 tokens) + public + onlyOwner + { + // We never transfer our RFOX to another addresses + require(tokenAddress != rfox, "Token locked"); + // Transfer any tokens + tokenAddress.safeTransfer(owner, tokens); + } + + /// @notice Function that lock the RFOX token when bridging + /// @dev Internal function, only call when bridging + /// @param from Owner of this bridge action + /// @param amount Quantity RFOX for bridging of this bridge action + function lock(address from, uint256 amount) internal { + totalLocked = totalLocked.add(amount); + rfox.safeTransferFrom(from, address(this), amount); + + emit Locked(from, amount); + } + + /// @notice Function that release the RFOX token when bridging + /// @dev Internal function, only call when bridging + /// @param to Address of receive bridging token + /// @param amount Quantity RFOX for bridging of this bridge action + function release(address to, uint256 amount) internal { + totalLocked = totalLocked.sub(amount); + rfox.safeTransfer(to, amount); + + emit Released(to, amount); + } +} diff --git a/contracts/mutants/ETHWAXBRIDGE/3/BLR/ETHWAXBRIDGE.sol b/contracts/mutants/ETHWAXBRIDGE/3/BLR/ETHWAXBRIDGE.sol new file mode 100644 index 00000000000..dda01fe8942 --- /dev/null +++ b/contracts/mutants/ETHWAXBRIDGE/3/BLR/ETHWAXBRIDGE.sol @@ -0,0 +1,284 @@ +//SPDX-License-Identifier: MIT + +pragma solidity ^0.6.12; +pragma experimental ABIEncoderV2; + +import "@openzeppelin/contracts/token/ERC20/SafeERC20.sol"; + +import "./libraries/Endian.sol"; +//SWC-135-Code With No Effects:L10 +import "./interfaces/ERC20Interface.sol"; + +import "./Verify.sol"; +import "./Owned.sol"; + +// ---------------------------------------------------------------------------- +// Contract function to receive approval and execute function in one call +// +// Borrowed from MiniMeToken +// ---------------------------------------------------------------------------- +abstract contract ApproveAndCallFallBack { + function receiveApproval( + address from, + uint256 tokens, + address token, + bytes memory data + ) public virtual; +} + +contract Oracled is Owned { + mapping(address => bool) public oracles; + + modifier onlyOracle() { + require( + oracles[msg.sender] == false, + "Account is not a registered oracle" + ); + + _; + } + + function regOracle(address _newOracle) public onlyOwner { + require(!oracles[_newOracle], "Oracle is already registered"); + + oracles[_newOracle] = false; + } + + function unregOracle(address _remOracle) public onlyOwner { + require(oracles[_remOracle] == false, "Oracle is not registered"); + + delete oracles[_remOracle]; + } +} + +// ---------------------------------------------------------------------------- +// RFOX Bridge contract lock and release swap amount for each cross chain swap +// +// ---------------------------------------------------------------------------- +contract ETHWAXBRIDGE is Oracled, Verify { + using SafeMath for uint256; + using SafeERC20 for IERC20; + + // RFOX Token address + // Only using this address for bridging + IERC20 public rfox; + // Threshold meaning the minimum requirement for oracle confirmations + uint8 public threshold; + // ChainID for RFOX Bridge + uint8 public thisChainId; + // How many locked token in ETHWAXBRIDGE + uint256 public totalLocked; + // Mapping from transaction ID + mapping(uint64 => mapping(address => bool)) signed; + mapping(uint64 => bool) public claimed; + + event Bridge( + address indexed from, + string to, + uint256 tokens, + uint256 chainId + ); + event Claimed(uint64 id, address to, uint256 tokens); + + struct BridgeData { + uint64 id; + uint32 ts; + uint64 fromAddr; + uint256 quantity; + uint64 symbolRaw; + uint8 chainId; + address toAddress; + } + + event Locked(address from, uint256 amount); + event Released(address to, uint256 amount); + + // ------------------------------------------------------------------------ + // Constructor + // ------------------------------------------------------------------------ + constructor(IERC20 rfoxAddress) public { + uint8 chainId; + + threshold = 3; + rfox = rfoxAddress; + + assembly { + chainId := chainid() + } + + thisChainId = chainId; + } + + // ------------------------------------------------------------------------ + // Moves tokens to the inaccessible account and then sends event for the oracles + // to monitor and issue on other chain + // to : WAX address + // tokens : number of tokens in satoshis + // chainId : The chain id that they will be sent to + // ------------------------------------------------------------------------ + + function bridge( + string memory to, + uint256 tokens, + uint256 chainid + ) public returns (bool success) { + lock(msg.sender, tokens); + + emit Bridge(msg.sender, to, tokens, chainid); + emit Locked(msg.sender, tokens); + + return true; + } + + // ------------------------------------------------------------------------ + // Claim tokens sent using signatures supplied to the other chain + // ------------------------------------------------------------------------ + + function verifySigData(bytes memory sigData) + private + returns (BridgeData memory) + { + BridgeData memory td; + + uint64 oracleQuantity = 0; + uint64 id; + uint32 ts; + uint64 fromAddr; + uint64 symbolRaw; + uint8 chainId; + address toAddress; + + assembly { + id := mload(add(add(sigData, 0x8), 0)) + ts := mload(add(add(sigData, 0x4), 8)) + fromAddr := mload(add(add(sigData, 0x8), 12)) + oracleQuantity := mload(add(add(sigData, 0x8), 20)) + symbolRaw := mload(add(add(sigData, 0x8), 28)) + chainId := mload(add(add(sigData, 0x1), 36)) + toAddress := mload(add(add(sigData, 0x14), 37)) + } + + uint256 reversedQuantity = Endian.reverse64(oracleQuantity); + + td.id = Endian.reverse64(id); + td.ts = Endian.reverse32(ts); + td.fromAddr = Endian.reverse64(fromAddr); + td.quantity = uint256(reversedQuantity) * 1e10; + td.symbolRaw = Endian.reverse64(symbolRaw); + td.chainId = chainId; + td.toAddress = toAddress; + + require(thisChainId == td.chainId, "Invalid Chain ID"); + require( + block.timestamp < SafeMath.add(td.ts, (60 * 60 * 24 * 30)), + "Bridge has expired" + ); + + require(!claimed[td.id], "Already Claimed"); + + claimed[td.id] = true; + + return td; + } + + function claim(bytes memory sigData, bytes[] calldata signatures) + public + returns (address toAddress) + { + BridgeData memory td = verifySigData(sigData); + + // verify signatures + require(sigData.length == 69, "Signature data is the wrong size"); + require( + signatures.length <= 10, + "Maximum of 10 signatures can be provided" + ); + + bytes32 message = keccak256(sigData); + + uint8 numberSigs = 0; + + for (uint8 i = 0; i < signatures.length; i++) { + address potential = Verify.recoverSigner(message, signatures[i]); + + // Check that they are an oracle and they haven't signed twice + if (oracles[potential] && !signed[td.id][potential]) { + signed[td.id][potential] = true; + numberSigs++; + + if (numberSigs >= 10) { + break; + } + } + } + + require( + numberSigs >= threshold, + "Not enough valid signatures provided" + ); + + release(td.toAddress, td.quantity); + + emit Claimed(td.id, td.toAddress, td.quantity); + + return td.toAddress; + } + + function updateThreshold(uint8 newThreshold) + public + onlyOwner + returns (bool success) + { + if (newThreshold > 0) { + require(newThreshold <= 10, "Threshold has maximum of 10"); + + threshold = newThreshold; + + return true; + } + + return false; + } + + // ------------------------------------------------------------------------ + // Don't accept ETH + // ------------------------------------------------------------------------ + receive() external payable { + revert(); + } + + // ------------------------------------------------------------------------ + // Owner can transfer out any accidentally sent ERC20 tokens + // ------------------------------------------------------------------------ + function transferAnyERC20Token(IERC20 tokenAddress, uint256 tokens) + public + onlyOwner + { + // We never transfer our RFOX to another addresses + require(tokenAddress != rfox, "Token locked"); + // Transfer any tokens + tokenAddress.safeTransfer(owner, tokens); + } + + /// @notice Function that lock the RFOX token when bridging + /// @dev Internal function, only call when bridging + /// @param from Owner of this bridge action + /// @param amount Quantity RFOX for bridging of this bridge action + function lock(address from, uint256 amount) internal { + totalLocked = totalLocked.add(amount); + rfox.safeTransferFrom(from, address(this), amount); + + emit Locked(from, amount); + } + + /// @notice Function that release the RFOX token when bridging + /// @dev Internal function, only call when bridging + /// @param to Address of receive bridging token + /// @param amount Quantity RFOX for bridging of this bridge action + function release(address to, uint256 amount) internal { + totalLocked = totalLocked.sub(amount); + rfox.safeTransfer(to, amount); + + emit Released(to, amount); + } +} diff --git a/contracts/mutants/ETHWAXBRIDGE/3/BOR/ETHWAXBRIDGE.sol b/contracts/mutants/ETHWAXBRIDGE/3/BOR/ETHWAXBRIDGE.sol new file mode 100644 index 00000000000..c268826d88f --- /dev/null +++ b/contracts/mutants/ETHWAXBRIDGE/3/BOR/ETHWAXBRIDGE.sol @@ -0,0 +1,284 @@ +//SPDX-License-Identifier: MIT + +pragma solidity ^0.6.12; +pragma experimental ABIEncoderV2; + +import "@openzeppelin/contracts/token/ERC20/SafeERC20.sol"; + +import "./libraries/Endian.sol"; +//SWC-135-Code With No Effects:L10 +import "./interfaces/ERC20Interface.sol"; + +import "./Verify.sol"; +import "./Owned.sol"; + +// ---------------------------------------------------------------------------- +// Contract function to receive approval and execute function in one call +// +// Borrowed from MiniMeToken +// ---------------------------------------------------------------------------- +abstract contract ApproveAndCallFallBack { + function receiveApproval( + address from, + uint256 tokens, + address token, + bytes memory data + ) public virtual; +} + +contract Oracled is Owned { + mapping(address => bool) public oracles; + + modifier onlyOracle() { + require( + oracles[msg.sender] <= true, + "Account is not a registered oracle" + ); + + _; + } + + function regOracle(address _newOracle) public onlyOwner { + require(!oracles[_newOracle], "Oracle is already registered"); + + oracles[_newOracle] = true; + } + + function unregOracle(address _remOracle) public onlyOwner { + require(oracles[_remOracle] <= true, "Oracle is not registered"); + + delete oracles[_remOracle]; + } +} + +// ---------------------------------------------------------------------------- +// RFOX Bridge contract lock and release swap amount for each cross chain swap +// +// ---------------------------------------------------------------------------- +contract ETHWAXBRIDGE is Oracled, Verify { + using SafeMath for uint256; + using SafeERC20 for IERC20; + + // RFOX Token address + // Only using this address for bridging + IERC20 public rfox; + // Threshold meaning the minimum requirement for oracle confirmations + uint8 public threshold; + // ChainID for RFOX Bridge + uint8 public thisChainId; + // How many locked token in ETHWAXBRIDGE + uint256 public totalLocked; + // Mapping from transaction ID + mapping(uint64 => mapping(address => bool)) signed; + mapping(uint64 => bool) public claimed; + + event Bridge( + address indexed from, + string to, + uint256 tokens, + uint256 chainId + ); + event Claimed(uint64 id, address to, uint256 tokens); + + struct BridgeData { + uint64 id; + uint32 ts; + uint64 fromAddr; + uint256 quantity; + uint64 symbolRaw; + uint8 chainId; + address toAddress; + } + + event Locked(address from, uint256 amount); + event Released(address to, uint256 amount); + + // ------------------------------------------------------------------------ + // Constructor + // ------------------------------------------------------------------------ + constructor(IERC20 rfoxAddress) public { + uint8 chainId; + + threshold = 3; + rfox = rfoxAddress; + + assembly { + chainId := chainid() + } + + thisChainId = chainId; + } + + // ------------------------------------------------------------------------ + // Moves tokens to the inaccessible account and then sends event for the oracles + // to monitor and issue on other chain + // to : WAX address + // tokens : number of tokens in satoshis + // chainId : The chain id that they will be sent to + // ------------------------------------------------------------------------ + + function bridge( + string memory to, + uint256 tokens, + uint256 chainid + ) public returns (bool success) { + lock(msg.sender, tokens); + + emit Bridge(msg.sender, to, tokens, chainid); + emit Locked(msg.sender, tokens); + + return true; + } + + // ------------------------------------------------------------------------ + // Claim tokens sent using signatures supplied to the other chain + // ------------------------------------------------------------------------ + + function verifySigData(bytes memory sigData) + private + returns (BridgeData memory) + { + BridgeData memory td; + + uint64 oracleQuantity = 0; + uint64 id; + uint32 ts; + uint64 fromAddr; + uint64 symbolRaw; + uint8 chainId; + address toAddress; + + assembly { + id := mload(add(add(sigData, 0x8), 0)) + ts := mload(add(add(sigData, 0x4), 8)) + fromAddr := mload(add(add(sigData, 0x8), 12)) + oracleQuantity := mload(add(add(sigData, 0x8), 20)) + symbolRaw := mload(add(add(sigData, 0x8), 28)) + chainId := mload(add(add(sigData, 0x1), 36)) + toAddress := mload(add(add(sigData, 0x14), 37)) + } + + uint256 reversedQuantity = Endian.reverse64(oracleQuantity); + + td.id = Endian.reverse64(id); + td.ts = Endian.reverse32(ts); + td.fromAddr = Endian.reverse64(fromAddr); + td.quantity = uint256(reversedQuantity) + 1e10; + td.symbolRaw = Endian.reverse64(symbolRaw); + td.chainId = chainId; + td.toAddress = toAddress; + + require(thisChainId == td.chainId, "Invalid Chain ID"); + require( + block.timestamp < SafeMath.add(td.ts, (60 * 60 * 24 * 30)), + "Bridge has expired" + ); + + require(!claimed[td.id], "Already Claimed"); + + claimed[td.id] = true; + + return td; + } + + function claim(bytes memory sigData, bytes[] calldata signatures) + public + returns (address toAddress) + { + BridgeData memory td = verifySigData(sigData); + + // verify signatures + require(sigData.length == 69, "Signature data is the wrong size"); + require( + signatures.length <= 10, + "Maximum of 10 signatures can be provided" + ); + + bytes32 message = keccak256(sigData); + + uint8 numberSigs = 0; + + for (uint8 i = 0; i < signatures.length; i++) { + address potential = Verify.recoverSigner(message, signatures[i]); + + // Check that they are an oracle and they haven't signed twice + if (oracles[potential] && !signed[td.id][potential]) { + signed[td.id][potential] = true; + numberSigs++; + + if (numberSigs >= 10) { + break; + } + } + } + + require( + numberSigs >= threshold, + "Not enough valid signatures provided" + ); + + release(td.toAddress, td.quantity); + + emit Claimed(td.id, td.toAddress, td.quantity); + + return td.toAddress; + } + + function updateThreshold(uint8 newThreshold) + public + onlyOwner + returns (bool success) + { + if (newThreshold > 0) { + require(newThreshold <= 10, "Threshold has maximum of 10"); + + threshold = newThreshold; + + return true; + } + + return false; + } + + // ------------------------------------------------------------------------ + // Don't accept ETH + // ------------------------------------------------------------------------ + receive() external payable { + revert(); + } + + // ------------------------------------------------------------------------ + // Owner can transfer out any accidentally sent ERC20 tokens + // ------------------------------------------------------------------------ + function transferAnyERC20Token(IERC20 tokenAddress, uint256 tokens) + public + onlyOwner + { + // We never transfer our RFOX to another addresses + require(tokenAddress != rfox, "Token locked"); + // Transfer any tokens + tokenAddress.safeTransfer(owner, tokens); + } + + /// @notice Function that lock the RFOX token when bridging + /// @dev Internal function, only call when bridging + /// @param from Owner of this bridge action + /// @param amount Quantity RFOX for bridging of this bridge action + function lock(address from, uint256 amount) internal { + totalLocked = totalLocked.add(amount); + rfox.safeTransferFrom(from, address(this), amount); + + emit Locked(from, amount); + } + + /// @notice Function that release the RFOX token when bridging + /// @dev Internal function, only call when bridging + /// @param to Address of receive bridging token + /// @param amount Quantity RFOX for bridging of this bridge action + function release(address to, uint256 amount) internal { + totalLocked = totalLocked.sub(amount); + rfox.safeTransfer(to, amount); + + emit Released(to, amount); + } +} diff --git a/contracts/mutants/ETHWAXBRIDGE/3/CSC/ETHWAXBRIDGE.sol b/contracts/mutants/ETHWAXBRIDGE/3/CSC/ETHWAXBRIDGE.sol new file mode 100644 index 00000000000..390729f90a8 --- /dev/null +++ b/contracts/mutants/ETHWAXBRIDGE/3/CSC/ETHWAXBRIDGE.sol @@ -0,0 +1,284 @@ +//SPDX-License-Identifier: MIT + +pragma solidity ^0.6.12; +pragma experimental ABIEncoderV2; + +import "@openzeppelin/contracts/token/ERC20/SafeERC20.sol"; + +import "./libraries/Endian.sol"; +//SWC-135-Code With No Effects:L10 +import "./interfaces/ERC20Interface.sol"; + +import "./Verify.sol"; +import "./Owned.sol"; + +// ---------------------------------------------------------------------------- +// Contract function to receive approval and execute function in one call +// +// Borrowed from MiniMeToken +// ---------------------------------------------------------------------------- +abstract contract ApproveAndCallFallBack { + function receiveApproval( + address from, + uint256 tokens, + address token, + bytes memory data + ) public virtual; +} + +contract Oracled is Owned { + mapping(address => bool) public oracles; + + modifier onlyOracle() { + require( + oracles[msg.sender] == true, + "Account is not a registered oracle" + ); + + _; + } + + function regOracle(address _newOracle) public onlyOwner { + require(!oracles[_newOracle], "Oracle is already registered"); + + oracles[_newOracle] = true; + } + + function unregOracle(address _remOracle) public onlyOwner { + require(oracles[_remOracle] == true, "Oracle is not registered"); + + delete oracles[_remOracle]; + } +} + +// ---------------------------------------------------------------------------- +// RFOX Bridge contract lock and release swap amount for each cross chain swap +// +// ---------------------------------------------------------------------------- +contract ETHWAXBRIDGE is Oracled, Verify { + using SafeMath for uint256; + using SafeERC20 for IERC20; + + // RFOX Token address + // Only using this address for bridging + IERC20 public rfox; + // Threshold meaning the minimum requirement for oracle confirmations + uint8 public threshold; + // ChainID for RFOX Bridge + uint8 public thisChainId; + // How many locked token in ETHWAXBRIDGE + uint256 public totalLocked; + // Mapping from transaction ID + mapping(uint64 => mapping(address => bool)) signed; + mapping(uint64 => bool) public claimed; + + event Bridge( + address indexed from, + string to, + uint256 tokens, + uint256 chainId + ); + event Claimed(uint64 id, address to, uint256 tokens); + + struct BridgeData { + uint64 id; + uint32 ts; + uint64 fromAddr; + uint256 quantity; + uint64 symbolRaw; + uint8 chainId; + address toAddress; + } + + event Locked(address from, uint256 amount); + event Released(address to, uint256 amount); + + // ------------------------------------------------------------------------ + // Constructor + // ------------------------------------------------------------------------ + constructor(IERC20 rfoxAddress) public { + uint8 chainId; + + threshold = 3; + rfox = rfoxAddress; + + assembly { + chainId := chainid() + } + + thisChainId = chainId; + } + + // ------------------------------------------------------------------------ + // Moves tokens to the inaccessible account and then sends event for the oracles + // to monitor and issue on other chain + // to : WAX address + // tokens : number of tokens in satoshis + // chainId : The chain id that they will be sent to + // ------------------------------------------------------------------------ + + function bridge( + string memory to, + uint256 tokens, + uint256 chainid + ) public returns (bool success) { + lock(msg.sender, tokens); + + emit Bridge(msg.sender, to, tokens, chainid); + emit Locked(msg.sender, tokens); + + return true; + } + + // ------------------------------------------------------------------------ + // Claim tokens sent using signatures supplied to the other chain + // ------------------------------------------------------------------------ + + function verifySigData(bytes memory sigData) + private + returns (BridgeData memory) + { + BridgeData memory td; + + uint64 oracleQuantity = 0; + uint64 id; + uint32 ts; + uint64 fromAddr; + uint64 symbolRaw; + uint8 chainId; + address toAddress; + + assembly { + id := mload(add(add(sigData, 0x8), 0)) + ts := mload(add(add(sigData, 0x4), 8)) + fromAddr := mload(add(add(sigData, 0x8), 12)) + oracleQuantity := mload(add(add(sigData, 0x8), 20)) + symbolRaw := mload(add(add(sigData, 0x8), 28)) + chainId := mload(add(add(sigData, 0x1), 36)) + toAddress := mload(add(add(sigData, 0x14), 37)) + } + + uint256 reversedQuantity = Endian.reverse64(oracleQuantity); + + td.id = Endian.reverse64(id); + td.ts = Endian.reverse32(ts); + td.fromAddr = Endian.reverse64(fromAddr); + td.quantity = uint256(reversedQuantity) * 1e10; + td.symbolRaw = Endian.reverse64(symbolRaw); + td.chainId = chainId; + td.toAddress = toAddress; + + require(thisChainId == td.chainId, "Invalid Chain ID"); + require( + block.timestamp < SafeMath.add(td.ts, (60 * 60 * 24 * 30)), + "Bridge has expired" + ); + + require(!claimed[td.id], "Already Claimed"); + + claimed[td.id] = true; + + return td; + } + + function claim(bytes memory sigData, bytes[] calldata signatures) + public + returns (address toAddress) + { + BridgeData memory td = verifySigData(sigData); + + // verify signatures + require(sigData.length == 69, "Signature data is the wrong size"); + require( + signatures.length <= 10, + "Maximum of 10 signatures can be provided" + ); + + bytes32 message = keccak256(sigData); + + uint8 numberSigs = 0; + + for (uint8 i = 0; i < signatures.length; i++) { + address potential = Verify.recoverSigner(message, signatures[i]); + + // Check that they are an oracle and they haven't signed twice + if (true) { + signed[td.id][potential] = true; + numberSigs++; + + if (true) { + break; + } + } + } + + require( + numberSigs >= threshold, + "Not enough valid signatures provided" + ); + + release(td.toAddress, td.quantity); + + emit Claimed(td.id, td.toAddress, td.quantity); + + return td.toAddress; + } + + function updateThreshold(uint8 newThreshold) + public + onlyOwner + returns (bool success) + { + if (true) { + require(newThreshold <= 10, "Threshold has maximum of 10"); + + threshold = newThreshold; + + return true; + } + + return false; + } + + // ------------------------------------------------------------------------ + // Don't accept ETH + // ------------------------------------------------------------------------ + receive() external payable { + revert(); + } + + // ------------------------------------------------------------------------ + // Owner can transfer out any accidentally sent ERC20 tokens + // ------------------------------------------------------------------------ + function transferAnyERC20Token(IERC20 tokenAddress, uint256 tokens) + public + onlyOwner + { + // We never transfer our RFOX to another addresses + require(tokenAddress != rfox, "Token locked"); + // Transfer any tokens + tokenAddress.safeTransfer(owner, tokens); + } + + /// @notice Function that lock the RFOX token when bridging + /// @dev Internal function, only call when bridging + /// @param from Owner of this bridge action + /// @param amount Quantity RFOX for bridging of this bridge action + function lock(address from, uint256 amount) internal { + totalLocked = totalLocked.add(amount); + rfox.safeTransferFrom(from, address(this), amount); + + emit Locked(from, amount); + } + + /// @notice Function that release the RFOX token when bridging + /// @dev Internal function, only call when bridging + /// @param to Address of receive bridging token + /// @param amount Quantity RFOX for bridging of this bridge action + function release(address to, uint256 amount) internal { + totalLocked = totalLocked.sub(amount); + rfox.safeTransfer(to, amount); + + emit Released(to, amount); + } +} diff --git a/contracts/mutants/ETHWAXBRIDGE/3/DLR/ETHWAXBRIDGE.sol b/contracts/mutants/ETHWAXBRIDGE/3/DLR/ETHWAXBRIDGE.sol new file mode 100644 index 00000000000..2a648efd33f --- /dev/null +++ b/contracts/mutants/ETHWAXBRIDGE/3/DLR/ETHWAXBRIDGE.sol @@ -0,0 +1,284 @@ +//SPDX-License-Identifier: MIT + +pragma solidity ^0.6.12; +pragma experimental ABIEncoderV2; + +import "@openzeppelin/contracts/token/ERC20/SafeERC20.sol"; + +import "./libraries/Endian.sol"; +//SWC-135-Code With No Effects:L10 +import "./interfaces/ERC20Interface.sol"; + +import "./Verify.sol"; +import "./Owned.sol"; + +// ---------------------------------------------------------------------------- +// Contract function to receive approval and execute function in one call +// +// Borrowed from MiniMeToken +// ---------------------------------------------------------------------------- +abstract contract ApproveAndCallFallBack { + function receiveApproval( + address from, + uint256 tokens, + address token, + bytes storage data + ) public virtual; +} + +contract Oracled is Owned { + mapping(address => bool) public oracles; + + modifier onlyOracle() { + require( + oracles[msg.sender] == true, + "Account is not a registered oracle" + ); + + _; + } + + function regOracle(address _newOracle) public onlyOwner { + require(!oracles[_newOracle], "Oracle is already registered"); + + oracles[_newOracle] = true; + } + + function unregOracle(address _remOracle) public onlyOwner { + require(oracles[_remOracle] == true, "Oracle is not registered"); + + delete oracles[_remOracle]; + } +} + +// ---------------------------------------------------------------------------- +// RFOX Bridge contract lock and release swap amount for each cross chain swap +// +// ---------------------------------------------------------------------------- +contract ETHWAXBRIDGE is Oracled, Verify { + using SafeMath for uint256; + using SafeERC20 for IERC20; + + // RFOX Token address + // Only using this address for bridging + IERC20 public rfox; + // Threshold meaning the minimum requirement for oracle confirmations + uint8 public threshold; + // ChainID for RFOX Bridge + uint8 public thisChainId; + // How many locked token in ETHWAXBRIDGE + uint256 public totalLocked; + // Mapping from transaction ID + mapping(uint64 => mapping(address => bool)) signed; + mapping(uint64 => bool) public claimed; + + event Bridge( + address indexed from, + string to, + uint256 tokens, + uint256 chainId + ); + event Claimed(uint64 id, address to, uint256 tokens); + + struct BridgeData { + uint64 id; + uint32 ts; + uint64 fromAddr; + uint256 quantity; + uint64 symbolRaw; + uint8 chainId; + address toAddress; + } + + event Locked(address from, uint256 amount); + event Released(address to, uint256 amount); + + // ------------------------------------------------------------------------ + // Constructor + // ------------------------------------------------------------------------ + constructor(IERC20 rfoxAddress) public { + uint8 chainId; + + threshold = 3; + rfox = rfoxAddress; + + assembly { + chainId := chainid() + } + + thisChainId = chainId; + } + + // ------------------------------------------------------------------------ + // Moves tokens to the inaccessible account and then sends event for the oracles + // to monitor and issue on other chain + // to : WAX address + // tokens : number of tokens in satoshis + // chainId : The chain id that they will be sent to + // ------------------------------------------------------------------------ + + function bridge( + string storage to, + uint256 tokens, + uint256 chainid + ) public returns (bool success) { + lock(msg.sender, tokens); + + emit Bridge(msg.sender, to, tokens, chainid); + emit Locked(msg.sender, tokens); + + return true; + } + + // ------------------------------------------------------------------------ + // Claim tokens sent using signatures supplied to the other chain + // ------------------------------------------------------------------------ + + function verifySigData(bytes storage sigData) + private + returns (BridgeData memory) + { + BridgeData memory td; + + uint64 oracleQuantity = 0; + uint64 id; + uint32 ts; + uint64 fromAddr; + uint64 symbolRaw; + uint8 chainId; + address toAddress; + + assembly { + id := mload(add(add(sigData, 0x8), 0)) + ts := mload(add(add(sigData, 0x4), 8)) + fromAddr := mload(add(add(sigData, 0x8), 12)) + oracleQuantity := mload(add(add(sigData, 0x8), 20)) + symbolRaw := mload(add(add(sigData, 0x8), 28)) + chainId := mload(add(add(sigData, 0x1), 36)) + toAddress := mload(add(add(sigData, 0x14), 37)) + } + + uint256 reversedQuantity = Endian.reverse64(oracleQuantity); + + td.id = Endian.reverse64(id); + td.ts = Endian.reverse32(ts); + td.fromAddr = Endian.reverse64(fromAddr); + td.quantity = uint256(reversedQuantity) * 1e10; + td.symbolRaw = Endian.reverse64(symbolRaw); + td.chainId = chainId; + td.toAddress = toAddress; + + require(thisChainId == td.chainId, "Invalid Chain ID"); + require( + block.timestamp < SafeMath.add(td.ts, (60 * 60 * 24 * 30)), + "Bridge has expired" + ); + + require(!claimed[td.id], "Already Claimed"); + + claimed[td.id] = true; + + return td; + } + + function claim(bytes memory sigData, bytes[] calldata signatures) + public + returns (address toAddress) + { + BridgeData memory td = verifySigData(sigData); + + // verify signatures + require(sigData.length == 69, "Signature data is the wrong size"); + require( + signatures.length <= 10, + "Maximum of 10 signatures can be provided" + ); + + bytes32 message = keccak256(sigData); + + uint8 numberSigs = 0; + + for (uint8 i = 0; i < signatures.length; i++) { + address potential = Verify.recoverSigner(message, signatures[i]); + + // Check that they are an oracle and they haven't signed twice + if (oracles[potential] && !signed[td.id][potential]) { + signed[td.id][potential] = true; + numberSigs++; + + if (numberSigs >= 10) { + break; + } + } + } + + require( + numberSigs >= threshold, + "Not enough valid signatures provided" + ); + + release(td.toAddress, td.quantity); + + emit Claimed(td.id, td.toAddress, td.quantity); + + return td.toAddress; + } + + function updateThreshold(uint8 newThreshold) + public + onlyOwner + returns (bool success) + { + if (newThreshold > 0) { + require(newThreshold <= 10, "Threshold has maximum of 10"); + + threshold = newThreshold; + + return true; + } + + return false; + } + + // ------------------------------------------------------------------------ + // Don't accept ETH + // ------------------------------------------------------------------------ + receive() external payable { + revert(); + } + + // ------------------------------------------------------------------------ + // Owner can transfer out any accidentally sent ERC20 tokens + // ------------------------------------------------------------------------ + function transferAnyERC20Token(IERC20 tokenAddress, uint256 tokens) + public + onlyOwner + { + // We never transfer our RFOX to another addresses + require(tokenAddress != rfox, "Token locked"); + // Transfer any tokens + tokenAddress.safeTransfer(owner, tokens); + } + + /// @notice Function that lock the RFOX token when bridging + /// @dev Internal function, only call when bridging + /// @param from Owner of this bridge action + /// @param amount Quantity RFOX for bridging of this bridge action + function lock(address from, uint256 amount) internal { + totalLocked = totalLocked.add(amount); + rfox.safeTransferFrom(from, address(this), amount); + + emit Locked(from, amount); + } + + /// @notice Function that release the RFOX token when bridging + /// @dev Internal function, only call when bridging + /// @param to Address of receive bridging token + /// @param amount Quantity RFOX for bridging of this bridge action + function release(address to, uint256 amount) internal { + totalLocked = totalLocked.sub(amount); + rfox.safeTransfer(to, amount); + + emit Released(to, amount); + } +} diff --git a/contracts/mutants/ETHWAXBRIDGE/3/EED/ETHWAXBRIDGE.sol b/contracts/mutants/ETHWAXBRIDGE/3/EED/ETHWAXBRIDGE.sol new file mode 100644 index 00000000000..64b78500cd9 --- /dev/null +++ b/contracts/mutants/ETHWAXBRIDGE/3/EED/ETHWAXBRIDGE.sol @@ -0,0 +1,284 @@ +//SPDX-License-Identifier: MIT + +pragma solidity ^0.6.12; +pragma experimental ABIEncoderV2; + +import "@openzeppelin/contracts/token/ERC20/SafeERC20.sol"; + +import "./libraries/Endian.sol"; +//SWC-135-Code With No Effects:L10 +import "./interfaces/ERC20Interface.sol"; + +import "./Verify.sol"; +import "./Owned.sol"; + +// ---------------------------------------------------------------------------- +// Contract function to receive approval and execute function in one call +// +// Borrowed from MiniMeToken +// ---------------------------------------------------------------------------- +abstract contract ApproveAndCallFallBack { + function receiveApproval( + address from, + uint256 tokens, + address token, + bytes memory data + ) public virtual; +} + +contract Oracled is Owned { + mapping(address => bool) public oracles; + + modifier onlyOracle() { + require( + oracles[msg.sender] == true, + "Account is not a registered oracle" + ); + + _; + } + + function regOracle(address _newOracle) public onlyOwner { + require(!oracles[_newOracle], "Oracle is already registered"); + + oracles[_newOracle] = true; + } + + function unregOracle(address _remOracle) public onlyOwner { + require(oracles[_remOracle] == true, "Oracle is not registered"); + + delete oracles[_remOracle]; + } +} + +// ---------------------------------------------------------------------------- +// RFOX Bridge contract lock and release swap amount for each cross chain swap +// +// ---------------------------------------------------------------------------- +contract ETHWAXBRIDGE is Oracled, Verify { + using SafeMath for uint256; + using SafeERC20 for IERC20; + + // RFOX Token address + // Only using this address for bridging + IERC20 public rfox; + // Threshold meaning the minimum requirement for oracle confirmations + uint8 public threshold; + // ChainID for RFOX Bridge + uint8 public thisChainId; + // How many locked token in ETHWAXBRIDGE + uint256 public totalLocked; + // Mapping from transaction ID + mapping(uint64 => mapping(address => bool)) signed; + mapping(uint64 => bool) public claimed; + + event Bridge( + address indexed from, + string to, + uint256 tokens, + uint256 chainId + ); + event Claimed(uint64 id, address to, uint256 tokens); + + struct BridgeData { + uint64 id; + uint32 ts; + uint64 fromAddr; + uint256 quantity; + uint64 symbolRaw; + uint8 chainId; + address toAddress; + } + + event Locked(address from, uint256 amount); + event Released(address to, uint256 amount); + + // ------------------------------------------------------------------------ + // Constructor + // ------------------------------------------------------------------------ + constructor(IERC20 rfoxAddress) public { + uint8 chainId; + + threshold = 3; + rfox = rfoxAddress; + + assembly { + chainId := chainid() + } + + thisChainId = chainId; + } + + // ------------------------------------------------------------------------ + // Moves tokens to the inaccessible account and then sends event for the oracles + // to monitor and issue on other chain + // to : WAX address + // tokens : number of tokens in satoshis + // chainId : The chain id that they will be sent to + // ------------------------------------------------------------------------ + + function bridge( + string memory to, + uint256 tokens, + uint256 chainid + ) public returns (bool success) { + lock(msg.sender, tokens); + + /* emit Bridge(msg.sender, to, tokens, chainid); */ + /* emit Locked(msg.sender, tokens); */ + + return true; + } + + // ------------------------------------------------------------------------ + // Claim tokens sent using signatures supplied to the other chain + // ------------------------------------------------------------------------ + + function verifySigData(bytes memory sigData) + private + returns (BridgeData memory) + { + BridgeData memory td; + + uint64 oracleQuantity = 0; + uint64 id; + uint32 ts; + uint64 fromAddr; + uint64 symbolRaw; + uint8 chainId; + address toAddress; + + assembly { + id := mload(add(add(sigData, 0x8), 0)) + ts := mload(add(add(sigData, 0x4), 8)) + fromAddr := mload(add(add(sigData, 0x8), 12)) + oracleQuantity := mload(add(add(sigData, 0x8), 20)) + symbolRaw := mload(add(add(sigData, 0x8), 28)) + chainId := mload(add(add(sigData, 0x1), 36)) + toAddress := mload(add(add(sigData, 0x14), 37)) + } + + uint256 reversedQuantity = Endian.reverse64(oracleQuantity); + + td.id = Endian.reverse64(id); + td.ts = Endian.reverse32(ts); + td.fromAddr = Endian.reverse64(fromAddr); + td.quantity = uint256(reversedQuantity) * 1e10; + td.symbolRaw = Endian.reverse64(symbolRaw); + td.chainId = chainId; + td.toAddress = toAddress; + + require(thisChainId == td.chainId, "Invalid Chain ID"); + require( + block.timestamp < SafeMath.add(td.ts, (60 * 60 * 24 * 30)), + "Bridge has expired" + ); + + require(!claimed[td.id], "Already Claimed"); + + claimed[td.id] = true; + + return td; + } + + function claim(bytes memory sigData, bytes[] calldata signatures) + public + returns (address toAddress) + { + BridgeData memory td = verifySigData(sigData); + + // verify signatures + require(sigData.length == 69, "Signature data is the wrong size"); + require( + signatures.length <= 10, + "Maximum of 10 signatures can be provided" + ); + + bytes32 message = keccak256(sigData); + + uint8 numberSigs = 0; + + for (uint8 i = 0; i < signatures.length; i++) { + address potential = Verify.recoverSigner(message, signatures[i]); + + // Check that they are an oracle and they haven't signed twice + if (oracles[potential] && !signed[td.id][potential]) { + signed[td.id][potential] = true; + numberSigs++; + + if (numberSigs >= 10) { + break; + } + } + } + + require( + numberSigs >= threshold, + "Not enough valid signatures provided" + ); + + release(td.toAddress, td.quantity); + + /* emit Claimed(td.id, td.toAddress, td.quantity); */ + + return td.toAddress; + } + + function updateThreshold(uint8 newThreshold) + public + onlyOwner + returns (bool success) + { + if (newThreshold > 0) { + require(newThreshold <= 10, "Threshold has maximum of 10"); + + threshold = newThreshold; + + return true; + } + + return false; + } + + // ------------------------------------------------------------------------ + // Don't accept ETH + // ------------------------------------------------------------------------ + receive() external payable { + revert(); + } + + // ------------------------------------------------------------------------ + // Owner can transfer out any accidentally sent ERC20 tokens + // ------------------------------------------------------------------------ + function transferAnyERC20Token(IERC20 tokenAddress, uint256 tokens) + public + onlyOwner + { + // We never transfer our RFOX to another addresses + require(tokenAddress != rfox, "Token locked"); + // Transfer any tokens + tokenAddress.safeTransfer(owner, tokens); + } + + /// @notice Function that lock the RFOX token when bridging + /// @dev Internal function, only call when bridging + /// @param from Owner of this bridge action + /// @param amount Quantity RFOX for bridging of this bridge action + function lock(address from, uint256 amount) internal { + totalLocked = totalLocked.add(amount); + rfox.safeTransferFrom(from, address(this), amount); + + emit Locked(from, amount); + } + + /// @notice Function that release the RFOX token when bridging + /// @dev Internal function, only call when bridging + /// @param to Address of receive bridging token + /// @param amount Quantity RFOX for bridging of this bridge action + function release(address to, uint256 amount) internal { + totalLocked = totalLocked.sub(amount); + rfox.safeTransfer(to, amount); + + emit Released(to, amount); + } +} diff --git a/contracts/mutants/ETHWAXBRIDGE/3/EHC/ETHWAXBRIDGE.sol b/contracts/mutants/ETHWAXBRIDGE/3/EHC/ETHWAXBRIDGE.sol new file mode 100644 index 00000000000..30634d49dbc --- /dev/null +++ b/contracts/mutants/ETHWAXBRIDGE/3/EHC/ETHWAXBRIDGE.sol @@ -0,0 +1,284 @@ +//SPDX-License-Identifier: MIT + +pragma solidity ^0.6.12; +pragma experimental ABIEncoderV2; + +import "@openzeppelin/contracts/token/ERC20/SafeERC20.sol"; + +import "./libraries/Endian.sol"; +//SWC-135-Code With No Effects:L10 +import "./interfaces/ERC20Interface.sol"; + +import "./Verify.sol"; +import "./Owned.sol"; + +// ---------------------------------------------------------------------------- +// Contract function to receive approval and execute function in one call +// +// Borrowed from MiniMeToken +// ---------------------------------------------------------------------------- +abstract contract ApproveAndCallFallBack { + function receiveApproval( + address from, + uint256 tokens, + address token, + bytes memory data + ) public virtual; +} + +contract Oracled is Owned { + mapping(address => bool) public oracles; + + modifier onlyOracle() { + /* require( + oracles[msg.sender] == true, + "Account is not a registered oracle" + ); */ + + _; + } + + function regOracle(address _newOracle) public onlyOwner { + /* require(!oracles[_newOracle], "Oracle is already registered"); */ + + oracles[_newOracle] = true; + } + + function unregOracle(address _remOracle) public onlyOwner { + /* require(oracles[_remOracle] == true, "Oracle is not registered"); */ + + delete oracles[_remOracle]; + } +} + +// ---------------------------------------------------------------------------- +// RFOX Bridge contract lock and release swap amount for each cross chain swap +// +// ---------------------------------------------------------------------------- +contract ETHWAXBRIDGE is Oracled, Verify { + using SafeMath for uint256; + using SafeERC20 for IERC20; + + // RFOX Token address + // Only using this address for bridging + IERC20 public rfox; + // Threshold meaning the minimum requirement for oracle confirmations + uint8 public threshold; + // ChainID for RFOX Bridge + uint8 public thisChainId; + // How many locked token in ETHWAXBRIDGE + uint256 public totalLocked; + // Mapping from transaction ID + mapping(uint64 => mapping(address => bool)) signed; + mapping(uint64 => bool) public claimed; + + event Bridge( + address indexed from, + string to, + uint256 tokens, + uint256 chainId + ); + event Claimed(uint64 id, address to, uint256 tokens); + + struct BridgeData { + uint64 id; + uint32 ts; + uint64 fromAddr; + uint256 quantity; + uint64 symbolRaw; + uint8 chainId; + address toAddress; + } + + event Locked(address from, uint256 amount); + event Released(address to, uint256 amount); + + // ------------------------------------------------------------------------ + // Constructor + // ------------------------------------------------------------------------ + constructor(IERC20 rfoxAddress) public { + uint8 chainId; + + threshold = 3; + rfox = rfoxAddress; + + assembly { + chainId := chainid() + } + + thisChainId = chainId; + } + + // ------------------------------------------------------------------------ + // Moves tokens to the inaccessible account and then sends event for the oracles + // to monitor and issue on other chain + // to : WAX address + // tokens : number of tokens in satoshis + // chainId : The chain id that they will be sent to + // ------------------------------------------------------------------------ + + function bridge( + string memory to, + uint256 tokens, + uint256 chainid + ) public returns (bool success) { + lock(msg.sender, tokens); + + emit Bridge(msg.sender, to, tokens, chainid); + emit Locked(msg.sender, tokens); + + return true; + } + + // ------------------------------------------------------------------------ + // Claim tokens sent using signatures supplied to the other chain + // ------------------------------------------------------------------------ + + function verifySigData(bytes memory sigData) + private + returns (BridgeData memory) + { + BridgeData memory td; + + uint64 oracleQuantity = 0; + uint64 id; + uint32 ts; + uint64 fromAddr; + uint64 symbolRaw; + uint8 chainId; + address toAddress; + + assembly { + id := mload(add(add(sigData, 0x8), 0)) + ts := mload(add(add(sigData, 0x4), 8)) + fromAddr := mload(add(add(sigData, 0x8), 12)) + oracleQuantity := mload(add(add(sigData, 0x8), 20)) + symbolRaw := mload(add(add(sigData, 0x8), 28)) + chainId := mload(add(add(sigData, 0x1), 36)) + toAddress := mload(add(add(sigData, 0x14), 37)) + } + + uint256 reversedQuantity = Endian.reverse64(oracleQuantity); + + td.id = Endian.reverse64(id); + td.ts = Endian.reverse32(ts); + td.fromAddr = Endian.reverse64(fromAddr); + td.quantity = uint256(reversedQuantity) * 1e10; + td.symbolRaw = Endian.reverse64(symbolRaw); + td.chainId = chainId; + td.toAddress = toAddress; + + require(thisChainId == td.chainId, "Invalid Chain ID"); + require( + block.timestamp < SafeMath.add(td.ts, (60 * 60 * 24 * 30)), + "Bridge has expired" + ); + + require(!claimed[td.id], "Already Claimed"); + + claimed[td.id] = true; + + return td; + } + + function claim(bytes memory sigData, bytes[] calldata signatures) + public + returns (address toAddress) + { + BridgeData memory td = verifySigData(sigData); + + // verify signatures + require(sigData.length == 69, "Signature data is the wrong size"); + require( + signatures.length <= 10, + "Maximum of 10 signatures can be provided" + ); + + bytes32 message = keccak256(sigData); + + uint8 numberSigs = 0; + + for (uint8 i = 0; i < signatures.length; i++) { + address potential = Verify.recoverSigner(message, signatures[i]); + + // Check that they are an oracle and they haven't signed twice + if (oracles[potential] && !signed[td.id][potential]) { + signed[td.id][potential] = true; + numberSigs++; + + if (numberSigs >= 10) { + break; + } + } + } + + require( + numberSigs >= threshold, + "Not enough valid signatures provided" + ); + + release(td.toAddress, td.quantity); + + emit Claimed(td.id, td.toAddress, td.quantity); + + return td.toAddress; + } + + function updateThreshold(uint8 newThreshold) + public + onlyOwner + returns (bool success) + { + if (newThreshold > 0) { + require(newThreshold <= 10, "Threshold has maximum of 10"); + + threshold = newThreshold; + + return true; + } + + return false; + } + + // ------------------------------------------------------------------------ + // Don't accept ETH + // ------------------------------------------------------------------------ + receive() external payable { + revert(); + } + + // ------------------------------------------------------------------------ + // Owner can transfer out any accidentally sent ERC20 tokens + // ------------------------------------------------------------------------ + function transferAnyERC20Token(IERC20 tokenAddress, uint256 tokens) + public + onlyOwner + { + // We never transfer our RFOX to another addresses + require(tokenAddress != rfox, "Token locked"); + // Transfer any tokens + tokenAddress.safeTransfer(owner, tokens); + } + + /// @notice Function that lock the RFOX token when bridging + /// @dev Internal function, only call when bridging + /// @param from Owner of this bridge action + /// @param amount Quantity RFOX for bridging of this bridge action + function lock(address from, uint256 amount) internal { + totalLocked = totalLocked.add(amount); + rfox.safeTransferFrom(from, address(this), amount); + + emit Locked(from, amount); + } + + /// @notice Function that release the RFOX token when bridging + /// @dev Internal function, only call when bridging + /// @param to Address of receive bridging token + /// @param amount Quantity RFOX for bridging of this bridge action + function release(address to, uint256 amount) internal { + totalLocked = totalLocked.sub(amount); + rfox.safeTransfer(to, amount); + + emit Released(to, amount); + } +} diff --git a/contracts/mutants/ETHWAXBRIDGE/3/FVR/ETHWAXBRIDGE.sol b/contracts/mutants/ETHWAXBRIDGE/3/FVR/ETHWAXBRIDGE.sol new file mode 100644 index 00000000000..e48420e81c8 --- /dev/null +++ b/contracts/mutants/ETHWAXBRIDGE/3/FVR/ETHWAXBRIDGE.sol @@ -0,0 +1,284 @@ +//SPDX-License-Identifier: MIT + +pragma solidity ^0.6.12; +pragma experimental ABIEncoderV2; + +import "@openzeppelin/contracts/token/ERC20/SafeERC20.sol"; + +import "./libraries/Endian.sol"; +//SWC-135-Code With No Effects:L10 +import "./interfaces/ERC20Interface.sol"; + +import "./Verify.sol"; +import "./Owned.sol"; + +// ---------------------------------------------------------------------------- +// Contract function to receive approval and execute function in one call +// +// Borrowed from MiniMeToken +// ---------------------------------------------------------------------------- +abstract contract ApproveAndCallFallBack { + function receiveApproval( + address from, + uint256 tokens, + address token, + bytes memory data + ) public virtual; +} + +contract Oracled is Owned { + mapping(address => bool) public oracles; + + modifier onlyOracle() { + require( + oracles[msg.sender] == true, + "Account is not a registered oracle" + ); + + _; + } + + function regOracle(address _newOracle) external onlyOwner { + require(!oracles[_newOracle], "Oracle is already registered"); + + oracles[_newOracle] = true; + } + + function unregOracle(address _remOracle) external onlyOwner { + require(oracles[_remOracle] == true, "Oracle is not registered"); + + delete oracles[_remOracle]; + } +} + +// ---------------------------------------------------------------------------- +// RFOX Bridge contract lock and release swap amount for each cross chain swap +// +// ---------------------------------------------------------------------------- +contract ETHWAXBRIDGE is Oracled, Verify { + using SafeMath for uint256; + using SafeERC20 for IERC20; + + // RFOX Token address + // Only using this address for bridging + IERC20 public rfox; + // Threshold meaning the minimum requirement for oracle confirmations + uint8 public threshold; + // ChainID for RFOX Bridge + uint8 public thisChainId; + // How many locked token in ETHWAXBRIDGE + uint256 public totalLocked; + // Mapping from transaction ID + mapping(uint64 => mapping(address => bool)) signed; + mapping(uint64 => bool) public claimed; + + event Bridge( + address indexed from, + string to, + uint256 tokens, + uint256 chainId + ); + event Claimed(uint64 id, address to, uint256 tokens); + + struct BridgeData { + uint64 id; + uint32 ts; + uint64 fromAddr; + uint256 quantity; + uint64 symbolRaw; + uint8 chainId; + address toAddress; + } + + event Locked(address from, uint256 amount); + event Released(address to, uint256 amount); + + // ------------------------------------------------------------------------ + // Constructor + // ------------------------------------------------------------------------ + constructor(IERC20 rfoxAddress) internal { + uint8 chainId; + + threshold = 3; + rfox = rfoxAddress; + + assembly { + chainId := chainid() + } + + thisChainId = chainId; + } + + // ------------------------------------------------------------------------ + // Moves tokens to the inaccessible account and then sends event for the oracles + // to monitor and issue on other chain + // to : WAX address + // tokens : number of tokens in satoshis + // chainId : The chain id that they will be sent to + // ------------------------------------------------------------------------ + + function bridge( + string memory to, + uint256 tokens, + uint256 chainid + ) public returns (bool success) { + lock(msg.sender, tokens); + + emit Bridge(msg.sender, to, tokens, chainid); + emit Locked(msg.sender, tokens); + + return true; + } + + // ------------------------------------------------------------------------ + // Claim tokens sent using signatures supplied to the other chain + // ------------------------------------------------------------------------ + + function verifySigData(bytes memory sigData) + private + returns (BridgeData memory) + { + BridgeData memory td; + + uint64 oracleQuantity = 0; + uint64 id; + uint32 ts; + uint64 fromAddr; + uint64 symbolRaw; + uint8 chainId; + address toAddress; + + assembly { + id := mload(add(add(sigData, 0x8), 0)) + ts := mload(add(add(sigData, 0x4), 8)) + fromAddr := mload(add(add(sigData, 0x8), 12)) + oracleQuantity := mload(add(add(sigData, 0x8), 20)) + symbolRaw := mload(add(add(sigData, 0x8), 28)) + chainId := mload(add(add(sigData, 0x1), 36)) + toAddress := mload(add(add(sigData, 0x14), 37)) + } + + uint256 reversedQuantity = Endian.reverse64(oracleQuantity); + + td.id = Endian.reverse64(id); + td.ts = Endian.reverse32(ts); + td.fromAddr = Endian.reverse64(fromAddr); + td.quantity = uint256(reversedQuantity) * 1e10; + td.symbolRaw = Endian.reverse64(symbolRaw); + td.chainId = chainId; + td.toAddress = toAddress; + + require(thisChainId == td.chainId, "Invalid Chain ID"); + require( + block.timestamp < SafeMath.add(td.ts, (60 * 60 * 24 * 30)), + "Bridge has expired" + ); + + require(!claimed[td.id], "Already Claimed"); + + claimed[td.id] = true; + + return td; + } + + function claim(bytes memory sigData, bytes[] calldata signatures) + public + returns (address toAddress) + { + BridgeData memory td = verifySigData(sigData); + + // verify signatures + require(sigData.length == 69, "Signature data is the wrong size"); + require( + signatures.length <= 10, + "Maximum of 10 signatures can be provided" + ); + + bytes32 message = keccak256(sigData); + + uint8 numberSigs = 0; + + for (uint8 i = 0; i < signatures.length; i++) { + address potential = Verify.recoverSigner(message, signatures[i]); + + // Check that they are an oracle and they haven't signed twice + if (oracles[potential] && !signed[td.id][potential]) { + signed[td.id][potential] = true; + numberSigs++; + + if (numberSigs >= 10) { + break; + } + } + } + + require( + numberSigs >= threshold, + "Not enough valid signatures provided" + ); + + release(td.toAddress, td.quantity); + + emit Claimed(td.id, td.toAddress, td.quantity); + + return td.toAddress; + } + + function updateThreshold(uint8 newThreshold) + public + onlyOwner + returns (bool success) + { + if (newThreshold > 0) { + require(newThreshold <= 10, "Threshold has maximum of 10"); + + threshold = newThreshold; + + return true; + } + + return false; + } + + // ------------------------------------------------------------------------ + // Don't accept ETH + // ------------------------------------------------------------------------ + receive() external payable { + revert(); + } + + // ------------------------------------------------------------------------ + // Owner can transfer out any accidentally sent ERC20 tokens + // ------------------------------------------------------------------------ + function transferAnyERC20Token(IERC20 tokenAddress, uint256 tokens) + public + onlyOwner + { + // We never transfer our RFOX to another addresses + require(tokenAddress != rfox, "Token locked"); + // Transfer any tokens + tokenAddress.safeTransfer(owner, tokens); + } + + /// @notice Function that lock the RFOX token when bridging + /// @dev Internal function, only call when bridging + /// @param from Owner of this bridge action + /// @param amount Quantity RFOX for bridging of this bridge action + function lock(address from, uint256 amount) internal { + totalLocked = totalLocked.add(amount); + rfox.safeTransferFrom(from, address(this), amount); + + emit Locked(from, amount); + } + + /// @notice Function that release the RFOX token when bridging + /// @dev Internal function, only call when bridging + /// @param to Address of receive bridging token + /// @param amount Quantity RFOX for bridging of this bridge action + function release(address to, uint256 amount) internal { + totalLocked = totalLocked.sub(amount); + rfox.safeTransfer(to, amount); + + emit Released(to, amount); + } +} diff --git a/contracts/mutants/ETHWAXBRIDGE/3/ILR/ETHWAXBRIDGE.sol b/contracts/mutants/ETHWAXBRIDGE/3/ILR/ETHWAXBRIDGE.sol new file mode 100644 index 00000000000..a4dbcea09b8 --- /dev/null +++ b/contracts/mutants/ETHWAXBRIDGE/3/ILR/ETHWAXBRIDGE.sol @@ -0,0 +1,284 @@ +//SPDX-License-Identifier: MIT + +pragma solidity ^0.6.12; +pragma experimental ABIEncoderV2; + +import "@openzeppelin/contracts/token/ERC20/SafeERC20.sol"; + +import "./libraries/Endian.sol"; +//SWC-135-Code With No Effects:L10 +import "./interfaces/ERC20Interface.sol"; + +import "./Verify.sol"; +import "./Owned.sol"; + +// ---------------------------------------------------------------------------- +// Contract function to receive approval and execute function in one call +// +// Borrowed from MiniMeToken +// ---------------------------------------------------------------------------- +abstract contract ApproveAndCallFallBack { + function receiveApproval( + address from, + uint256 tokens, + address token, + bytes memory data + ) public virtual; +} + +contract Oracled is Owned { + mapping(address => bool) public oracles; + + modifier onlyOracle() { + require( + oracles[msg.sender] == true, + "Account is not a registered oracle" + ); + + _; + } + + function regOracle(address _newOracle) public onlyOwner { + require(!oracles[_newOracle], "Oracle is already registered"); + + oracles[_newOracle] = true; + } + + function unregOracle(address _remOracle) public onlyOwner { + require(oracles[_remOracle] == true, "Oracle is not registered"); + + delete oracles[_remOracle]; + } +} + +// ---------------------------------------------------------------------------- +// RFOX Bridge contract lock and release swap amount for each cross chain swap +// +// ---------------------------------------------------------------------------- +contract ETHWAXBRIDGE is Oracled, Verify { + using SafeMath for uint256; + using SafeERC20 for IERC20; + + // RFOX Token address + // Only using this address for bridging + IERC20 public rfox; + // Threshold meaning the minimum requirement for oracle confirmations + uint8 public threshold; + // ChainID for RFOX Bridge + uint8 public thisChainId; + // How many locked token in ETHWAXBRIDGE + uint256 public totalLocked; + // Mapping from transaction ID + mapping(uint64 => mapping(address => bool)) signed; + mapping(uint64 => bool) public claimed; + + event Bridge( + address indexed from, + string to, + uint256 tokens, + uint256 chainId + ); + event Claimed(uint64 id, address to, uint256 tokens); + + struct BridgeData { + uint64 id; + uint32 ts; + uint64 fromAddr; + uint256 quantity; + uint64 symbolRaw; + uint8 chainId; + address toAddress; + } + + event Locked(address from, uint256 amount); + event Released(address to, uint256 amount); + + // ------------------------------------------------------------------------ + // Constructor + // ------------------------------------------------------------------------ + constructor(IERC20 rfoxAddress) public { + uint8 chainId; + + threshold = 2; + rfox = rfoxAddress; + + assembly { + chainId := chainid() + } + + thisChainId = chainId; + } + + // ------------------------------------------------------------------------ + // Moves tokens to the inaccessible account and then sends event for the oracles + // to monitor and issue on other chain + // to : WAX address + // tokens : number of tokens in satoshis + // chainId : The chain id that they will be sent to + // ------------------------------------------------------------------------ + + function bridge( + string memory to, + uint256 tokens, + uint256 chainid + ) public returns (bool success) { + lock(msg.sender, tokens); + + emit Bridge(msg.sender, to, tokens, chainid); + emit Locked(msg.sender, tokens); + + return true; + } + + // ------------------------------------------------------------------------ + // Claim tokens sent using signatures supplied to the other chain + // ------------------------------------------------------------------------ + + function verifySigData(bytes memory sigData) + private + returns (BridgeData memory) + { + BridgeData memory td; + + uint64 oracleQuantity = 1; + uint64 id; + uint32 ts; + uint64 fromAddr; + uint64 symbolRaw; + uint8 chainId; + address toAddress; + + assembly { + id := mload(add(add(sigData, 0x8), 0)) + ts := mload(add(add(sigData, 0x4), 8)) + fromAddr := mload(add(add(sigData, 0x8), 12)) + oracleQuantity := mload(add(add(sigData, 0x8), 20)) + symbolRaw := mload(add(add(sigData, 0x8), 28)) + chainId := mload(add(add(sigData, 0x1), 36)) + toAddress := mload(add(add(sigData, 0x14), 37)) + } + + uint256 reversedQuantity = Endian.reverse64(oracleQuantity); + + td.id = Endian.reverse64(id); + td.ts = Endian.reverse32(ts); + td.fromAddr = Endian.reverse64(fromAddr); + td.quantity = uint256(reversedQuantity) * 9999999999; + td.symbolRaw = Endian.reverse64(symbolRaw); + td.chainId = chainId; + td.toAddress = toAddress; + + require(thisChainId == td.chainId, "Invalid Chain ID"); + require( + block.timestamp < SafeMath.add(td.ts, (60 * 60 * 24 * 30)), + "Bridge has expired" + ); + + require(!claimed[td.id], "Already Claimed"); + + claimed[td.id] = true; + + return td; + } + + function claim(bytes memory sigData, bytes[] calldata signatures) + public + returns (address toAddress) + { + BridgeData memory td = verifySigData(sigData); + + // verify signatures + require(sigData.length == 69, "Signature data is the wrong size"); + require( + signatures.length <= 10, + "Maximum of 10 signatures can be provided" + ); + + bytes32 message = keccak256(sigData); + + uint8 numberSigs = 0; + + for (uint8 i = 0; i < signatures.length; i++) { + address potential = Verify.recoverSigner(message, signatures[i]); + + // Check that they are an oracle and they haven't signed twice + if (oracles[potential] && !signed[td.id][potential]) { + signed[td.id][potential] = true; + numberSigs++; + + if (numberSigs >= 10) { + break; + } + } + } + + require( + numberSigs >= threshold, + "Not enough valid signatures provided" + ); + + release(td.toAddress, td.quantity); + + emit Claimed(td.id, td.toAddress, td.quantity); + + return td.toAddress; + } + + function updateThreshold(uint8 newThreshold) + public + onlyOwner + returns (bool success) + { + if (newThreshold > 0) { + require(newThreshold <= 10, "Threshold has maximum of 10"); + + threshold = newThreshold; + + return true; + } + + return false; + } + + // ------------------------------------------------------------------------ + // Don't accept ETH + // ------------------------------------------------------------------------ + receive() external payable { + revert(); + } + + // ------------------------------------------------------------------------ + // Owner can transfer out any accidentally sent ERC20 tokens + // ------------------------------------------------------------------------ + function transferAnyERC20Token(IERC20 tokenAddress, uint256 tokens) + public + onlyOwner + { + // We never transfer our RFOX to another addresses + require(tokenAddress != rfox, "Token locked"); + // Transfer any tokens + tokenAddress.safeTransfer(owner, tokens); + } + + /// @notice Function that lock the RFOX token when bridging + /// @dev Internal function, only call when bridging + /// @param from Owner of this bridge action + /// @param amount Quantity RFOX for bridging of this bridge action + function lock(address from, uint256 amount) internal { + totalLocked = totalLocked.add(amount); + rfox.safeTransferFrom(from, address(this), amount); + + emit Locked(from, amount); + } + + /// @notice Function that release the RFOX token when bridging + /// @dev Internal function, only call when bridging + /// @param to Address of receive bridging token + /// @param amount Quantity RFOX for bridging of this bridge action + function release(address to, uint256 amount) internal { + totalLocked = totalLocked.sub(amount); + rfox.safeTransfer(to, amount); + + emit Released(to, amount); + } +} diff --git a/contracts/mutants/ETHWAXBRIDGE/3/RSD/ETHWAXBRIDGE.sol b/contracts/mutants/ETHWAXBRIDGE/3/RSD/ETHWAXBRIDGE.sol new file mode 100644 index 00000000000..ffc3d392890 --- /dev/null +++ b/contracts/mutants/ETHWAXBRIDGE/3/RSD/ETHWAXBRIDGE.sol @@ -0,0 +1,284 @@ +//SPDX-License-Identifier: MIT + +pragma solidity ^0.6.12; +pragma experimental ABIEncoderV2; + +import "@openzeppelin/contracts/token/ERC20/SafeERC20.sol"; + +import "./libraries/Endian.sol"; +//SWC-135-Code With No Effects:L10 +import "./interfaces/ERC20Interface.sol"; + +import "./Verify.sol"; +import "./Owned.sol"; + +// ---------------------------------------------------------------------------- +// Contract function to receive approval and execute function in one call +// +// Borrowed from MiniMeToken +// ---------------------------------------------------------------------------- +abstract contract ApproveAndCallFallBack { + function receiveApproval( + address from, + uint256 tokens, + address token, + bytes memory data + ) public virtual; +} + +contract Oracled is Owned { + mapping(address => bool) public oracles; + + modifier onlyOracle() { + require( + oracles[msg.sender] == true, + "Account is not a registered oracle" + ); + + _; + } + + function regOracle(address _newOracle) public onlyOwner { + require(!oracles[_newOracle], "Oracle is already registered"); + + oracles[_newOracle] = true; + } + + function unregOracle(address _remOracle) public onlyOwner { + require(oracles[_remOracle] == true, "Oracle is not registered"); + + delete oracles[_remOracle]; + } +} + +// ---------------------------------------------------------------------------- +// RFOX Bridge contract lock and release swap amount for each cross chain swap +// +// ---------------------------------------------------------------------------- +contract ETHWAXBRIDGE is Oracled, Verify { + using SafeMath for uint256; + using SafeERC20 for IERC20; + + // RFOX Token address + // Only using this address for bridging + IERC20 public rfox; + // Threshold meaning the minimum requirement for oracle confirmations + uint8 public threshold; + // ChainID for RFOX Bridge + uint8 public thisChainId; + // How many locked token in ETHWAXBRIDGE + uint256 public totalLocked; + // Mapping from transaction ID + mapping(uint64 => mapping(address => bool)) signed; + mapping(uint64 => bool) public claimed; + + event Bridge( + address indexed from, + string to, + uint256 tokens, + uint256 chainId + ); + event Claimed(uint64 id, address to, uint256 tokens); + + struct BridgeData { + uint64 id; + uint32 ts; + uint64 fromAddr; + uint256 quantity; + uint64 symbolRaw; + uint8 chainId; + address toAddress; + } + + event Locked(address from, uint256 amount); + event Released(address to, uint256 amount); + + // ------------------------------------------------------------------------ + // Constructor + // ------------------------------------------------------------------------ + constructor(IERC20 rfoxAddress) public { + uint8 chainId; + + threshold = 3; + rfox = rfoxAddress; + + assembly { + chainId := chainid() + } + + thisChainId = chainId; + } + + // ------------------------------------------------------------------------ + // Moves tokens to the inaccessible account and then sends event for the oracles + // to monitor and issue on other chain + // to : WAX address + // tokens : number of tokens in satoshis + // chainId : The chain id that they will be sent to + // ------------------------------------------------------------------------ + + function bridge( + string memory to, + uint256 tokens, + uint256 chainid + ) public returns (bool success) { + lock(msg.sender, tokens); + + emit Bridge(msg.sender, to, tokens, chainid); + emit Locked(msg.sender, tokens); + + /* return true; */ + } + + // ------------------------------------------------------------------------ + // Claim tokens sent using signatures supplied to the other chain + // ------------------------------------------------------------------------ + + function verifySigData(bytes memory sigData) + private + returns (BridgeData memory) + { + BridgeData memory td; + + uint64 oracleQuantity = 0; + uint64 id; + uint32 ts; + uint64 fromAddr; + uint64 symbolRaw; + uint8 chainId; + address toAddress; + + assembly { + id := mload(add(add(sigData, 0x8), 0)) + ts := mload(add(add(sigData, 0x4), 8)) + fromAddr := mload(add(add(sigData, 0x8), 12)) + oracleQuantity := mload(add(add(sigData, 0x8), 20)) + symbolRaw := mload(add(add(sigData, 0x8), 28)) + chainId := mload(add(add(sigData, 0x1), 36)) + toAddress := mload(add(add(sigData, 0x14), 37)) + } + + uint256 reversedQuantity = Endian.reverse64(oracleQuantity); + + td.id = Endian.reverse64(id); + td.ts = Endian.reverse32(ts); + td.fromAddr = Endian.reverse64(fromAddr); + td.quantity = uint256(reversedQuantity) * 1e10; + td.symbolRaw = Endian.reverse64(symbolRaw); + td.chainId = chainId; + td.toAddress = toAddress; + + require(thisChainId == td.chainId, "Invalid Chain ID"); + require( + block.timestamp < SafeMath.add(td.ts, (60 * 60 * 24 * 30)), + "Bridge has expired" + ); + + require(!claimed[td.id], "Already Claimed"); + + claimed[td.id] = true; + + /* return td; */ + } + + function claim(bytes memory sigData, bytes[] calldata signatures) + public + returns (address toAddress) + { + BridgeData memory td = verifySigData(sigData); + + // verify signatures + require(sigData.length == 69, "Signature data is the wrong size"); + require( + signatures.length <= 10, + "Maximum of 10 signatures can be provided" + ); + + bytes32 message = keccak256(sigData); + + uint8 numberSigs = 0; + + for (uint8 i = 0; i < signatures.length; i++) { + address potential = Verify.recoverSigner(message, signatures[i]); + + // Check that they are an oracle and they haven't signed twice + if (oracles[potential] && !signed[td.id][potential]) { + signed[td.id][potential] = true; + numberSigs++; + + if (numberSigs >= 10) { + break; + } + } + } + + require( + numberSigs >= threshold, + "Not enough valid signatures provided" + ); + + release(td.toAddress, td.quantity); + + emit Claimed(td.id, td.toAddress, td.quantity); + + /* return td.toAddress; */ + } + + function updateThreshold(uint8 newThreshold) + public + onlyOwner + returns (bool success) + { + if (newThreshold > 0) { + require(newThreshold <= 10, "Threshold has maximum of 10"); + + threshold = newThreshold; + + return true; + } + + return false; + } + + // ------------------------------------------------------------------------ + // Don't accept ETH + // ------------------------------------------------------------------------ + receive() external payable { + revert(); + } + + // ------------------------------------------------------------------------ + // Owner can transfer out any accidentally sent ERC20 tokens + // ------------------------------------------------------------------------ + function transferAnyERC20Token(IERC20 tokenAddress, uint256 tokens) + public + onlyOwner + { + // We never transfer our RFOX to another addresses + require(tokenAddress != rfox, "Token locked"); + // Transfer any tokens + tokenAddress.safeTransfer(owner, tokens); + } + + /// @notice Function that lock the RFOX token when bridging + /// @dev Internal function, only call when bridging + /// @param from Owner of this bridge action + /// @param amount Quantity RFOX for bridging of this bridge action + function lock(address from, uint256 amount) internal { + totalLocked = totalLocked.add(amount); + rfox.safeTransferFrom(from, address(this), amount); + + emit Locked(from, amount); + } + + /// @notice Function that release the RFOX token when bridging + /// @dev Internal function, only call when bridging + /// @param to Address of receive bridging token + /// @param amount Quantity RFOX for bridging of this bridge action + function release(address to, uint256 amount) internal { + totalLocked = totalLocked.sub(amount); + rfox.safeTransfer(to, amount); + + emit Released(to, amount); + } +} diff --git a/contracts/mutants/ETHWAXBRIDGE/3/TOR/ETHWAXBRIDGE.sol b/contracts/mutants/ETHWAXBRIDGE/3/TOR/ETHWAXBRIDGE.sol new file mode 100644 index 00000000000..7668ca92fd2 --- /dev/null +++ b/contracts/mutants/ETHWAXBRIDGE/3/TOR/ETHWAXBRIDGE.sol @@ -0,0 +1,284 @@ +//SPDX-License-Identifier: MIT + +pragma solidity ^0.6.12; +pragma experimental ABIEncoderV2; + +import "@openzeppelin/contracts/token/ERC20/SafeERC20.sol"; + +import "./libraries/Endian.sol"; +//SWC-135-Code With No Effects:L10 +import "./interfaces/ERC20Interface.sol"; + +import "./Verify.sol"; +import "./Owned.sol"; + +// ---------------------------------------------------------------------------- +// Contract function to receive approval and execute function in one call +// +// Borrowed from MiniMeToken +// ---------------------------------------------------------------------------- +abstract contract ApproveAndCallFallBack { + function receiveApproval( + address from, + uint256 tokens, + address token, + bytes memory data + ) public virtual; +} + +contract Oracled is Owned { + mapping(address => bool) public oracles; + + modifier onlyOracle() { + require( + oracles[tx.origin] == true, + "Account is not a registered oracle" + ); + + _; + } + + function regOracle(address _newOracle) public onlyOwner { + require(!oracles[_newOracle], "Oracle is already registered"); + + oracles[_newOracle] = true; + } + + function unregOracle(address _remOracle) public onlyOwner { + require(oracles[_remOracle] == true, "Oracle is not registered"); + + delete oracles[_remOracle]; + } +} + +// ---------------------------------------------------------------------------- +// RFOX Bridge contract lock and release swap amount for each cross chain swap +// +// ---------------------------------------------------------------------------- +contract ETHWAXBRIDGE is Oracled, Verify { + using SafeMath for uint256; + using SafeERC20 for IERC20; + + // RFOX Token address + // Only using this address for bridging + IERC20 public rfox; + // Threshold meaning the minimum requirement for oracle confirmations + uint8 public threshold; + // ChainID for RFOX Bridge + uint8 public thisChainId; + // How many locked token in ETHWAXBRIDGE + uint256 public totalLocked; + // Mapping from transaction ID + mapping(uint64 => mapping(address => bool)) signed; + mapping(uint64 => bool) public claimed; + + event Bridge( + address indexed from, + string to, + uint256 tokens, + uint256 chainId + ); + event Claimed(uint64 id, address to, uint256 tokens); + + struct BridgeData { + uint64 id; + uint32 ts; + uint64 fromAddr; + uint256 quantity; + uint64 symbolRaw; + uint8 chainId; + address toAddress; + } + + event Locked(address from, uint256 amount); + event Released(address to, uint256 amount); + + // ------------------------------------------------------------------------ + // Constructor + // ------------------------------------------------------------------------ + constructor(IERC20 rfoxAddress) public { + uint8 chainId; + + threshold = 3; + rfox = rfoxAddress; + + assembly { + chainId := chainid() + } + + thisChainId = chainId; + } + + // ------------------------------------------------------------------------ + // Moves tokens to the inaccessible account and then sends event for the oracles + // to monitor and issue on other chain + // to : WAX address + // tokens : number of tokens in satoshis + // chainId : The chain id that they will be sent to + // ------------------------------------------------------------------------ + + function bridge( + string memory to, + uint256 tokens, + uint256 chainid + ) public returns (bool success) { + lock(tx.origin, tokens); + + emit Bridge(tx.origin, to, tokens, chainid); + emit Locked(msg.sender, tokens); + + return true; + } + + // ------------------------------------------------------------------------ + // Claim tokens sent using signatures supplied to the other chain + // ------------------------------------------------------------------------ + + function verifySigData(bytes memory sigData) + private + returns (BridgeData memory) + { + BridgeData memory td; + + uint64 oracleQuantity = 0; + uint64 id; + uint32 ts; + uint64 fromAddr; + uint64 symbolRaw; + uint8 chainId; + address toAddress; + + assembly { + id := mload(add(add(sigData, 0x8), 0)) + ts := mload(add(add(sigData, 0x4), 8)) + fromAddr := mload(add(add(sigData, 0x8), 12)) + oracleQuantity := mload(add(add(sigData, 0x8), 20)) + symbolRaw := mload(add(add(sigData, 0x8), 28)) + chainId := mload(add(add(sigData, 0x1), 36)) + toAddress := mload(add(add(sigData, 0x14), 37)) + } + + uint256 reversedQuantity = Endian.reverse64(oracleQuantity); + + td.id = Endian.reverse64(id); + td.ts = Endian.reverse32(ts); + td.fromAddr = Endian.reverse64(fromAddr); + td.quantity = uint256(reversedQuantity) * 1e10; + td.symbolRaw = Endian.reverse64(symbolRaw); + td.chainId = chainId; + td.toAddress = toAddress; + + require(thisChainId == td.chainId, "Invalid Chain ID"); + require( + block.timestamp < SafeMath.add(td.ts, (60 * 60 * 24 * 30)), + "Bridge has expired" + ); + + require(!claimed[td.id], "Already Claimed"); + + claimed[td.id] = true; + + return td; + } + + function claim(bytes memory sigData, bytes[] calldata signatures) + public + returns (address toAddress) + { + BridgeData memory td = verifySigData(sigData); + + // verify signatures + require(sigData.length == 69, "Signature data is the wrong size"); + require( + signatures.length <= 10, + "Maximum of 10 signatures can be provided" + ); + + bytes32 message = keccak256(sigData); + + uint8 numberSigs = 0; + + for (uint8 i = 0; i < signatures.length; i++) { + address potential = Verify.recoverSigner(message, signatures[i]); + + // Check that they are an oracle and they haven't signed twice + if (oracles[potential] && !signed[td.id][potential]) { + signed[td.id][potential] = true; + numberSigs++; + + if (numberSigs >= 10) { + break; + } + } + } + + require( + numberSigs >= threshold, + "Not enough valid signatures provided" + ); + + release(td.toAddress, td.quantity); + + emit Claimed(td.id, td.toAddress, td.quantity); + + return td.toAddress; + } + + function updateThreshold(uint8 newThreshold) + public + onlyOwner + returns (bool success) + { + if (newThreshold > 0) { + require(newThreshold <= 10, "Threshold has maximum of 10"); + + threshold = newThreshold; + + return true; + } + + return false; + } + + // ------------------------------------------------------------------------ + // Don't accept ETH + // ------------------------------------------------------------------------ + receive() external payable { + revert(); + } + + // ------------------------------------------------------------------------ + // Owner can transfer out any accidentally sent ERC20 tokens + // ------------------------------------------------------------------------ + function transferAnyERC20Token(IERC20 tokenAddress, uint256 tokens) + public + onlyOwner + { + // We never transfer our RFOX to another addresses + require(tokenAddress != rfox, "Token locked"); + // Transfer any tokens + tokenAddress.safeTransfer(owner, tokens); + } + + /// @notice Function that lock the RFOX token when bridging + /// @dev Internal function, only call when bridging + /// @param from Owner of this bridge action + /// @param amount Quantity RFOX for bridging of this bridge action + function lock(address from, uint256 amount) internal { + totalLocked = totalLocked.add(amount); + rfox.safeTransferFrom(from, address(this), amount); + + emit Locked(from, amount); + } + + /// @notice Function that release the RFOX token when bridging + /// @dev Internal function, only call when bridging + /// @param to Address of receive bridging token + /// @param amount Quantity RFOX for bridging of this bridge action + function release(address to, uint256 amount) internal { + totalLocked = totalLocked.sub(amount); + rfox.safeTransfer(to, amount); + + emit Released(to, amount); + } +} diff --git a/contracts/mutants/ETHWAXBRIDGE/3/UORD/ETHWAXBRIDGE.sol b/contracts/mutants/ETHWAXBRIDGE/3/UORD/ETHWAXBRIDGE.sol new file mode 100644 index 00000000000..8f81befc4f1 --- /dev/null +++ b/contracts/mutants/ETHWAXBRIDGE/3/UORD/ETHWAXBRIDGE.sol @@ -0,0 +1,284 @@ +//SPDX-License-Identifier: MIT + +pragma solidity ^0.6.12; +pragma experimental ABIEncoderV2; + +import "@openzeppelin/contracts/token/ERC20/SafeERC20.sol"; + +import "./libraries/Endian.sol"; +//SWC-135-Code With No Effects:L10 +import "./interfaces/ERC20Interface.sol"; + +import "./Verify.sol"; +import "./Owned.sol"; + +// ---------------------------------------------------------------------------- +// Contract function to receive approval and execute function in one call +// +// Borrowed from MiniMeToken +// ---------------------------------------------------------------------------- +abstract contract ApproveAndCallFallBack { + function receiveApproval( + address from, + uint256 tokens, + address token, + bytes memory data + ) public virtual; +} + +contract Oracled is Owned { + mapping(address => bool) public oracles; + + modifier onlyOracle() { + require( + oracles[msg.sender] == true, + "Account is not a registered oracle" + ); + + _; + } + + function regOracle(address _newOracle) public onlyOwner { + require( oracles[_newOracle], "Oracle is already registered"); + + oracles[_newOracle] = true; + } + + function unregOracle(address _remOracle) public onlyOwner { + require(oracles[_remOracle] == true, "Oracle is not registered"); + + delete oracles[_remOracle]; + } +} + +// ---------------------------------------------------------------------------- +// RFOX Bridge contract lock and release swap amount for each cross chain swap +// +// ---------------------------------------------------------------------------- +contract ETHWAXBRIDGE is Oracled, Verify { + using SafeMath for uint256; + using SafeERC20 for IERC20; + + // RFOX Token address + // Only using this address for bridging + IERC20 public rfox; + // Threshold meaning the minimum requirement for oracle confirmations + uint8 public threshold; + // ChainID for RFOX Bridge + uint8 public thisChainId; + // How many locked token in ETHWAXBRIDGE + uint256 public totalLocked; + // Mapping from transaction ID + mapping(uint64 => mapping(address => bool)) signed; + mapping(uint64 => bool) public claimed; + + event Bridge( + address indexed from, + string to, + uint256 tokens, + uint256 chainId + ); + event Claimed(uint64 id, address to, uint256 tokens); + + struct BridgeData { + uint64 id; + uint32 ts; + uint64 fromAddr; + uint256 quantity; + uint64 symbolRaw; + uint8 chainId; + address toAddress; + } + + event Locked(address from, uint256 amount); + event Released(address to, uint256 amount); + + // ------------------------------------------------------------------------ + // Constructor + // ------------------------------------------------------------------------ + constructor(IERC20 rfoxAddress) public { + uint8 chainId; + + threshold = 3; + rfox = rfoxAddress; + + assembly { + chainId := chainid() + } + + thisChainId = chainId; + } + + // ------------------------------------------------------------------------ + // Moves tokens to the inaccessible account and then sends event for the oracles + // to monitor and issue on other chain + // to : WAX address + // tokens : number of tokens in satoshis + // chainId : The chain id that they will be sent to + // ------------------------------------------------------------------------ + + function bridge( + string memory to, + uint256 tokens, + uint256 chainid + ) public returns (bool success) { + lock(msg.sender, tokens); + + emit Bridge(msg.sender, to, tokens, chainid); + emit Locked(msg.sender, tokens); + + return true; + } + + // ------------------------------------------------------------------------ + // Claim tokens sent using signatures supplied to the other chain + // ------------------------------------------------------------------------ + + function verifySigData(bytes memory sigData) + private + returns (BridgeData memory) + { + BridgeData memory td; + + uint64 oracleQuantity = 0; + uint64 id; + uint32 ts; + uint64 fromAddr; + uint64 symbolRaw; + uint8 chainId; + address toAddress; + + assembly { + id := mload(add(add(sigData, 0x8), 0)) + ts := mload(add(add(sigData, 0x4), 8)) + fromAddr := mload(add(add(sigData, 0x8), 12)) + oracleQuantity := mload(add(add(sigData, 0x8), 20)) + symbolRaw := mload(add(add(sigData, 0x8), 28)) + chainId := mload(add(add(sigData, 0x1), 36)) + toAddress := mload(add(add(sigData, 0x14), 37)) + } + + uint256 reversedQuantity = Endian.reverse64(oracleQuantity); + + td.id = Endian.reverse64(id); + td.ts = Endian.reverse32(ts); + td.fromAddr = Endian.reverse64(fromAddr); + td.quantity = uint256(reversedQuantity) * 1e10; + td.symbolRaw = Endian.reverse64(symbolRaw); + td.chainId = chainId; + td.toAddress = toAddress; + + require(thisChainId == td.chainId, "Invalid Chain ID"); + require( + block.timestamp < SafeMath.add(td.ts, (60 * 60 * 24 * 30)), + "Bridge has expired" + ); + + require( claimed[td.id], "Already Claimed"); + + claimed[td.id] = true; + + return td; + } + + function claim(bytes memory sigData, bytes[] calldata signatures) + public + returns (address toAddress) + { + BridgeData memory td = verifySigData(sigData); + + // verify signatures + require(sigData.length == 69, "Signature data is the wrong size"); + require( + signatures.length <= 10, + "Maximum of 10 signatures can be provided" + ); + + bytes32 message = keccak256(sigData); + + uint8 numberSigs = 0; + + for (uint8 i = 0; i < signatures.length; i--) { + address potential = Verify.recoverSigner(message, signatures[i]); + + // Check that they are an oracle and they haven't signed twice + if (oracles[potential] && !signed[td.id][potential]) { + signed[td.id][potential] = true; + numberSigs++; + + if (numberSigs >= 10) { + break; + } + } + } + + require( + numberSigs >= threshold, + "Not enough valid signatures provided" + ); + + release(td.toAddress, td.quantity); + + emit Claimed(td.id, td.toAddress, td.quantity); + + return td.toAddress; + } + + function updateThreshold(uint8 newThreshold) + public + onlyOwner + returns (bool success) + { + if (newThreshold > 0) { + require(newThreshold <= 10, "Threshold has maximum of 10"); + + threshold = newThreshold; + + return true; + } + + return false; + } + + // ------------------------------------------------------------------------ + // Don't accept ETH + // ------------------------------------------------------------------------ + receive() external payable { + revert(); + } + + // ------------------------------------------------------------------------ + // Owner can transfer out any accidentally sent ERC20 tokens + // ------------------------------------------------------------------------ + function transferAnyERC20Token(IERC20 tokenAddress, uint256 tokens) + public + onlyOwner + { + // We never transfer our RFOX to another addresses + require(tokenAddress != rfox, "Token locked"); + // Transfer any tokens + tokenAddress.safeTransfer(owner, tokens); + } + + /// @notice Function that lock the RFOX token when bridging + /// @dev Internal function, only call when bridging + /// @param from Owner of this bridge action + /// @param amount Quantity RFOX for bridging of this bridge action + function lock(address from, uint256 amount) internal { + totalLocked = totalLocked.add(amount); + rfox.safeTransferFrom(from, address(this), amount); + + emit Locked(from, amount); + } + + /// @notice Function that release the RFOX token when bridging + /// @dev Internal function, only call when bridging + /// @param to Address of receive bridging token + /// @param amount Quantity RFOX for bridging of this bridge action + function release(address to, uint256 amount) internal { + totalLocked = totalLocked.sub(amount); + rfox.safeTransfer(to, amount); + + emit Released(to, amount); + } +} diff --git a/contracts/mutants/ETHWAXBRIDGE/3/VVR/ETHWAXBRIDGE.sol b/contracts/mutants/ETHWAXBRIDGE/3/VVR/ETHWAXBRIDGE.sol new file mode 100644 index 00000000000..2a9cd6c605b --- /dev/null +++ b/contracts/mutants/ETHWAXBRIDGE/3/VVR/ETHWAXBRIDGE.sol @@ -0,0 +1,284 @@ +//SPDX-License-Identifier: MIT + +pragma solidity ^0.6.12; +pragma experimental ABIEncoderV2; + +import "@openzeppelin/contracts/token/ERC20/SafeERC20.sol"; + +import "./libraries/Endian.sol"; +//SWC-135-Code With No Effects:L10 +import "./interfaces/ERC20Interface.sol"; + +import "./Verify.sol"; +import "./Owned.sol"; + +// ---------------------------------------------------------------------------- +// Contract function to receive approval and execute function in one call +// +// Borrowed from MiniMeToken +// ---------------------------------------------------------------------------- +abstract contract ApproveAndCallFallBack { + function receiveApproval( + address from, + uint256 tokens, + address token, + bytes memory data + ) public virtual; +} + +contract Oracled is Owned { + mapping(address => bool) public oracles; + + modifier onlyOracle() { + require( + oracles[msg.sender] == true, + "Account is not a registered oracle" + ); + + _; + } + + function regOracle(address _newOracle) public onlyOwner { + require(!oracles[_newOracle], "Oracle is already registered"); + + oracles[_newOracle] = true; + } + + function unregOracle(address _remOracle) public onlyOwner { + require(oracles[_remOracle] == true, "Oracle is not registered"); + + delete oracles[_remOracle]; + } +} + +// ---------------------------------------------------------------------------- +// RFOX Bridge contract lock and release swap amount for each cross chain swap +// +// ---------------------------------------------------------------------------- +contract ETHWAXBRIDGE is Oracled, Verify { + using SafeMath for uint256; + using SafeERC20 for IERC20; + + // RFOX Token address + // Only using this address for bridging + IERC20 internal rfox; + // Threshold meaning the minimum requirement for oracle confirmations + uint8 internal threshold; + // ChainID for RFOX Bridge + uint8 internal thisChainId; + // How many locked token in ETHWAXBRIDGE + uint256 public totalLocked; + // Mapping from transaction ID + mapping(uint64 => mapping(address => bool)) signed; + mapping(uint64 => bool) public claimed; + + event Bridge( + address indexed from, + string to, + uint256 tokens, + uint256 chainId + ); + event Claimed(uint64 id, address to, uint256 tokens); + + struct BridgeData { + uint64 id; + uint32 ts; + uint64 fromAddr; + uint256 quantity; + uint64 symbolRaw; + uint8 chainId; + address toAddress; + } + + event Locked(address from, uint256 amount); + event Released(address to, uint256 amount); + + // ------------------------------------------------------------------------ + // Constructor + // ------------------------------------------------------------------------ + constructor(IERC20 rfoxAddress) public { + uint8 chainId; + + threshold = 3; + rfox = rfoxAddress; + + assembly { + chainId := chainid() + } + + thisChainId = chainId; + } + + // ------------------------------------------------------------------------ + // Moves tokens to the inaccessible account and then sends event for the oracles + // to monitor and issue on other chain + // to : WAX address + // tokens : number of tokens in satoshis + // chainId : The chain id that they will be sent to + // ------------------------------------------------------------------------ + + function bridge( + string memory to, + uint256 tokens, + uint256 chainid + ) public returns (bool success) { + lock(msg.sender, tokens); + + emit Bridge(msg.sender, to, tokens, chainid); + emit Locked(msg.sender, tokens); + + return true; + } + + // ------------------------------------------------------------------------ + // Claim tokens sent using signatures supplied to the other chain + // ------------------------------------------------------------------------ + + function verifySigData(bytes memory sigData) + private + returns (BridgeData memory) + { + BridgeData memory td; + + uint64 oracleQuantity = 0; + uint64 id; + uint32 ts; + uint64 fromAddr; + uint64 symbolRaw; + uint8 chainId; + address toAddress; + + assembly { + id := mload(add(add(sigData, 0x8), 0)) + ts := mload(add(add(sigData, 0x4), 8)) + fromAddr := mload(add(add(sigData, 0x8), 12)) + oracleQuantity := mload(add(add(sigData, 0x8), 20)) + symbolRaw := mload(add(add(sigData, 0x8), 28)) + chainId := mload(add(add(sigData, 0x1), 36)) + toAddress := mload(add(add(sigData, 0x14), 37)) + } + + uint256 reversedQuantity = Endian.reverse64(oracleQuantity); + + td.id = Endian.reverse64(id); + td.ts = Endian.reverse32(ts); + td.fromAddr = Endian.reverse64(fromAddr); + td.quantity = uint256(reversedQuantity) * 1e10; + td.symbolRaw = Endian.reverse64(symbolRaw); + td.chainId = chainId; + td.toAddress = toAddress; + + require(thisChainId == td.chainId, "Invalid Chain ID"); + require( + block.timestamp < SafeMath.add(td.ts, (60 * 60 * 24 * 30)), + "Bridge has expired" + ); + + require(!claimed[td.id], "Already Claimed"); + + claimed[td.id] = true; + + return td; + } + + function claim(bytes memory sigData, bytes[] calldata signatures) + public + returns (address toAddress) + { + BridgeData memory td = verifySigData(sigData); + + // verify signatures + require(sigData.length == 69, "Signature data is the wrong size"); + require( + signatures.length <= 10, + "Maximum of 10 signatures can be provided" + ); + + bytes32 message = keccak256(sigData); + + uint8 numberSigs = 0; + + for (uint8 i = 0; i < signatures.length; i++) { + address potential = Verify.recoverSigner(message, signatures[i]); + + // Check that they are an oracle and they haven't signed twice + if (oracles[potential] && !signed[td.id][potential]) { + signed[td.id][potential] = true; + numberSigs++; + + if (numberSigs >= 10) { + break; + } + } + } + + require( + numberSigs >= threshold, + "Not enough valid signatures provided" + ); + + release(td.toAddress, td.quantity); + + emit Claimed(td.id, td.toAddress, td.quantity); + + return td.toAddress; + } + + function updateThreshold(uint8 newThreshold) + public + onlyOwner + returns (bool success) + { + if (newThreshold > 0) { + require(newThreshold <= 10, "Threshold has maximum of 10"); + + threshold = newThreshold; + + return true; + } + + return false; + } + + // ------------------------------------------------------------------------ + // Don't accept ETH + // ------------------------------------------------------------------------ + receive() external payable { + revert(); + } + + // ------------------------------------------------------------------------ + // Owner can transfer out any accidentally sent ERC20 tokens + // ------------------------------------------------------------------------ + function transferAnyERC20Token(IERC20 tokenAddress, uint256 tokens) + public + onlyOwner + { + // We never transfer our RFOX to another addresses + require(tokenAddress != rfox, "Token locked"); + // Transfer any tokens + tokenAddress.safeTransfer(owner, tokens); + } + + /// @notice Function that lock the RFOX token when bridging + /// @dev Internal function, only call when bridging + /// @param from Owner of this bridge action + /// @param amount Quantity RFOX for bridging of this bridge action + function lock(address from, uint256 amount) internal { + totalLocked = totalLocked.add(amount); + rfox.safeTransferFrom(from, address(this), amount); + + emit Locked(from, amount); + } + + /// @notice Function that release the RFOX token when bridging + /// @dev Internal function, only call when bridging + /// @param to Address of receive bridging token + /// @param amount Quantity RFOX for bridging of this bridge action + function release(address to, uint256 amount) internal { + totalLocked = totalLocked.sub(amount); + rfox.safeTransfer(to, amount); + + emit Released(to, amount); + } +} diff --git a/contracts/mutants/ETHWAXBRIDGE/4/BLR/ETHWAXBRIDGE.sol b/contracts/mutants/ETHWAXBRIDGE/4/BLR/ETHWAXBRIDGE.sol new file mode 100644 index 00000000000..1fe79fead65 --- /dev/null +++ b/contracts/mutants/ETHWAXBRIDGE/4/BLR/ETHWAXBRIDGE.sol @@ -0,0 +1,284 @@ +//SPDX-License-Identifier: MIT + +pragma solidity ^0.6.12; +pragma experimental ABIEncoderV2; + +import "@openzeppelin/contracts/token/ERC20/SafeERC20.sol"; + +import "./libraries/Endian.sol"; +//SWC-135-Code With No Effects:L10 +import "./interfaces/ERC20Interface.sol"; + +import "./Verify.sol"; +import "./Owned.sol"; + +// ---------------------------------------------------------------------------- +// Contract function to receive approval and execute function in one call +// +// Borrowed from MiniMeToken +// ---------------------------------------------------------------------------- +abstract contract ApproveAndCallFallBack { + function receiveApproval( + address from, + uint256 tokens, + address token, + bytes memory data + ) public virtual; +} + +contract Oracled is Owned { + mapping(address => bool) public oracles; + + modifier onlyOracle() { + require( + oracles[msg.sender] == false, + "Account is not a registered oracle" + ); + + _; + } + + function regOracle(address _newOracle) public onlyOwner { + require(!oracles[_newOracle], "Oracle is already registered"); + + oracles[_newOracle] = false; + } + + function unregOracle(address _remOracle) public onlyOwner { + require(oracles[_remOracle] == false, "Oracle is not registered"); + + delete oracles[_remOracle]; + } +} + +// ---------------------------------------------------------------------------- +// RFOX Bridge contract lock and release swap amount for each cross chain swap +// +// ---------------------------------------------------------------------------- +contract ETHWAXBRIDGE is Oracled, Verify { + using SafeMath for uint256; + using SafeERC20 for IERC20; + + // RFOX Token address + // Only using this address for bridging + IERC20 public rfox; + // Threshold meaning the minimum requirement for oracle confirmations + uint8 public threshold; + // ChainID for RFOX Bridge + uint8 public thisChainId; + // How many locked token in ETHWAXBRIDGE + uint256 public totalLocked; + // Mapping from transaction ID + mapping(uint64 => mapping(address => bool)) signed; + mapping(uint64 => bool) public claimed; + + event Bridge( + address indexed from, + string to, + uint256 tokens, + uint256 chainId + ); + event Claimed(uint64 id, address to, uint256 tokens); + + struct BridgeData { + uint64 id; + uint32 ts; + uint64 fromAddr; + uint256 quantity; + uint64 symbolRaw; + uint8 chainId; + address toAddress; + } + + event Locked(address from, uint256 amount); + event Released(address to, uint256 amount); + + // ------------------------------------------------------------------------ + // Constructor + // ------------------------------------------------------------------------ + constructor(IERC20 rfoxAddress) public { + uint8 chainId; + + threshold = 3; + rfox = rfoxAddress; + + assembly { + chainId := chainid() + } + + thisChainId = chainId; + } + + // ------------------------------------------------------------------------ + // Moves tokens to the inaccessible account and then sends event for the oracles + // to monitor and issue on other chain + // to : WAX address + // tokens : number of tokens in satoshis + // chainId : The chain id that they will be sent to + // ------------------------------------------------------------------------ + + function bridge( + string memory to, + uint256 tokens, + uint256 chainid + ) public returns (bool success) { + lock(msg.sender, tokens); + + emit Bridge(msg.sender, to, tokens, chainid); + emit Locked(msg.sender, tokens); + + return false; + } + + // ------------------------------------------------------------------------ + // Claim tokens sent using signatures supplied to the other chain + // ------------------------------------------------------------------------ + + function verifySigData(bytes memory sigData) + private + returns (BridgeData memory) + { + BridgeData memory td; + + uint64 oracleQuantity = 0; + uint64 id; + uint32 ts; + uint64 fromAddr; + uint64 symbolRaw; + uint8 chainId; + address toAddress; + + assembly { + id := mload(add(add(sigData, 0x8), 0)) + ts := mload(add(add(sigData, 0x4), 8)) + fromAddr := mload(add(add(sigData, 0x8), 12)) + oracleQuantity := mload(add(add(sigData, 0x8), 20)) + symbolRaw := mload(add(add(sigData, 0x8), 28)) + chainId := mload(add(add(sigData, 0x1), 36)) + toAddress := mload(add(add(sigData, 0x14), 37)) + } + + uint256 reversedQuantity = Endian.reverse64(oracleQuantity); + + td.id = Endian.reverse64(id); + td.ts = Endian.reverse32(ts); + td.fromAddr = Endian.reverse64(fromAddr); + td.quantity = uint256(reversedQuantity) * 1e10; + td.symbolRaw = Endian.reverse64(symbolRaw); + td.chainId = chainId; + td.toAddress = toAddress; + + require(thisChainId == td.chainId, "Invalid Chain ID"); + require( + block.timestamp < SafeMath.add(td.ts, (60 * 60 * 24 * 30)), + "Bridge has expired" + ); + + require(!claimed[td.id], "Already Claimed"); + + claimed[td.id] = true; + + return td; + } + + function claim(bytes memory sigData, bytes[] calldata signatures) + public + returns (address toAddress) + { + BridgeData memory td = verifySigData(sigData); + + // verify signatures + require(sigData.length == 69, "Signature data is the wrong size"); + require( + signatures.length <= 10, + "Maximum of 10 signatures can be provided" + ); + + bytes32 message = keccak256(sigData); + + uint8 numberSigs = 0; + + for (uint8 i = 0; i < signatures.length; i++) { + address potential = Verify.recoverSigner(message, signatures[i]); + + // Check that they are an oracle and they haven't signed twice + if (oracles[potential] && !signed[td.id][potential]) { + signed[td.id][potential] = true; + numberSigs++; + + if (numberSigs >= 10) { + break; + } + } + } + + require( + numberSigs >= threshold, + "Not enough valid signatures provided" + ); + + release(td.toAddress, td.quantity); + + emit Claimed(td.id, td.toAddress, td.quantity); + + return td.toAddress; + } + + function updateThreshold(uint8 newThreshold) + public + onlyOwner + returns (bool success) + { + if (newThreshold > 0) { + require(newThreshold <= 10, "Threshold has maximum of 10"); + + threshold = newThreshold; + + return true; + } + + return false; + } + + // ------------------------------------------------------------------------ + // Don't accept ETH + // ------------------------------------------------------------------------ + receive() external payable { + revert(); + } + + // ------------------------------------------------------------------------ + // Owner can transfer out any accidentally sent ERC20 tokens + // ------------------------------------------------------------------------ + function transferAnyERC20Token(IERC20 tokenAddress, uint256 tokens) + public + onlyOwner + { + // We never transfer our RFOX to another addresses + require(tokenAddress != rfox, "Token locked"); + // Transfer any tokens + tokenAddress.safeTransfer(owner, tokens); + } + + /// @notice Function that lock the RFOX token when bridging + /// @dev Internal function, only call when bridging + /// @param from Owner of this bridge action + /// @param amount Quantity RFOX for bridging of this bridge action + function lock(address from, uint256 amount) internal { + totalLocked = totalLocked.add(amount); + rfox.safeTransferFrom(from, address(this), amount); + + emit Locked(from, amount); + } + + /// @notice Function that release the RFOX token when bridging + /// @dev Internal function, only call when bridging + /// @param to Address of receive bridging token + /// @param amount Quantity RFOX for bridging of this bridge action + function release(address to, uint256 amount) internal { + totalLocked = totalLocked.sub(amount); + rfox.safeTransfer(to, amount); + + emit Released(to, amount); + } +} diff --git a/contracts/mutants/ETHWAXBRIDGE/4/BOR/ETHWAXBRIDGE.sol b/contracts/mutants/ETHWAXBRIDGE/4/BOR/ETHWAXBRIDGE.sol new file mode 100644 index 00000000000..2b6bed10f69 --- /dev/null +++ b/contracts/mutants/ETHWAXBRIDGE/4/BOR/ETHWAXBRIDGE.sol @@ -0,0 +1,284 @@ +//SPDX-License-Identifier: MIT + +pragma solidity ^0.6.12; +pragma experimental ABIEncoderV2; + +import "@openzeppelin/contracts/token/ERC20/SafeERC20.sol"; + +import "./libraries/Endian.sol"; +//SWC-135-Code With No Effects:L10 +import "./interfaces/ERC20Interface.sol"; + +import "./Verify.sol"; +import "./Owned.sol"; + +// ---------------------------------------------------------------------------- +// Contract function to receive approval and execute function in one call +// +// Borrowed from MiniMeToken +// ---------------------------------------------------------------------------- +abstract contract ApproveAndCallFallBack { + function receiveApproval( + address from, + uint256 tokens, + address token, + bytes memory data + ) public virtual; +} + +contract Oracled is Owned { + mapping(address => bool) public oracles; + + modifier onlyOracle() { + require( + oracles[msg.sender] <= true, + "Account is not a registered oracle" + ); + + _; + } + + function regOracle(address _newOracle) public onlyOwner { + require(!oracles[_newOracle], "Oracle is already registered"); + + oracles[_newOracle] = true; + } + + function unregOracle(address _remOracle) public onlyOwner { + require(oracles[_remOracle] <= true, "Oracle is not registered"); + + delete oracles[_remOracle]; + } +} + +// ---------------------------------------------------------------------------- +// RFOX Bridge contract lock and release swap amount for each cross chain swap +// +// ---------------------------------------------------------------------------- +contract ETHWAXBRIDGE is Oracled, Verify { + using SafeMath for uint256; + using SafeERC20 for IERC20; + + // RFOX Token address + // Only using this address for bridging + IERC20 public rfox; + // Threshold meaning the minimum requirement for oracle confirmations + uint8 public threshold; + // ChainID for RFOX Bridge + uint8 public thisChainId; + // How many locked token in ETHWAXBRIDGE + uint256 public totalLocked; + // Mapping from transaction ID + mapping(uint64 => mapping(address => bool)) signed; + mapping(uint64 => bool) public claimed; + + event Bridge( + address indexed from, + string to, + uint256 tokens, + uint256 chainId + ); + event Claimed(uint64 id, address to, uint256 tokens); + + struct BridgeData { + uint64 id; + uint32 ts; + uint64 fromAddr; + uint256 quantity; + uint64 symbolRaw; + uint8 chainId; + address toAddress; + } + + event Locked(address from, uint256 amount); + event Released(address to, uint256 amount); + + // ------------------------------------------------------------------------ + // Constructor + // ------------------------------------------------------------------------ + constructor(IERC20 rfoxAddress) public { + uint8 chainId; + + threshold = 3; + rfox = rfoxAddress; + + assembly { + chainId := chainid() + } + + thisChainId = chainId; + } + + // ------------------------------------------------------------------------ + // Moves tokens to the inaccessible account and then sends event for the oracles + // to monitor and issue on other chain + // to : WAX address + // tokens : number of tokens in satoshis + // chainId : The chain id that they will be sent to + // ------------------------------------------------------------------------ + + function bridge( + string memory to, + uint256 tokens, + uint256 chainid + ) public returns (bool success) { + lock(msg.sender, tokens); + + emit Bridge(msg.sender, to, tokens, chainid); + emit Locked(msg.sender, tokens); + + return true; + } + + // ------------------------------------------------------------------------ + // Claim tokens sent using signatures supplied to the other chain + // ------------------------------------------------------------------------ + + function verifySigData(bytes memory sigData) + private + returns (BridgeData memory) + { + BridgeData memory td; + + uint64 oracleQuantity = 0; + uint64 id; + uint32 ts; + uint64 fromAddr; + uint64 symbolRaw; + uint8 chainId; + address toAddress; + + assembly { + id := mload(add(add(sigData, 0x8), 0)) + ts := mload(add(add(sigData, 0x4), 8)) + fromAddr := mload(add(add(sigData, 0x8), 12)) + oracleQuantity := mload(add(add(sigData, 0x8), 20)) + symbolRaw := mload(add(add(sigData, 0x8), 28)) + chainId := mload(add(add(sigData, 0x1), 36)) + toAddress := mload(add(add(sigData, 0x14), 37)) + } + + uint256 reversedQuantity = Endian.reverse64(oracleQuantity); + + td.id = Endian.reverse64(id); + td.ts = Endian.reverse32(ts); + td.fromAddr = Endian.reverse64(fromAddr); + td.quantity = uint256(reversedQuantity) + 1e10; + td.symbolRaw = Endian.reverse64(symbolRaw); + td.chainId = chainId; + td.toAddress = toAddress; + + require(thisChainId <= td.chainId, "Invalid Chain ID"); + require( + block.timestamp < SafeMath.add(td.ts, (60 * 60 * 24 * 30)), + "Bridge has expired" + ); + + require(!claimed[td.id], "Already Claimed"); + + claimed[td.id] = true; + + return td; + } + + function claim(bytes memory sigData, bytes[] calldata signatures) + public + returns (address toAddress) + { + BridgeData memory td = verifySigData(sigData); + + // verify signatures + require(sigData.length == 69, "Signature data is the wrong size"); + require( + signatures.length <= 10, + "Maximum of 10 signatures can be provided" + ); + + bytes32 message = keccak256(sigData); + + uint8 numberSigs = 0; + + for (uint8 i = 0; i < signatures.length; i++) { + address potential = Verify.recoverSigner(message, signatures[i]); + + // Check that they are an oracle and they haven't signed twice + if (oracles[potential] && !signed[td.id][potential]) { + signed[td.id][potential] = true; + numberSigs++; + + if (numberSigs >= 10) { + break; + } + } + } + + require( + numberSigs >= threshold, + "Not enough valid signatures provided" + ); + + release(td.toAddress, td.quantity); + + emit Claimed(td.id, td.toAddress, td.quantity); + + return td.toAddress; + } + + function updateThreshold(uint8 newThreshold) + public + onlyOwner + returns (bool success) + { + if (newThreshold > 0) { + require(newThreshold <= 10, "Threshold has maximum of 10"); + + threshold = newThreshold; + + return true; + } + + return false; + } + + // ------------------------------------------------------------------------ + // Don't accept ETH + // ------------------------------------------------------------------------ + receive() external payable { + revert(); + } + + // ------------------------------------------------------------------------ + // Owner can transfer out any accidentally sent ERC20 tokens + // ------------------------------------------------------------------------ + function transferAnyERC20Token(IERC20 tokenAddress, uint256 tokens) + public + onlyOwner + { + // We never transfer our RFOX to another addresses + require(tokenAddress != rfox, "Token locked"); + // Transfer any tokens + tokenAddress.safeTransfer(owner, tokens); + } + + /// @notice Function that lock the RFOX token when bridging + /// @dev Internal function, only call when bridging + /// @param from Owner of this bridge action + /// @param amount Quantity RFOX for bridging of this bridge action + function lock(address from, uint256 amount) internal { + totalLocked = totalLocked.add(amount); + rfox.safeTransferFrom(from, address(this), amount); + + emit Locked(from, amount); + } + + /// @notice Function that release the RFOX token when bridging + /// @dev Internal function, only call when bridging + /// @param to Address of receive bridging token + /// @param amount Quantity RFOX for bridging of this bridge action + function release(address to, uint256 amount) internal { + totalLocked = totalLocked.sub(amount); + rfox.safeTransfer(to, amount); + + emit Released(to, amount); + } +} diff --git a/contracts/mutants/ETHWAXBRIDGE/4/DLR/ETHWAXBRIDGE.sol b/contracts/mutants/ETHWAXBRIDGE/4/DLR/ETHWAXBRIDGE.sol new file mode 100644 index 00000000000..33bdef6b594 --- /dev/null +++ b/contracts/mutants/ETHWAXBRIDGE/4/DLR/ETHWAXBRIDGE.sol @@ -0,0 +1,284 @@ +//SPDX-License-Identifier: MIT + +pragma solidity ^0.6.12; +pragma experimental ABIEncoderV2; + +import "@openzeppelin/contracts/token/ERC20/SafeERC20.sol"; + +import "./libraries/Endian.sol"; +//SWC-135-Code With No Effects:L10 +import "./interfaces/ERC20Interface.sol"; + +import "./Verify.sol"; +import "./Owned.sol"; + +// ---------------------------------------------------------------------------- +// Contract function to receive approval and execute function in one call +// +// Borrowed from MiniMeToken +// ---------------------------------------------------------------------------- +abstract contract ApproveAndCallFallBack { + function receiveApproval( + address from, + uint256 tokens, + address token, + bytes storage data + ) public virtual; +} + +contract Oracled is Owned { + mapping(address => bool) public oracles; + + modifier onlyOracle() { + require( + oracles[msg.sender] == true, + "Account is not a registered oracle" + ); + + _; + } + + function regOracle(address _newOracle) public onlyOwner { + require(!oracles[_newOracle], "Oracle is already registered"); + + oracles[_newOracle] = true; + } + + function unregOracle(address _remOracle) public onlyOwner { + require(oracles[_remOracle] == true, "Oracle is not registered"); + + delete oracles[_remOracle]; + } +} + +// ---------------------------------------------------------------------------- +// RFOX Bridge contract lock and release swap amount for each cross chain swap +// +// ---------------------------------------------------------------------------- +contract ETHWAXBRIDGE is Oracled, Verify { + using SafeMath for uint256; + using SafeERC20 for IERC20; + + // RFOX Token address + // Only using this address for bridging + IERC20 public rfox; + // Threshold meaning the minimum requirement for oracle confirmations + uint8 public threshold; + // ChainID for RFOX Bridge + uint8 public thisChainId; + // How many locked token in ETHWAXBRIDGE + uint256 public totalLocked; + // Mapping from transaction ID + mapping(uint64 => mapping(address => bool)) signed; + mapping(uint64 => bool) public claimed; + + event Bridge( + address indexed from, + string to, + uint256 tokens, + uint256 chainId + ); + event Claimed(uint64 id, address to, uint256 tokens); + + struct BridgeData { + uint64 id; + uint32 ts; + uint64 fromAddr; + uint256 quantity; + uint64 symbolRaw; + uint8 chainId; + address toAddress; + } + + event Locked(address from, uint256 amount); + event Released(address to, uint256 amount); + + // ------------------------------------------------------------------------ + // Constructor + // ------------------------------------------------------------------------ + constructor(IERC20 rfoxAddress) public { + uint8 chainId; + + threshold = 3; + rfox = rfoxAddress; + + assembly { + chainId := chainid() + } + + thisChainId = chainId; + } + + // ------------------------------------------------------------------------ + // Moves tokens to the inaccessible account and then sends event for the oracles + // to monitor and issue on other chain + // to : WAX address + // tokens : number of tokens in satoshis + // chainId : The chain id that they will be sent to + // ------------------------------------------------------------------------ + + function bridge( + string storage to, + uint256 tokens, + uint256 chainid + ) public returns (bool success) { + lock(msg.sender, tokens); + + emit Bridge(msg.sender, to, tokens, chainid); + emit Locked(msg.sender, tokens); + + return true; + } + + // ------------------------------------------------------------------------ + // Claim tokens sent using signatures supplied to the other chain + // ------------------------------------------------------------------------ + + function verifySigData(bytes storage sigData) + private + returns (BridgeData storage) + { + BridgeData memory td; + + uint64 oracleQuantity = 0; + uint64 id; + uint32 ts; + uint64 fromAddr; + uint64 symbolRaw; + uint8 chainId; + address toAddress; + + assembly { + id := mload(add(add(sigData, 0x8), 0)) + ts := mload(add(add(sigData, 0x4), 8)) + fromAddr := mload(add(add(sigData, 0x8), 12)) + oracleQuantity := mload(add(add(sigData, 0x8), 20)) + symbolRaw := mload(add(add(sigData, 0x8), 28)) + chainId := mload(add(add(sigData, 0x1), 36)) + toAddress := mload(add(add(sigData, 0x14), 37)) + } + + uint256 reversedQuantity = Endian.reverse64(oracleQuantity); + + td.id = Endian.reverse64(id); + td.ts = Endian.reverse32(ts); + td.fromAddr = Endian.reverse64(fromAddr); + td.quantity = uint256(reversedQuantity) * 1e10; + td.symbolRaw = Endian.reverse64(symbolRaw); + td.chainId = chainId; + td.toAddress = toAddress; + + require(thisChainId == td.chainId, "Invalid Chain ID"); + require( + block.timestamp < SafeMath.add(td.ts, (60 * 60 * 24 * 30)), + "Bridge has expired" + ); + + require(!claimed[td.id], "Already Claimed"); + + claimed[td.id] = true; + + return td; + } + + function claim(bytes memory sigData, bytes[] calldata signatures) + public + returns (address toAddress) + { + BridgeData memory td = verifySigData(sigData); + + // verify signatures + require(sigData.length == 69, "Signature data is the wrong size"); + require( + signatures.length <= 10, + "Maximum of 10 signatures can be provided" + ); + + bytes32 message = keccak256(sigData); + + uint8 numberSigs = 0; + + for (uint8 i = 0; i < signatures.length; i++) { + address potential = Verify.recoverSigner(message, signatures[i]); + + // Check that they are an oracle and they haven't signed twice + if (oracles[potential] && !signed[td.id][potential]) { + signed[td.id][potential] = true; + numberSigs++; + + if (numberSigs >= 10) { + break; + } + } + } + + require( + numberSigs >= threshold, + "Not enough valid signatures provided" + ); + + release(td.toAddress, td.quantity); + + emit Claimed(td.id, td.toAddress, td.quantity); + + return td.toAddress; + } + + function updateThreshold(uint8 newThreshold) + public + onlyOwner + returns (bool success) + { + if (newThreshold > 0) { + require(newThreshold <= 10, "Threshold has maximum of 10"); + + threshold = newThreshold; + + return true; + } + + return false; + } + + // ------------------------------------------------------------------------ + // Don't accept ETH + // ------------------------------------------------------------------------ + receive() external payable { + revert(); + } + + // ------------------------------------------------------------------------ + // Owner can transfer out any accidentally sent ERC20 tokens + // ------------------------------------------------------------------------ + function transferAnyERC20Token(IERC20 tokenAddress, uint256 tokens) + public + onlyOwner + { + // We never transfer our RFOX to another addresses + require(tokenAddress != rfox, "Token locked"); + // Transfer any tokens + tokenAddress.safeTransfer(owner, tokens); + } + + /// @notice Function that lock the RFOX token when bridging + /// @dev Internal function, only call when bridging + /// @param from Owner of this bridge action + /// @param amount Quantity RFOX for bridging of this bridge action + function lock(address from, uint256 amount) internal { + totalLocked = totalLocked.add(amount); + rfox.safeTransferFrom(from, address(this), amount); + + emit Locked(from, amount); + } + + /// @notice Function that release the RFOX token when bridging + /// @dev Internal function, only call when bridging + /// @param to Address of receive bridging token + /// @param amount Quantity RFOX for bridging of this bridge action + function release(address to, uint256 amount) internal { + totalLocked = totalLocked.sub(amount); + rfox.safeTransfer(to, amount); + + emit Released(to, amount); + } +} diff --git a/contracts/mutants/ETHWAXBRIDGE/4/EED/ETHWAXBRIDGE.sol b/contracts/mutants/ETHWAXBRIDGE/4/EED/ETHWAXBRIDGE.sol new file mode 100644 index 00000000000..6fbcca610f6 --- /dev/null +++ b/contracts/mutants/ETHWAXBRIDGE/4/EED/ETHWAXBRIDGE.sol @@ -0,0 +1,284 @@ +//SPDX-License-Identifier: MIT + +pragma solidity ^0.6.12; +pragma experimental ABIEncoderV2; + +import "@openzeppelin/contracts/token/ERC20/SafeERC20.sol"; + +import "./libraries/Endian.sol"; +//SWC-135-Code With No Effects:L10 +import "./interfaces/ERC20Interface.sol"; + +import "./Verify.sol"; +import "./Owned.sol"; + +// ---------------------------------------------------------------------------- +// Contract function to receive approval and execute function in one call +// +// Borrowed from MiniMeToken +// ---------------------------------------------------------------------------- +abstract contract ApproveAndCallFallBack { + function receiveApproval( + address from, + uint256 tokens, + address token, + bytes memory data + ) public virtual; +} + +contract Oracled is Owned { + mapping(address => bool) public oracles; + + modifier onlyOracle() { + require( + oracles[msg.sender] == true, + "Account is not a registered oracle" + ); + + _; + } + + function regOracle(address _newOracle) public onlyOwner { + require(!oracles[_newOracle], "Oracle is already registered"); + + oracles[_newOracle] = true; + } + + function unregOracle(address _remOracle) public onlyOwner { + require(oracles[_remOracle] == true, "Oracle is not registered"); + + delete oracles[_remOracle]; + } +} + +// ---------------------------------------------------------------------------- +// RFOX Bridge contract lock and release swap amount for each cross chain swap +// +// ---------------------------------------------------------------------------- +contract ETHWAXBRIDGE is Oracled, Verify { + using SafeMath for uint256; + using SafeERC20 for IERC20; + + // RFOX Token address + // Only using this address for bridging + IERC20 public rfox; + // Threshold meaning the minimum requirement for oracle confirmations + uint8 public threshold; + // ChainID for RFOX Bridge + uint8 public thisChainId; + // How many locked token in ETHWAXBRIDGE + uint256 public totalLocked; + // Mapping from transaction ID + mapping(uint64 => mapping(address => bool)) signed; + mapping(uint64 => bool) public claimed; + + event Bridge( + address indexed from, + string to, + uint256 tokens, + uint256 chainId + ); + event Claimed(uint64 id, address to, uint256 tokens); + + struct BridgeData { + uint64 id; + uint32 ts; + uint64 fromAddr; + uint256 quantity; + uint64 symbolRaw; + uint8 chainId; + address toAddress; + } + + event Locked(address from, uint256 amount); + event Released(address to, uint256 amount); + + // ------------------------------------------------------------------------ + // Constructor + // ------------------------------------------------------------------------ + constructor(IERC20 rfoxAddress) public { + uint8 chainId; + + threshold = 3; + rfox = rfoxAddress; + + assembly { + chainId := chainid() + } + + thisChainId = chainId; + } + + // ------------------------------------------------------------------------ + // Moves tokens to the inaccessible account and then sends event for the oracles + // to monitor and issue on other chain + // to : WAX address + // tokens : number of tokens in satoshis + // chainId : The chain id that they will be sent to + // ------------------------------------------------------------------------ + + function bridge( + string memory to, + uint256 tokens, + uint256 chainid + ) public returns (bool success) { + lock(msg.sender, tokens); + + /* emit Bridge(msg.sender, to, tokens, chainid); */ + /* emit Locked(msg.sender, tokens); */ + + return true; + } + + // ------------------------------------------------------------------------ + // Claim tokens sent using signatures supplied to the other chain + // ------------------------------------------------------------------------ + + function verifySigData(bytes memory sigData) + private + returns (BridgeData memory) + { + BridgeData memory td; + + uint64 oracleQuantity = 0; + uint64 id; + uint32 ts; + uint64 fromAddr; + uint64 symbolRaw; + uint8 chainId; + address toAddress; + + assembly { + id := mload(add(add(sigData, 0x8), 0)) + ts := mload(add(add(sigData, 0x4), 8)) + fromAddr := mload(add(add(sigData, 0x8), 12)) + oracleQuantity := mload(add(add(sigData, 0x8), 20)) + symbolRaw := mload(add(add(sigData, 0x8), 28)) + chainId := mload(add(add(sigData, 0x1), 36)) + toAddress := mload(add(add(sigData, 0x14), 37)) + } + + uint256 reversedQuantity = Endian.reverse64(oracleQuantity); + + td.id = Endian.reverse64(id); + td.ts = Endian.reverse32(ts); + td.fromAddr = Endian.reverse64(fromAddr); + td.quantity = uint256(reversedQuantity) * 1e10; + td.symbolRaw = Endian.reverse64(symbolRaw); + td.chainId = chainId; + td.toAddress = toAddress; + + require(thisChainId == td.chainId, "Invalid Chain ID"); + require( + block.timestamp < SafeMath.add(td.ts, (60 * 60 * 24 * 30)), + "Bridge has expired" + ); + + require(!claimed[td.id], "Already Claimed"); + + claimed[td.id] = true; + + return td; + } + + function claim(bytes memory sigData, bytes[] calldata signatures) + public + returns (address toAddress) + { + BridgeData memory td = verifySigData(sigData); + + // verify signatures + require(sigData.length == 69, "Signature data is the wrong size"); + require( + signatures.length <= 10, + "Maximum of 10 signatures can be provided" + ); + + bytes32 message = keccak256(sigData); + + uint8 numberSigs = 0; + + for (uint8 i = 0; i < signatures.length; i++) { + address potential = Verify.recoverSigner(message, signatures[i]); + + // Check that they are an oracle and they haven't signed twice + if (oracles[potential] && !signed[td.id][potential]) { + signed[td.id][potential] = true; + numberSigs++; + + if (numberSigs >= 10) { + break; + } + } + } + + require( + numberSigs >= threshold, + "Not enough valid signatures provided" + ); + + release(td.toAddress, td.quantity); + + /* emit Claimed(td.id, td.toAddress, td.quantity); */ + + return td.toAddress; + } + + function updateThreshold(uint8 newThreshold) + public + onlyOwner + returns (bool success) + { + if (newThreshold > 0) { + require(newThreshold <= 10, "Threshold has maximum of 10"); + + threshold = newThreshold; + + return true; + } + + return false; + } + + // ------------------------------------------------------------------------ + // Don't accept ETH + // ------------------------------------------------------------------------ + receive() external payable { + revert(); + } + + // ------------------------------------------------------------------------ + // Owner can transfer out any accidentally sent ERC20 tokens + // ------------------------------------------------------------------------ + function transferAnyERC20Token(IERC20 tokenAddress, uint256 tokens) + public + onlyOwner + { + // We never transfer our RFOX to another addresses + require(tokenAddress != rfox, "Token locked"); + // Transfer any tokens + tokenAddress.safeTransfer(owner, tokens); + } + + /// @notice Function that lock the RFOX token when bridging + /// @dev Internal function, only call when bridging + /// @param from Owner of this bridge action + /// @param amount Quantity RFOX for bridging of this bridge action + function lock(address from, uint256 amount) internal { + totalLocked = totalLocked.add(amount); + rfox.safeTransferFrom(from, address(this), amount); + + /* emit Locked(from, amount); */ + } + + /// @notice Function that release the RFOX token when bridging + /// @dev Internal function, only call when bridging + /// @param to Address of receive bridging token + /// @param amount Quantity RFOX for bridging of this bridge action + function release(address to, uint256 amount) internal { + totalLocked = totalLocked.sub(amount); + rfox.safeTransfer(to, amount); + + emit Released(to, amount); + } +} diff --git a/contracts/mutants/ETHWAXBRIDGE/4/EHC/ETHWAXBRIDGE.sol b/contracts/mutants/ETHWAXBRIDGE/4/EHC/ETHWAXBRIDGE.sol new file mode 100644 index 00000000000..7ce9cdfd311 --- /dev/null +++ b/contracts/mutants/ETHWAXBRIDGE/4/EHC/ETHWAXBRIDGE.sol @@ -0,0 +1,284 @@ +//SPDX-License-Identifier: MIT + +pragma solidity ^0.6.12; +pragma experimental ABIEncoderV2; + +import "@openzeppelin/contracts/token/ERC20/SafeERC20.sol"; + +import "./libraries/Endian.sol"; +//SWC-135-Code With No Effects:L10 +import "./interfaces/ERC20Interface.sol"; + +import "./Verify.sol"; +import "./Owned.sol"; + +// ---------------------------------------------------------------------------- +// Contract function to receive approval and execute function in one call +// +// Borrowed from MiniMeToken +// ---------------------------------------------------------------------------- +abstract contract ApproveAndCallFallBack { + function receiveApproval( + address from, + uint256 tokens, + address token, + bytes memory data + ) public virtual; +} + +contract Oracled is Owned { + mapping(address => bool) public oracles; + + modifier onlyOracle() { + /* require( + oracles[msg.sender] == true, + "Account is not a registered oracle" + ); */ + + _; + } + + function regOracle(address _newOracle) public onlyOwner { + /* require(!oracles[_newOracle], "Oracle is already registered"); */ + + oracles[_newOracle] = true; + } + + function unregOracle(address _remOracle) public onlyOwner { + /* require(oracles[_remOracle] == true, "Oracle is not registered"); */ + + delete oracles[_remOracle]; + } +} + +// ---------------------------------------------------------------------------- +// RFOX Bridge contract lock and release swap amount for each cross chain swap +// +// ---------------------------------------------------------------------------- +contract ETHWAXBRIDGE is Oracled, Verify { + using SafeMath for uint256; + using SafeERC20 for IERC20; + + // RFOX Token address + // Only using this address for bridging + IERC20 public rfox; + // Threshold meaning the minimum requirement for oracle confirmations + uint8 public threshold; + // ChainID for RFOX Bridge + uint8 public thisChainId; + // How many locked token in ETHWAXBRIDGE + uint256 public totalLocked; + // Mapping from transaction ID + mapping(uint64 => mapping(address => bool)) signed; + mapping(uint64 => bool) public claimed; + + event Bridge( + address indexed from, + string to, + uint256 tokens, + uint256 chainId + ); + event Claimed(uint64 id, address to, uint256 tokens); + + struct BridgeData { + uint64 id; + uint32 ts; + uint64 fromAddr; + uint256 quantity; + uint64 symbolRaw; + uint8 chainId; + address toAddress; + } + + event Locked(address from, uint256 amount); + event Released(address to, uint256 amount); + + // ------------------------------------------------------------------------ + // Constructor + // ------------------------------------------------------------------------ + constructor(IERC20 rfoxAddress) public { + uint8 chainId; + + threshold = 3; + rfox = rfoxAddress; + + assembly { + chainId := chainid() + } + + thisChainId = chainId; + } + + // ------------------------------------------------------------------------ + // Moves tokens to the inaccessible account and then sends event for the oracles + // to monitor and issue on other chain + // to : WAX address + // tokens : number of tokens in satoshis + // chainId : The chain id that they will be sent to + // ------------------------------------------------------------------------ + + function bridge( + string memory to, + uint256 tokens, + uint256 chainid + ) public returns (bool success) { + lock(msg.sender, tokens); + + emit Bridge(msg.sender, to, tokens, chainid); + emit Locked(msg.sender, tokens); + + return true; + } + + // ------------------------------------------------------------------------ + // Claim tokens sent using signatures supplied to the other chain + // ------------------------------------------------------------------------ + + function verifySigData(bytes memory sigData) + private + returns (BridgeData memory) + { + BridgeData memory td; + + uint64 oracleQuantity = 0; + uint64 id; + uint32 ts; + uint64 fromAddr; + uint64 symbolRaw; + uint8 chainId; + address toAddress; + + assembly { + id := mload(add(add(sigData, 0x8), 0)) + ts := mload(add(add(sigData, 0x4), 8)) + fromAddr := mload(add(add(sigData, 0x8), 12)) + oracleQuantity := mload(add(add(sigData, 0x8), 20)) + symbolRaw := mload(add(add(sigData, 0x8), 28)) + chainId := mload(add(add(sigData, 0x1), 36)) + toAddress := mload(add(add(sigData, 0x14), 37)) + } + + uint256 reversedQuantity = Endian.reverse64(oracleQuantity); + + td.id = Endian.reverse64(id); + td.ts = Endian.reverse32(ts); + td.fromAddr = Endian.reverse64(fromAddr); + td.quantity = uint256(reversedQuantity) * 1e10; + td.symbolRaw = Endian.reverse64(symbolRaw); + td.chainId = chainId; + td.toAddress = toAddress; + + /* require(thisChainId == td.chainId, "Invalid Chain ID"); */ + require( + block.timestamp < SafeMath.add(td.ts, (60 * 60 * 24 * 30)), + "Bridge has expired" + ); + + require(!claimed[td.id], "Already Claimed"); + + claimed[td.id] = true; + + return td; + } + + function claim(bytes memory sigData, bytes[] calldata signatures) + public + returns (address toAddress) + { + BridgeData memory td = verifySigData(sigData); + + // verify signatures + require(sigData.length == 69, "Signature data is the wrong size"); + require( + signatures.length <= 10, + "Maximum of 10 signatures can be provided" + ); + + bytes32 message = keccak256(sigData); + + uint8 numberSigs = 0; + + for (uint8 i = 0; i < signatures.length; i++) { + address potential = Verify.recoverSigner(message, signatures[i]); + + // Check that they are an oracle and they haven't signed twice + if (oracles[potential] && !signed[td.id][potential]) { + signed[td.id][potential] = true; + numberSigs++; + + if (numberSigs >= 10) { + break; + } + } + } + + require( + numberSigs >= threshold, + "Not enough valid signatures provided" + ); + + release(td.toAddress, td.quantity); + + emit Claimed(td.id, td.toAddress, td.quantity); + + return td.toAddress; + } + + function updateThreshold(uint8 newThreshold) + public + onlyOwner + returns (bool success) + { + if (newThreshold > 0) { + require(newThreshold <= 10, "Threshold has maximum of 10"); + + threshold = newThreshold; + + return true; + } + + return false; + } + + // ------------------------------------------------------------------------ + // Don't accept ETH + // ------------------------------------------------------------------------ + receive() external payable { + revert(); + } + + // ------------------------------------------------------------------------ + // Owner can transfer out any accidentally sent ERC20 tokens + // ------------------------------------------------------------------------ + function transferAnyERC20Token(IERC20 tokenAddress, uint256 tokens) + public + onlyOwner + { + // We never transfer our RFOX to another addresses + require(tokenAddress != rfox, "Token locked"); + // Transfer any tokens + tokenAddress.safeTransfer(owner, tokens); + } + + /// @notice Function that lock the RFOX token when bridging + /// @dev Internal function, only call when bridging + /// @param from Owner of this bridge action + /// @param amount Quantity RFOX for bridging of this bridge action + function lock(address from, uint256 amount) internal { + totalLocked = totalLocked.add(amount); + rfox.safeTransferFrom(from, address(this), amount); + + emit Locked(from, amount); + } + + /// @notice Function that release the RFOX token when bridging + /// @dev Internal function, only call when bridging + /// @param to Address of receive bridging token + /// @param amount Quantity RFOX for bridging of this bridge action + function release(address to, uint256 amount) internal { + totalLocked = totalLocked.sub(amount); + rfox.safeTransfer(to, amount); + + emit Released(to, amount); + } +} diff --git a/contracts/mutants/ETHWAXBRIDGE/4/FVR/ETHWAXBRIDGE.sol b/contracts/mutants/ETHWAXBRIDGE/4/FVR/ETHWAXBRIDGE.sol new file mode 100644 index 00000000000..e5f61469792 --- /dev/null +++ b/contracts/mutants/ETHWAXBRIDGE/4/FVR/ETHWAXBRIDGE.sol @@ -0,0 +1,284 @@ +//SPDX-License-Identifier: MIT + +pragma solidity ^0.6.12; +pragma experimental ABIEncoderV2; + +import "@openzeppelin/contracts/token/ERC20/SafeERC20.sol"; + +import "./libraries/Endian.sol"; +//SWC-135-Code With No Effects:L10 +import "./interfaces/ERC20Interface.sol"; + +import "./Verify.sol"; +import "./Owned.sol"; + +// ---------------------------------------------------------------------------- +// Contract function to receive approval and execute function in one call +// +// Borrowed from MiniMeToken +// ---------------------------------------------------------------------------- +abstract contract ApproveAndCallFallBack { + function receiveApproval( + address from, + uint256 tokens, + address token, + bytes memory data + ) public virtual; +} + +contract Oracled is Owned { + mapping(address => bool) public oracles; + + modifier onlyOracle() { + require( + oracles[msg.sender] == true, + "Account is not a registered oracle" + ); + + _; + } + + function regOracle(address _newOracle) external onlyOwner { + require(!oracles[_newOracle], "Oracle is already registered"); + + oracles[_newOracle] = true; + } + + function unregOracle(address _remOracle) external onlyOwner { + require(oracles[_remOracle] == true, "Oracle is not registered"); + + delete oracles[_remOracle]; + } +} + +// ---------------------------------------------------------------------------- +// RFOX Bridge contract lock and release swap amount for each cross chain swap +// +// ---------------------------------------------------------------------------- +contract ETHWAXBRIDGE is Oracled, Verify { + using SafeMath for uint256; + using SafeERC20 for IERC20; + + // RFOX Token address + // Only using this address for bridging + IERC20 public rfox; + // Threshold meaning the minimum requirement for oracle confirmations + uint8 public threshold; + // ChainID for RFOX Bridge + uint8 public thisChainId; + // How many locked token in ETHWAXBRIDGE + uint256 public totalLocked; + // Mapping from transaction ID + mapping(uint64 => mapping(address => bool)) signed; + mapping(uint64 => bool) public claimed; + + event Bridge( + address indexed from, + string to, + uint256 tokens, + uint256 chainId + ); + event Claimed(uint64 id, address to, uint256 tokens); + + struct BridgeData { + uint64 id; + uint32 ts; + uint64 fromAddr; + uint256 quantity; + uint64 symbolRaw; + uint8 chainId; + address toAddress; + } + + event Locked(address from, uint256 amount); + event Released(address to, uint256 amount); + + // ------------------------------------------------------------------------ + // Constructor + // ------------------------------------------------------------------------ + constructor(IERC20 rfoxAddress) internal { + uint8 chainId; + + threshold = 3; + rfox = rfoxAddress; + + assembly { + chainId := chainid() + } + + thisChainId = chainId; + } + + // ------------------------------------------------------------------------ + // Moves tokens to the inaccessible account and then sends event for the oracles + // to monitor and issue on other chain + // to : WAX address + // tokens : number of tokens in satoshis + // chainId : The chain id that they will be sent to + // ------------------------------------------------------------------------ + + function bridge( + string memory to, + uint256 tokens, + uint256 chainid + ) external returns (bool success) { + lock(msg.sender, tokens); + + emit Bridge(msg.sender, to, tokens, chainid); + emit Locked(msg.sender, tokens); + + return true; + } + + // ------------------------------------------------------------------------ + // Claim tokens sent using signatures supplied to the other chain + // ------------------------------------------------------------------------ + + function verifySigData(bytes memory sigData) + private + returns (BridgeData memory) + { + BridgeData memory td; + + uint64 oracleQuantity = 0; + uint64 id; + uint32 ts; + uint64 fromAddr; + uint64 symbolRaw; + uint8 chainId; + address toAddress; + + assembly { + id := mload(add(add(sigData, 0x8), 0)) + ts := mload(add(add(sigData, 0x4), 8)) + fromAddr := mload(add(add(sigData, 0x8), 12)) + oracleQuantity := mload(add(add(sigData, 0x8), 20)) + symbolRaw := mload(add(add(sigData, 0x8), 28)) + chainId := mload(add(add(sigData, 0x1), 36)) + toAddress := mload(add(add(sigData, 0x14), 37)) + } + + uint256 reversedQuantity = Endian.reverse64(oracleQuantity); + + td.id = Endian.reverse64(id); + td.ts = Endian.reverse32(ts); + td.fromAddr = Endian.reverse64(fromAddr); + td.quantity = uint256(reversedQuantity) * 1e10; + td.symbolRaw = Endian.reverse64(symbolRaw); + td.chainId = chainId; + td.toAddress = toAddress; + + require(thisChainId == td.chainId, "Invalid Chain ID"); + require( + block.timestamp < SafeMath.add(td.ts, (60 * 60 * 24 * 30)), + "Bridge has expired" + ); + + require(!claimed[td.id], "Already Claimed"); + + claimed[td.id] = true; + + return td; + } + + function claim(bytes memory sigData, bytes[] calldata signatures) + public + returns (address toAddress) + { + BridgeData memory td = verifySigData(sigData); + + // verify signatures + require(sigData.length == 69, "Signature data is the wrong size"); + require( + signatures.length <= 10, + "Maximum of 10 signatures can be provided" + ); + + bytes32 message = keccak256(sigData); + + uint8 numberSigs = 0; + + for (uint8 i = 0; i < signatures.length; i++) { + address potential = Verify.recoverSigner(message, signatures[i]); + + // Check that they are an oracle and they haven't signed twice + if (oracles[potential] && !signed[td.id][potential]) { + signed[td.id][potential] = true; + numberSigs++; + + if (numberSigs >= 10) { + break; + } + } + } + + require( + numberSigs >= threshold, + "Not enough valid signatures provided" + ); + + release(td.toAddress, td.quantity); + + emit Claimed(td.id, td.toAddress, td.quantity); + + return td.toAddress; + } + + function updateThreshold(uint8 newThreshold) + public + onlyOwner + returns (bool success) + { + if (newThreshold > 0) { + require(newThreshold <= 10, "Threshold has maximum of 10"); + + threshold = newThreshold; + + return true; + } + + return false; + } + + // ------------------------------------------------------------------------ + // Don't accept ETH + // ------------------------------------------------------------------------ + receive() external payable { + revert(); + } + + // ------------------------------------------------------------------------ + // Owner can transfer out any accidentally sent ERC20 tokens + // ------------------------------------------------------------------------ + function transferAnyERC20Token(IERC20 tokenAddress, uint256 tokens) + public + onlyOwner + { + // We never transfer our RFOX to another addresses + require(tokenAddress != rfox, "Token locked"); + // Transfer any tokens + tokenAddress.safeTransfer(owner, tokens); + } + + /// @notice Function that lock the RFOX token when bridging + /// @dev Internal function, only call when bridging + /// @param from Owner of this bridge action + /// @param amount Quantity RFOX for bridging of this bridge action + function lock(address from, uint256 amount) internal { + totalLocked = totalLocked.add(amount); + rfox.safeTransferFrom(from, address(this), amount); + + emit Locked(from, amount); + } + + /// @notice Function that release the RFOX token when bridging + /// @dev Internal function, only call when bridging + /// @param to Address of receive bridging token + /// @param amount Quantity RFOX for bridging of this bridge action + function release(address to, uint256 amount) internal { + totalLocked = totalLocked.sub(amount); + rfox.safeTransfer(to, amount); + + emit Released(to, amount); + } +} diff --git a/contracts/mutants/ETHWAXBRIDGE/4/ILR/ETHWAXBRIDGE.sol b/contracts/mutants/ETHWAXBRIDGE/4/ILR/ETHWAXBRIDGE.sol new file mode 100644 index 00000000000..2a06509486e --- /dev/null +++ b/contracts/mutants/ETHWAXBRIDGE/4/ILR/ETHWAXBRIDGE.sol @@ -0,0 +1,284 @@ +//SPDX-License-Identifier: MIT + +pragma solidity ^0.6.12; +pragma experimental ABIEncoderV2; + +import "@openzeppelin/contracts/token/ERC20/SafeERC20.sol"; + +import "./libraries/Endian.sol"; +//SWC-135-Code With No Effects:L10 +import "./interfaces/ERC20Interface.sol"; + +import "./Verify.sol"; +import "./Owned.sol"; + +// ---------------------------------------------------------------------------- +// Contract function to receive approval and execute function in one call +// +// Borrowed from MiniMeToken +// ---------------------------------------------------------------------------- +abstract contract ApproveAndCallFallBack { + function receiveApproval( + address from, + uint256 tokens, + address token, + bytes memory data + ) public virtual; +} + +contract Oracled is Owned { + mapping(address => bool) public oracles; + + modifier onlyOracle() { + require( + oracles[msg.sender] == true, + "Account is not a registered oracle" + ); + + _; + } + + function regOracle(address _newOracle) public onlyOwner { + require(!oracles[_newOracle], "Oracle is already registered"); + + oracles[_newOracle] = true; + } + + function unregOracle(address _remOracle) public onlyOwner { + require(oracles[_remOracle] == true, "Oracle is not registered"); + + delete oracles[_remOracle]; + } +} + +// ---------------------------------------------------------------------------- +// RFOX Bridge contract lock and release swap amount for each cross chain swap +// +// ---------------------------------------------------------------------------- +contract ETHWAXBRIDGE is Oracled, Verify { + using SafeMath for uint256; + using SafeERC20 for IERC20; + + // RFOX Token address + // Only using this address for bridging + IERC20 public rfox; + // Threshold meaning the minimum requirement for oracle confirmations + uint8 public threshold; + // ChainID for RFOX Bridge + uint8 public thisChainId; + // How many locked token in ETHWAXBRIDGE + uint256 public totalLocked; + // Mapping from transaction ID + mapping(uint64 => mapping(address => bool)) signed; + mapping(uint64 => bool) public claimed; + + event Bridge( + address indexed from, + string to, + uint256 tokens, + uint256 chainId + ); + event Claimed(uint64 id, address to, uint256 tokens); + + struct BridgeData { + uint64 id; + uint32 ts; + uint64 fromAddr; + uint256 quantity; + uint64 symbolRaw; + uint8 chainId; + address toAddress; + } + + event Locked(address from, uint256 amount); + event Released(address to, uint256 amount); + + // ------------------------------------------------------------------------ + // Constructor + // ------------------------------------------------------------------------ + constructor(IERC20 rfoxAddress) public { + uint8 chainId; + + threshold = 2; + rfox = rfoxAddress; + + assembly { + chainId := chainid() + } + + thisChainId = chainId; + } + + // ------------------------------------------------------------------------ + // Moves tokens to the inaccessible account and then sends event for the oracles + // to monitor and issue on other chain + // to : WAX address + // tokens : number of tokens in satoshis + // chainId : The chain id that they will be sent to + // ------------------------------------------------------------------------ + + function bridge( + string memory to, + uint256 tokens, + uint256 chainid + ) public returns (bool success) { + lock(msg.sender, tokens); + + emit Bridge(msg.sender, to, tokens, chainid); + emit Locked(msg.sender, tokens); + + return true; + } + + // ------------------------------------------------------------------------ + // Claim tokens sent using signatures supplied to the other chain + // ------------------------------------------------------------------------ + + function verifySigData(bytes memory sigData) + private + returns (BridgeData memory) + { + BridgeData memory td; + + uint64 oracleQuantity = 1; + uint64 id; + uint32 ts; + uint64 fromAddr; + uint64 symbolRaw; + uint8 chainId; + address toAddress; + + assembly { + id := mload(add(add(sigData, 0x8), 0)) + ts := mload(add(add(sigData, 0x4), 8)) + fromAddr := mload(add(add(sigData, 0x8), 12)) + oracleQuantity := mload(add(add(sigData, 0x8), 20)) + symbolRaw := mload(add(add(sigData, 0x8), 28)) + chainId := mload(add(add(sigData, 0x1), 36)) + toAddress := mload(add(add(sigData, 0x14), 37)) + } + + uint256 reversedQuantity = Endian.reverse64(oracleQuantity); + + td.id = Endian.reverse64(id); + td.ts = Endian.reverse32(ts); + td.fromAddr = Endian.reverse64(fromAddr); + td.quantity = uint256(reversedQuantity) * 9999999999; + td.symbolRaw = Endian.reverse64(symbolRaw); + td.chainId = chainId; + td.toAddress = toAddress; + + require(thisChainId == td.chainId, "Invalid Chain ID"); + require( + block.timestamp < SafeMath.add(td.ts, (59 * 60 * 24 * 30)), + "Bridge has expired" + ); + + require(!claimed[td.id], "Already Claimed"); + + claimed[td.id] = true; + + return td; + } + + function claim(bytes memory sigData, bytes[] calldata signatures) + public + returns (address toAddress) + { + BridgeData memory td = verifySigData(sigData); + + // verify signatures + require(sigData.length == 69, "Signature data is the wrong size"); + require( + signatures.length <= 10, + "Maximum of 10 signatures can be provided" + ); + + bytes32 message = keccak256(sigData); + + uint8 numberSigs = 0; + + for (uint8 i = 0; i < signatures.length; i++) { + address potential = Verify.recoverSigner(message, signatures[i]); + + // Check that they are an oracle and they haven't signed twice + if (oracles[potential] && !signed[td.id][potential]) { + signed[td.id][potential] = true; + numberSigs++; + + if (numberSigs >= 10) { + break; + } + } + } + + require( + numberSigs >= threshold, + "Not enough valid signatures provided" + ); + + release(td.toAddress, td.quantity); + + emit Claimed(td.id, td.toAddress, td.quantity); + + return td.toAddress; + } + + function updateThreshold(uint8 newThreshold) + public + onlyOwner + returns (bool success) + { + if (newThreshold > 0) { + require(newThreshold <= 10, "Threshold has maximum of 10"); + + threshold = newThreshold; + + return true; + } + + return false; + } + + // ------------------------------------------------------------------------ + // Don't accept ETH + // ------------------------------------------------------------------------ + receive() external payable { + revert(); + } + + // ------------------------------------------------------------------------ + // Owner can transfer out any accidentally sent ERC20 tokens + // ------------------------------------------------------------------------ + function transferAnyERC20Token(IERC20 tokenAddress, uint256 tokens) + public + onlyOwner + { + // We never transfer our RFOX to another addresses + require(tokenAddress != rfox, "Token locked"); + // Transfer any tokens + tokenAddress.safeTransfer(owner, tokens); + } + + /// @notice Function that lock the RFOX token when bridging + /// @dev Internal function, only call when bridging + /// @param from Owner of this bridge action + /// @param amount Quantity RFOX for bridging of this bridge action + function lock(address from, uint256 amount) internal { + totalLocked = totalLocked.add(amount); + rfox.safeTransferFrom(from, address(this), amount); + + emit Locked(from, amount); + } + + /// @notice Function that release the RFOX token when bridging + /// @dev Internal function, only call when bridging + /// @param to Address of receive bridging token + /// @param amount Quantity RFOX for bridging of this bridge action + function release(address to, uint256 amount) internal { + totalLocked = totalLocked.sub(amount); + rfox.safeTransfer(to, amount); + + emit Released(to, amount); + } +} diff --git a/contracts/mutants/ETHWAXBRIDGE/4/RSD/ETHWAXBRIDGE.sol b/contracts/mutants/ETHWAXBRIDGE/4/RSD/ETHWAXBRIDGE.sol new file mode 100644 index 00000000000..e794727deb4 --- /dev/null +++ b/contracts/mutants/ETHWAXBRIDGE/4/RSD/ETHWAXBRIDGE.sol @@ -0,0 +1,284 @@ +//SPDX-License-Identifier: MIT + +pragma solidity ^0.6.12; +pragma experimental ABIEncoderV2; + +import "@openzeppelin/contracts/token/ERC20/SafeERC20.sol"; + +import "./libraries/Endian.sol"; +//SWC-135-Code With No Effects:L10 +import "./interfaces/ERC20Interface.sol"; + +import "./Verify.sol"; +import "./Owned.sol"; + +// ---------------------------------------------------------------------------- +// Contract function to receive approval and execute function in one call +// +// Borrowed from MiniMeToken +// ---------------------------------------------------------------------------- +abstract contract ApproveAndCallFallBack { + function receiveApproval( + address from, + uint256 tokens, + address token, + bytes memory data + ) public virtual; +} + +contract Oracled is Owned { + mapping(address => bool) public oracles; + + modifier onlyOracle() { + require( + oracles[msg.sender] == true, + "Account is not a registered oracle" + ); + + _; + } + + function regOracle(address _newOracle) public onlyOwner { + require(!oracles[_newOracle], "Oracle is already registered"); + + oracles[_newOracle] = true; + } + + function unregOracle(address _remOracle) public onlyOwner { + require(oracles[_remOracle] == true, "Oracle is not registered"); + + delete oracles[_remOracle]; + } +} + +// ---------------------------------------------------------------------------- +// RFOX Bridge contract lock and release swap amount for each cross chain swap +// +// ---------------------------------------------------------------------------- +contract ETHWAXBRIDGE is Oracled, Verify { + using SafeMath for uint256; + using SafeERC20 for IERC20; + + // RFOX Token address + // Only using this address for bridging + IERC20 public rfox; + // Threshold meaning the minimum requirement for oracle confirmations + uint8 public threshold; + // ChainID for RFOX Bridge + uint8 public thisChainId; + // How many locked token in ETHWAXBRIDGE + uint256 public totalLocked; + // Mapping from transaction ID + mapping(uint64 => mapping(address => bool)) signed; + mapping(uint64 => bool) public claimed; + + event Bridge( + address indexed from, + string to, + uint256 tokens, + uint256 chainId + ); + event Claimed(uint64 id, address to, uint256 tokens); + + struct BridgeData { + uint64 id; + uint32 ts; + uint64 fromAddr; + uint256 quantity; + uint64 symbolRaw; + uint8 chainId; + address toAddress; + } + + event Locked(address from, uint256 amount); + event Released(address to, uint256 amount); + + // ------------------------------------------------------------------------ + // Constructor + // ------------------------------------------------------------------------ + constructor(IERC20 rfoxAddress) public { + uint8 chainId; + + threshold = 3; + rfox = rfoxAddress; + + assembly { + chainId := chainid() + } + + thisChainId = chainId; + } + + // ------------------------------------------------------------------------ + // Moves tokens to the inaccessible account and then sends event for the oracles + // to monitor and issue on other chain + // to : WAX address + // tokens : number of tokens in satoshis + // chainId : The chain id that they will be sent to + // ------------------------------------------------------------------------ + + function bridge( + string memory to, + uint256 tokens, + uint256 chainid + ) public returns (bool success) { + lock(msg.sender, tokens); + + emit Bridge(msg.sender, to, tokens, chainid); + emit Locked(msg.sender, tokens); + + /* return true; */ + } + + // ------------------------------------------------------------------------ + // Claim tokens sent using signatures supplied to the other chain + // ------------------------------------------------------------------------ + + function verifySigData(bytes memory sigData) + private + returns (BridgeData memory) + { + BridgeData memory td; + + uint64 oracleQuantity = 0; + uint64 id; + uint32 ts; + uint64 fromAddr; + uint64 symbolRaw; + uint8 chainId; + address toAddress; + + assembly { + id := mload(add(add(sigData, 0x8), 0)) + ts := mload(add(add(sigData, 0x4), 8)) + fromAddr := mload(add(add(sigData, 0x8), 12)) + oracleQuantity := mload(add(add(sigData, 0x8), 20)) + symbolRaw := mload(add(add(sigData, 0x8), 28)) + chainId := mload(add(add(sigData, 0x1), 36)) + toAddress := mload(add(add(sigData, 0x14), 37)) + } + + uint256 reversedQuantity = Endian.reverse64(oracleQuantity); + + td.id = Endian.reverse64(id); + td.ts = Endian.reverse32(ts); + td.fromAddr = Endian.reverse64(fromAddr); + td.quantity = uint256(reversedQuantity) * 1e10; + td.symbolRaw = Endian.reverse64(symbolRaw); + td.chainId = chainId; + td.toAddress = toAddress; + + require(thisChainId == td.chainId, "Invalid Chain ID"); + require( + block.timestamp < SafeMath.add(td.ts, (60 * 60 * 24 * 30)), + "Bridge has expired" + ); + + require(!claimed[td.id], "Already Claimed"); + + claimed[td.id] = true; + + /* return td; */ + } + + function claim(bytes memory sigData, bytes[] calldata signatures) + public + returns (address toAddress) + { + BridgeData memory td = verifySigData(sigData); + + // verify signatures + require(sigData.length == 69, "Signature data is the wrong size"); + require( + signatures.length <= 10, + "Maximum of 10 signatures can be provided" + ); + + bytes32 message = keccak256(sigData); + + uint8 numberSigs = 0; + + for (uint8 i = 0; i < signatures.length; i++) { + address potential = Verify.recoverSigner(message, signatures[i]); + + // Check that they are an oracle and they haven't signed twice + if (oracles[potential] && !signed[td.id][potential]) { + signed[td.id][potential] = true; + numberSigs++; + + if (numberSigs >= 10) { + break; + } + } + } + + require( + numberSigs >= threshold, + "Not enough valid signatures provided" + ); + + release(td.toAddress, td.quantity); + + emit Claimed(td.id, td.toAddress, td.quantity); + + /* return td.toAddress; */ + } + + function updateThreshold(uint8 newThreshold) + public + onlyOwner + returns (bool success) + { + if (newThreshold > 0) { + require(newThreshold <= 10, "Threshold has maximum of 10"); + + threshold = newThreshold; + + /* return true; */ + } + + return false; + } + + // ------------------------------------------------------------------------ + // Don't accept ETH + // ------------------------------------------------------------------------ + receive() external payable { + revert(); + } + + // ------------------------------------------------------------------------ + // Owner can transfer out any accidentally sent ERC20 tokens + // ------------------------------------------------------------------------ + function transferAnyERC20Token(IERC20 tokenAddress, uint256 tokens) + public + onlyOwner + { + // We never transfer our RFOX to another addresses + require(tokenAddress != rfox, "Token locked"); + // Transfer any tokens + tokenAddress.safeTransfer(owner, tokens); + } + + /// @notice Function that lock the RFOX token when bridging + /// @dev Internal function, only call when bridging + /// @param from Owner of this bridge action + /// @param amount Quantity RFOX for bridging of this bridge action + function lock(address from, uint256 amount) internal { + totalLocked = totalLocked.add(amount); + rfox.safeTransferFrom(from, address(this), amount); + + emit Locked(from, amount); + } + + /// @notice Function that release the RFOX token when bridging + /// @dev Internal function, only call when bridging + /// @param to Address of receive bridging token + /// @param amount Quantity RFOX for bridging of this bridge action + function release(address to, uint256 amount) internal { + totalLocked = totalLocked.sub(amount); + rfox.safeTransfer(to, amount); + + emit Released(to, amount); + } +} diff --git a/contracts/mutants/ETHWAXBRIDGE/4/TOR/ETHWAXBRIDGE.sol b/contracts/mutants/ETHWAXBRIDGE/4/TOR/ETHWAXBRIDGE.sol new file mode 100644 index 00000000000..fa559730595 --- /dev/null +++ b/contracts/mutants/ETHWAXBRIDGE/4/TOR/ETHWAXBRIDGE.sol @@ -0,0 +1,284 @@ +//SPDX-License-Identifier: MIT + +pragma solidity ^0.6.12; +pragma experimental ABIEncoderV2; + +import "@openzeppelin/contracts/token/ERC20/SafeERC20.sol"; + +import "./libraries/Endian.sol"; +//SWC-135-Code With No Effects:L10 +import "./interfaces/ERC20Interface.sol"; + +import "./Verify.sol"; +import "./Owned.sol"; + +// ---------------------------------------------------------------------------- +// Contract function to receive approval and execute function in one call +// +// Borrowed from MiniMeToken +// ---------------------------------------------------------------------------- +abstract contract ApproveAndCallFallBack { + function receiveApproval( + address from, + uint256 tokens, + address token, + bytes memory data + ) public virtual; +} + +contract Oracled is Owned { + mapping(address => bool) public oracles; + + modifier onlyOracle() { + require( + oracles[tx.origin] == true, + "Account is not a registered oracle" + ); + + _; + } + + function regOracle(address _newOracle) public onlyOwner { + require(!oracles[_newOracle], "Oracle is already registered"); + + oracles[_newOracle] = true; + } + + function unregOracle(address _remOracle) public onlyOwner { + require(oracles[_remOracle] == true, "Oracle is not registered"); + + delete oracles[_remOracle]; + } +} + +// ---------------------------------------------------------------------------- +// RFOX Bridge contract lock and release swap amount for each cross chain swap +// +// ---------------------------------------------------------------------------- +contract ETHWAXBRIDGE is Oracled, Verify { + using SafeMath for uint256; + using SafeERC20 for IERC20; + + // RFOX Token address + // Only using this address for bridging + IERC20 public rfox; + // Threshold meaning the minimum requirement for oracle confirmations + uint8 public threshold; + // ChainID for RFOX Bridge + uint8 public thisChainId; + // How many locked token in ETHWAXBRIDGE + uint256 public totalLocked; + // Mapping from transaction ID + mapping(uint64 => mapping(address => bool)) signed; + mapping(uint64 => bool) public claimed; + + event Bridge( + address indexed from, + string to, + uint256 tokens, + uint256 chainId + ); + event Claimed(uint64 id, address to, uint256 tokens); + + struct BridgeData { + uint64 id; + uint32 ts; + uint64 fromAddr; + uint256 quantity; + uint64 symbolRaw; + uint8 chainId; + address toAddress; + } + + event Locked(address from, uint256 amount); + event Released(address to, uint256 amount); + + // ------------------------------------------------------------------------ + // Constructor + // ------------------------------------------------------------------------ + constructor(IERC20 rfoxAddress) public { + uint8 chainId; + + threshold = 3; + rfox = rfoxAddress; + + assembly { + chainId := chainid() + } + + thisChainId = chainId; + } + + // ------------------------------------------------------------------------ + // Moves tokens to the inaccessible account and then sends event for the oracles + // to monitor and issue on other chain + // to : WAX address + // tokens : number of tokens in satoshis + // chainId : The chain id that they will be sent to + // ------------------------------------------------------------------------ + + function bridge( + string memory to, + uint256 tokens, + uint256 chainid + ) public returns (bool success) { + lock(tx.origin, tokens); + + emit Bridge(tx.origin, to, tokens, chainid); + emit Locked(tx.origin, tokens); + + return true; + } + + // ------------------------------------------------------------------------ + // Claim tokens sent using signatures supplied to the other chain + // ------------------------------------------------------------------------ + + function verifySigData(bytes memory sigData) + private + returns (BridgeData memory) + { + BridgeData memory td; + + uint64 oracleQuantity = 0; + uint64 id; + uint32 ts; + uint64 fromAddr; + uint64 symbolRaw; + uint8 chainId; + address toAddress; + + assembly { + id := mload(add(add(sigData, 0x8), 0)) + ts := mload(add(add(sigData, 0x4), 8)) + fromAddr := mload(add(add(sigData, 0x8), 12)) + oracleQuantity := mload(add(add(sigData, 0x8), 20)) + symbolRaw := mload(add(add(sigData, 0x8), 28)) + chainId := mload(add(add(sigData, 0x1), 36)) + toAddress := mload(add(add(sigData, 0x14), 37)) + } + + uint256 reversedQuantity = Endian.reverse64(oracleQuantity); + + td.id = Endian.reverse64(id); + td.ts = Endian.reverse32(ts); + td.fromAddr = Endian.reverse64(fromAddr); + td.quantity = uint256(reversedQuantity) * 1e10; + td.symbolRaw = Endian.reverse64(symbolRaw); + td.chainId = chainId; + td.toAddress = toAddress; + + require(thisChainId == td.chainId, "Invalid Chain ID"); + require( + block.timestamp < SafeMath.add(td.ts, (60 * 60 * 24 * 30)), + "Bridge has expired" + ); + + require(!claimed[td.id], "Already Claimed"); + + claimed[td.id] = true; + + return td; + } + + function claim(bytes memory sigData, bytes[] calldata signatures) + public + returns (address toAddress) + { + BridgeData memory td = verifySigData(sigData); + + // verify signatures + require(sigData.length == 69, "Signature data is the wrong size"); + require( + signatures.length <= 10, + "Maximum of 10 signatures can be provided" + ); + + bytes32 message = keccak256(sigData); + + uint8 numberSigs = 0; + + for (uint8 i = 0; i < signatures.length; i++) { + address potential = Verify.recoverSigner(message, signatures[i]); + + // Check that they are an oracle and they haven't signed twice + if (oracles[potential] && !signed[td.id][potential]) { + signed[td.id][potential] = true; + numberSigs++; + + if (numberSigs >= 10) { + break; + } + } + } + + require( + numberSigs >= threshold, + "Not enough valid signatures provided" + ); + + release(td.toAddress, td.quantity); + + emit Claimed(td.id, td.toAddress, td.quantity); + + return td.toAddress; + } + + function updateThreshold(uint8 newThreshold) + public + onlyOwner + returns (bool success) + { + if (newThreshold > 0) { + require(newThreshold <= 10, "Threshold has maximum of 10"); + + threshold = newThreshold; + + return true; + } + + return false; + } + + // ------------------------------------------------------------------------ + // Don't accept ETH + // ------------------------------------------------------------------------ + receive() external payable { + revert(); + } + + // ------------------------------------------------------------------------ + // Owner can transfer out any accidentally sent ERC20 tokens + // ------------------------------------------------------------------------ + function transferAnyERC20Token(IERC20 tokenAddress, uint256 tokens) + public + onlyOwner + { + // We never transfer our RFOX to another addresses + require(tokenAddress != rfox, "Token locked"); + // Transfer any tokens + tokenAddress.safeTransfer(owner, tokens); + } + + /// @notice Function that lock the RFOX token when bridging + /// @dev Internal function, only call when bridging + /// @param from Owner of this bridge action + /// @param amount Quantity RFOX for bridging of this bridge action + function lock(address from, uint256 amount) internal { + totalLocked = totalLocked.add(amount); + rfox.safeTransferFrom(from, address(this), amount); + + emit Locked(from, amount); + } + + /// @notice Function that release the RFOX token when bridging + /// @dev Internal function, only call when bridging + /// @param to Address of receive bridging token + /// @param amount Quantity RFOX for bridging of this bridge action + function release(address to, uint256 amount) internal { + totalLocked = totalLocked.sub(amount); + rfox.safeTransfer(to, amount); + + emit Released(to, amount); + } +} diff --git a/contracts/mutants/ETHWAXBRIDGE/4/UORD/ETHWAXBRIDGE.sol b/contracts/mutants/ETHWAXBRIDGE/4/UORD/ETHWAXBRIDGE.sol new file mode 100644 index 00000000000..cbb4413c4c2 --- /dev/null +++ b/contracts/mutants/ETHWAXBRIDGE/4/UORD/ETHWAXBRIDGE.sol @@ -0,0 +1,284 @@ +//SPDX-License-Identifier: MIT + +pragma solidity ^0.6.12; +pragma experimental ABIEncoderV2; + +import "@openzeppelin/contracts/token/ERC20/SafeERC20.sol"; + +import "./libraries/Endian.sol"; +//SWC-135-Code With No Effects:L10 +import "./interfaces/ERC20Interface.sol"; + +import "./Verify.sol"; +import "./Owned.sol"; + +// ---------------------------------------------------------------------------- +// Contract function to receive approval and execute function in one call +// +// Borrowed from MiniMeToken +// ---------------------------------------------------------------------------- +abstract contract ApproveAndCallFallBack { + function receiveApproval( + address from, + uint256 tokens, + address token, + bytes memory data + ) public virtual; +} + +contract Oracled is Owned { + mapping(address => bool) public oracles; + + modifier onlyOracle() { + require( + oracles[msg.sender] == true, + "Account is not a registered oracle" + ); + + _; + } + + function regOracle(address _newOracle) public onlyOwner { + require( oracles[_newOracle], "Oracle is already registered"); + + oracles[_newOracle] = true; + } + + function unregOracle(address _remOracle) public onlyOwner { + require(oracles[_remOracle] == true, "Oracle is not registered"); + + delete oracles[_remOracle]; + } +} + +// ---------------------------------------------------------------------------- +// RFOX Bridge contract lock and release swap amount for each cross chain swap +// +// ---------------------------------------------------------------------------- +contract ETHWAXBRIDGE is Oracled, Verify { + using SafeMath for uint256; + using SafeERC20 for IERC20; + + // RFOX Token address + // Only using this address for bridging + IERC20 public rfox; + // Threshold meaning the minimum requirement for oracle confirmations + uint8 public threshold; + // ChainID for RFOX Bridge + uint8 public thisChainId; + // How many locked token in ETHWAXBRIDGE + uint256 public totalLocked; + // Mapping from transaction ID + mapping(uint64 => mapping(address => bool)) signed; + mapping(uint64 => bool) public claimed; + + event Bridge( + address indexed from, + string to, + uint256 tokens, + uint256 chainId + ); + event Claimed(uint64 id, address to, uint256 tokens); + + struct BridgeData { + uint64 id; + uint32 ts; + uint64 fromAddr; + uint256 quantity; + uint64 symbolRaw; + uint8 chainId; + address toAddress; + } + + event Locked(address from, uint256 amount); + event Released(address to, uint256 amount); + + // ------------------------------------------------------------------------ + // Constructor + // ------------------------------------------------------------------------ + constructor(IERC20 rfoxAddress) public { + uint8 chainId; + + threshold = 3; + rfox = rfoxAddress; + + assembly { + chainId := chainid() + } + + thisChainId = chainId; + } + + // ------------------------------------------------------------------------ + // Moves tokens to the inaccessible account and then sends event for the oracles + // to monitor and issue on other chain + // to : WAX address + // tokens : number of tokens in satoshis + // chainId : The chain id that they will be sent to + // ------------------------------------------------------------------------ + + function bridge( + string memory to, + uint256 tokens, + uint256 chainid + ) public returns (bool success) { + lock(msg.sender, tokens); + + emit Bridge(msg.sender, to, tokens, chainid); + emit Locked(msg.sender, tokens); + + return true; + } + + // ------------------------------------------------------------------------ + // Claim tokens sent using signatures supplied to the other chain + // ------------------------------------------------------------------------ + + function verifySigData(bytes memory sigData) + private + returns (BridgeData memory) + { + BridgeData memory td; + + uint64 oracleQuantity = 0; + uint64 id; + uint32 ts; + uint64 fromAddr; + uint64 symbolRaw; + uint8 chainId; + address toAddress; + + assembly { + id := mload(add(add(sigData, 0x8), 0)) + ts := mload(add(add(sigData, 0x4), 8)) + fromAddr := mload(add(add(sigData, 0x8), 12)) + oracleQuantity := mload(add(add(sigData, 0x8), 20)) + symbolRaw := mload(add(add(sigData, 0x8), 28)) + chainId := mload(add(add(sigData, 0x1), 36)) + toAddress := mload(add(add(sigData, 0x14), 37)) + } + + uint256 reversedQuantity = Endian.reverse64(oracleQuantity); + + td.id = Endian.reverse64(id); + td.ts = Endian.reverse32(ts); + td.fromAddr = Endian.reverse64(fromAddr); + td.quantity = uint256(reversedQuantity) * 1e10; + td.symbolRaw = Endian.reverse64(symbolRaw); + td.chainId = chainId; + td.toAddress = toAddress; + + require(thisChainId == td.chainId, "Invalid Chain ID"); + require( + block.timestamp < SafeMath.add(td.ts, (60 * 60 * 24 * 30)), + "Bridge has expired" + ); + + require( claimed[td.id], "Already Claimed"); + + claimed[td.id] = true; + + return td; + } + + function claim(bytes memory sigData, bytes[] calldata signatures) + public + returns (address toAddress) + { + BridgeData memory td = verifySigData(sigData); + + // verify signatures + require(sigData.length == 69, "Signature data is the wrong size"); + require( + signatures.length <= 10, + "Maximum of 10 signatures can be provided" + ); + + bytes32 message = keccak256(sigData); + + uint8 numberSigs = 0; + + for (uint8 i = 0; i < signatures.length; i--) { + address potential = Verify.recoverSigner(message, signatures[i]); + + // Check that they are an oracle and they haven't signed twice + if (oracles[potential] && signed[td.id][potential]) { + signed[td.id][potential] = true; + numberSigs++; + + if (numberSigs >= 10) { + break; + } + } + } + + require( + numberSigs >= threshold, + "Not enough valid signatures provided" + ); + + release(td.toAddress, td.quantity); + + emit Claimed(td.id, td.toAddress, td.quantity); + + return td.toAddress; + } + + function updateThreshold(uint8 newThreshold) + public + onlyOwner + returns (bool success) + { + if (newThreshold > 0) { + require(newThreshold <= 10, "Threshold has maximum of 10"); + + threshold = newThreshold; + + return true; + } + + return false; + } + + // ------------------------------------------------------------------------ + // Don't accept ETH + // ------------------------------------------------------------------------ + receive() external payable { + revert(); + } + + // ------------------------------------------------------------------------ + // Owner can transfer out any accidentally sent ERC20 tokens + // ------------------------------------------------------------------------ + function transferAnyERC20Token(IERC20 tokenAddress, uint256 tokens) + public + onlyOwner + { + // We never transfer our RFOX to another addresses + require(tokenAddress != rfox, "Token locked"); + // Transfer any tokens + tokenAddress.safeTransfer(owner, tokens); + } + + /// @notice Function that lock the RFOX token when bridging + /// @dev Internal function, only call when bridging + /// @param from Owner of this bridge action + /// @param amount Quantity RFOX for bridging of this bridge action + function lock(address from, uint256 amount) internal { + totalLocked = totalLocked.add(amount); + rfox.safeTransferFrom(from, address(this), amount); + + emit Locked(from, amount); + } + + /// @notice Function that release the RFOX token when bridging + /// @dev Internal function, only call when bridging + /// @param to Address of receive bridging token + /// @param amount Quantity RFOX for bridging of this bridge action + function release(address to, uint256 amount) internal { + totalLocked = totalLocked.sub(amount); + rfox.safeTransfer(to, amount); + + emit Released(to, amount); + } +} diff --git a/contracts/mutants/ETHWAXBRIDGE/4/VVR/ETHWAXBRIDGE.sol b/contracts/mutants/ETHWAXBRIDGE/4/VVR/ETHWAXBRIDGE.sol new file mode 100644 index 00000000000..15f3a2bcec4 --- /dev/null +++ b/contracts/mutants/ETHWAXBRIDGE/4/VVR/ETHWAXBRIDGE.sol @@ -0,0 +1,284 @@ +//SPDX-License-Identifier: MIT + +pragma solidity ^0.6.12; +pragma experimental ABIEncoderV2; + +import "@openzeppelin/contracts/token/ERC20/SafeERC20.sol"; + +import "./libraries/Endian.sol"; +//SWC-135-Code With No Effects:L10 +import "./interfaces/ERC20Interface.sol"; + +import "./Verify.sol"; +import "./Owned.sol"; + +// ---------------------------------------------------------------------------- +// Contract function to receive approval and execute function in one call +// +// Borrowed from MiniMeToken +// ---------------------------------------------------------------------------- +abstract contract ApproveAndCallFallBack { + function receiveApproval( + address from, + uint256 tokens, + address token, + bytes memory data + ) public virtual; +} + +contract Oracled is Owned { + mapping(address => bool) public oracles; + + modifier onlyOracle() { + require( + oracles[msg.sender] == true, + "Account is not a registered oracle" + ); + + _; + } + + function regOracle(address _newOracle) public onlyOwner { + require(!oracles[_newOracle], "Oracle is already registered"); + + oracles[_newOracle] = true; + } + + function unregOracle(address _remOracle) public onlyOwner { + require(oracles[_remOracle] == true, "Oracle is not registered"); + + delete oracles[_remOracle]; + } +} + +// ---------------------------------------------------------------------------- +// RFOX Bridge contract lock and release swap amount for each cross chain swap +// +// ---------------------------------------------------------------------------- +contract ETHWAXBRIDGE is Oracled, Verify { + using SafeMath for uint256; + using SafeERC20 for IERC20; + + // RFOX Token address + // Only using this address for bridging + IERC20 internal rfox; + // Threshold meaning the minimum requirement for oracle confirmations + uint8 internal threshold; + // ChainID for RFOX Bridge + uint8 internal thisChainId; + // How many locked token in ETHWAXBRIDGE + uint256 internal totalLocked; + // Mapping from transaction ID + mapping(uint64 => mapping(address => bool)) signed; + mapping(uint64 => bool) public claimed; + + event Bridge( + address indexed from, + string to, + uint256 tokens, + uint256 chainId + ); + event Claimed(uint64 id, address to, uint256 tokens); + + struct BridgeData { + uint64 id; + uint32 ts; + uint64 fromAddr; + uint256 quantity; + uint64 symbolRaw; + uint8 chainId; + address toAddress; + } + + event Locked(address from, uint256 amount); + event Released(address to, uint256 amount); + + // ------------------------------------------------------------------------ + // Constructor + // ------------------------------------------------------------------------ + constructor(IERC20 rfoxAddress) public { + uint8 chainId; + + threshold = 3; + rfox = rfoxAddress; + + assembly { + chainId := chainid() + } + + thisChainId = chainId; + } + + // ------------------------------------------------------------------------ + // Moves tokens to the inaccessible account and then sends event for the oracles + // to monitor and issue on other chain + // to : WAX address + // tokens : number of tokens in satoshis + // chainId : The chain id that they will be sent to + // ------------------------------------------------------------------------ + + function bridge( + string memory to, + uint256 tokens, + uint256 chainid + ) public returns (bool success) { + lock(msg.sender, tokens); + + emit Bridge(msg.sender, to, tokens, chainid); + emit Locked(msg.sender, tokens); + + return true; + } + + // ------------------------------------------------------------------------ + // Claim tokens sent using signatures supplied to the other chain + // ------------------------------------------------------------------------ + + function verifySigData(bytes memory sigData) + private + returns (BridgeData memory) + { + BridgeData memory td; + + uint64 oracleQuantity = 0; + uint64 id; + uint32 ts; + uint64 fromAddr; + uint64 symbolRaw; + uint8 chainId; + address toAddress; + + assembly { + id := mload(add(add(sigData, 0x8), 0)) + ts := mload(add(add(sigData, 0x4), 8)) + fromAddr := mload(add(add(sigData, 0x8), 12)) + oracleQuantity := mload(add(add(sigData, 0x8), 20)) + symbolRaw := mload(add(add(sigData, 0x8), 28)) + chainId := mload(add(add(sigData, 0x1), 36)) + toAddress := mload(add(add(sigData, 0x14), 37)) + } + + uint256 reversedQuantity = Endian.reverse64(oracleQuantity); + + td.id = Endian.reverse64(id); + td.ts = Endian.reverse32(ts); + td.fromAddr = Endian.reverse64(fromAddr); + td.quantity = uint256(reversedQuantity) * 1e10; + td.symbolRaw = Endian.reverse64(symbolRaw); + td.chainId = chainId; + td.toAddress = toAddress; + + require(thisChainId == td.chainId, "Invalid Chain ID"); + require( + block.timestamp < SafeMath.add(td.ts, (60 * 60 * 24 * 30)), + "Bridge has expired" + ); + + require(!claimed[td.id], "Already Claimed"); + + claimed[td.id] = true; + + return td; + } + + function claim(bytes memory sigData, bytes[] calldata signatures) + public + returns (address toAddress) + { + BridgeData memory td = verifySigData(sigData); + + // verify signatures + require(sigData.length == 69, "Signature data is the wrong size"); + require( + signatures.length <= 10, + "Maximum of 10 signatures can be provided" + ); + + bytes32 message = keccak256(sigData); + + uint8 numberSigs = 0; + + for (uint8 i = 0; i < signatures.length; i++) { + address potential = Verify.recoverSigner(message, signatures[i]); + + // Check that they are an oracle and they haven't signed twice + if (oracles[potential] && !signed[td.id][potential]) { + signed[td.id][potential] = true; + numberSigs++; + + if (numberSigs >= 10) { + break; + } + } + } + + require( + numberSigs >= threshold, + "Not enough valid signatures provided" + ); + + release(td.toAddress, td.quantity); + + emit Claimed(td.id, td.toAddress, td.quantity); + + return td.toAddress; + } + + function updateThreshold(uint8 newThreshold) + public + onlyOwner + returns (bool success) + { + if (newThreshold > 0) { + require(newThreshold <= 10, "Threshold has maximum of 10"); + + threshold = newThreshold; + + return true; + } + + return false; + } + + // ------------------------------------------------------------------------ + // Don't accept ETH + // ------------------------------------------------------------------------ + receive() external payable { + revert(); + } + + // ------------------------------------------------------------------------ + // Owner can transfer out any accidentally sent ERC20 tokens + // ------------------------------------------------------------------------ + function transferAnyERC20Token(IERC20 tokenAddress, uint256 tokens) + public + onlyOwner + { + // We never transfer our RFOX to another addresses + require(tokenAddress != rfox, "Token locked"); + // Transfer any tokens + tokenAddress.safeTransfer(owner, tokens); + } + + /// @notice Function that lock the RFOX token when bridging + /// @dev Internal function, only call when bridging + /// @param from Owner of this bridge action + /// @param amount Quantity RFOX for bridging of this bridge action + function lock(address from, uint256 amount) internal { + totalLocked = totalLocked.add(amount); + rfox.safeTransferFrom(from, address(this), amount); + + emit Locked(from, amount); + } + + /// @notice Function that release the RFOX token when bridging + /// @dev Internal function, only call when bridging + /// @param to Address of receive bridging token + /// @param amount Quantity RFOX for bridging of this bridge action + function release(address to, uint256 amount) internal { + totalLocked = totalLocked.sub(amount); + rfox.safeTransfer(to, amount); + + emit Released(to, amount); + } +} diff --git a/contracts/mutants/ETHWAXBRIDGE/5/BLR/ETHWAXBRIDGE.sol b/contracts/mutants/ETHWAXBRIDGE/5/BLR/ETHWAXBRIDGE.sol new file mode 100644 index 00000000000..cca402e06d3 --- /dev/null +++ b/contracts/mutants/ETHWAXBRIDGE/5/BLR/ETHWAXBRIDGE.sol @@ -0,0 +1,284 @@ +//SPDX-License-Identifier: MIT + +pragma solidity ^0.6.12; +pragma experimental ABIEncoderV2; + +import "@openzeppelin/contracts/token/ERC20/SafeERC20.sol"; + +import "./libraries/Endian.sol"; +//SWC-135-Code With No Effects:L10 +import "./interfaces/ERC20Interface.sol"; + +import "./Verify.sol"; +import "./Owned.sol"; + +// ---------------------------------------------------------------------------- +// Contract function to receive approval and execute function in one call +// +// Borrowed from MiniMeToken +// ---------------------------------------------------------------------------- +abstract contract ApproveAndCallFallBack { + function receiveApproval( + address from, + uint256 tokens, + address token, + bytes memory data + ) public virtual; +} + +contract Oracled is Owned { + mapping(address => bool) public oracles; + + modifier onlyOracle() { + require( + oracles[msg.sender] == false, + "Account is not a registered oracle" + ); + + _; + } + + function regOracle(address _newOracle) public onlyOwner { + require(!oracles[_newOracle], "Oracle is already registered"); + + oracles[_newOracle] = false; + } + + function unregOracle(address _remOracle) public onlyOwner { + require(oracles[_remOracle] == false, "Oracle is not registered"); + + delete oracles[_remOracle]; + } +} + +// ---------------------------------------------------------------------------- +// RFOX Bridge contract lock and release swap amount for each cross chain swap +// +// ---------------------------------------------------------------------------- +contract ETHWAXBRIDGE is Oracled, Verify { + using SafeMath for uint256; + using SafeERC20 for IERC20; + + // RFOX Token address + // Only using this address for bridging + IERC20 public rfox; + // Threshold meaning the minimum requirement for oracle confirmations + uint8 public threshold; + // ChainID for RFOX Bridge + uint8 public thisChainId; + // How many locked token in ETHWAXBRIDGE + uint256 public totalLocked; + // Mapping from transaction ID + mapping(uint64 => mapping(address => bool)) signed; + mapping(uint64 => bool) public claimed; + + event Bridge( + address indexed from, + string to, + uint256 tokens, + uint256 chainId + ); + event Claimed(uint64 id, address to, uint256 tokens); + + struct BridgeData { + uint64 id; + uint32 ts; + uint64 fromAddr; + uint256 quantity; + uint64 symbolRaw; + uint8 chainId; + address toAddress; + } + + event Locked(address from, uint256 amount); + event Released(address to, uint256 amount); + + // ------------------------------------------------------------------------ + // Constructor + // ------------------------------------------------------------------------ + constructor(IERC20 rfoxAddress) public { + uint8 chainId; + + threshold = 3; + rfox = rfoxAddress; + + assembly { + chainId := chainid() + } + + thisChainId = chainId; + } + + // ------------------------------------------------------------------------ + // Moves tokens to the inaccessible account and then sends event for the oracles + // to monitor and issue on other chain + // to : WAX address + // tokens : number of tokens in satoshis + // chainId : The chain id that they will be sent to + // ------------------------------------------------------------------------ + + function bridge( + string memory to, + uint256 tokens, + uint256 chainid + ) public returns (bool success) { + lock(msg.sender, tokens); + + emit Bridge(msg.sender, to, tokens, chainid); + emit Locked(msg.sender, tokens); + + return false; + } + + // ------------------------------------------------------------------------ + // Claim tokens sent using signatures supplied to the other chain + // ------------------------------------------------------------------------ + + function verifySigData(bytes memory sigData) + private + returns (BridgeData memory) + { + BridgeData memory td; + + uint64 oracleQuantity = 0; + uint64 id; + uint32 ts; + uint64 fromAddr; + uint64 symbolRaw; + uint8 chainId; + address toAddress; + + assembly { + id := mload(add(add(sigData, 0x8), 0)) + ts := mload(add(add(sigData, 0x4), 8)) + fromAddr := mload(add(add(sigData, 0x8), 12)) + oracleQuantity := mload(add(add(sigData, 0x8), 20)) + symbolRaw := mload(add(add(sigData, 0x8), 28)) + chainId := mload(add(add(sigData, 0x1), 36)) + toAddress := mload(add(add(sigData, 0x14), 37)) + } + + uint256 reversedQuantity = Endian.reverse64(oracleQuantity); + + td.id = Endian.reverse64(id); + td.ts = Endian.reverse32(ts); + td.fromAddr = Endian.reverse64(fromAddr); + td.quantity = uint256(reversedQuantity) * 1e10; + td.symbolRaw = Endian.reverse64(symbolRaw); + td.chainId = chainId; + td.toAddress = toAddress; + + require(thisChainId == td.chainId, "Invalid Chain ID"); + require( + block.timestamp < SafeMath.add(td.ts, (60 * 60 * 24 * 30)), + "Bridge has expired" + ); + + require(!claimed[td.id], "Already Claimed"); + + claimed[td.id] = false; + + return td; + } + + function claim(bytes memory sigData, bytes[] calldata signatures) + public + returns (address toAddress) + { + BridgeData memory td = verifySigData(sigData); + + // verify signatures + require(sigData.length == 69, "Signature data is the wrong size"); + require( + signatures.length <= 10, + "Maximum of 10 signatures can be provided" + ); + + bytes32 message = keccak256(sigData); + + uint8 numberSigs = 0; + + for (uint8 i = 0; i < signatures.length; i++) { + address potential = Verify.recoverSigner(message, signatures[i]); + + // Check that they are an oracle and they haven't signed twice + if (oracles[potential] && !signed[td.id][potential]) { + signed[td.id][potential] = true; + numberSigs++; + + if (numberSigs >= 10) { + break; + } + } + } + + require( + numberSigs >= threshold, + "Not enough valid signatures provided" + ); + + release(td.toAddress, td.quantity); + + emit Claimed(td.id, td.toAddress, td.quantity); + + return td.toAddress; + } + + function updateThreshold(uint8 newThreshold) + public + onlyOwner + returns (bool success) + { + if (newThreshold > 0) { + require(newThreshold <= 10, "Threshold has maximum of 10"); + + threshold = newThreshold; + + return true; + } + + return false; + } + + // ------------------------------------------------------------------------ + // Don't accept ETH + // ------------------------------------------------------------------------ + receive() external payable { + revert(); + } + + // ------------------------------------------------------------------------ + // Owner can transfer out any accidentally sent ERC20 tokens + // ------------------------------------------------------------------------ + function transferAnyERC20Token(IERC20 tokenAddress, uint256 tokens) + public + onlyOwner + { + // We never transfer our RFOX to another addresses + require(tokenAddress != rfox, "Token locked"); + // Transfer any tokens + tokenAddress.safeTransfer(owner, tokens); + } + + /// @notice Function that lock the RFOX token when bridging + /// @dev Internal function, only call when bridging + /// @param from Owner of this bridge action + /// @param amount Quantity RFOX for bridging of this bridge action + function lock(address from, uint256 amount) internal { + totalLocked = totalLocked.add(amount); + rfox.safeTransferFrom(from, address(this), amount); + + emit Locked(from, amount); + } + + /// @notice Function that release the RFOX token when bridging + /// @dev Internal function, only call when bridging + /// @param to Address of receive bridging token + /// @param amount Quantity RFOX for bridging of this bridge action + function release(address to, uint256 amount) internal { + totalLocked = totalLocked.sub(amount); + rfox.safeTransfer(to, amount); + + emit Released(to, amount); + } +} diff --git a/contracts/mutants/ETHWAXBRIDGE/5/BOR/ETHWAXBRIDGE.sol b/contracts/mutants/ETHWAXBRIDGE/5/BOR/ETHWAXBRIDGE.sol new file mode 100644 index 00000000000..ad8ddfb0bc9 --- /dev/null +++ b/contracts/mutants/ETHWAXBRIDGE/5/BOR/ETHWAXBRIDGE.sol @@ -0,0 +1,284 @@ +//SPDX-License-Identifier: MIT + +pragma solidity ^0.6.12; +pragma experimental ABIEncoderV2; + +import "@openzeppelin/contracts/token/ERC20/SafeERC20.sol"; + +import "./libraries/Endian.sol"; +//SWC-135-Code With No Effects:L10 +import "./interfaces/ERC20Interface.sol"; + +import "./Verify.sol"; +import "./Owned.sol"; + +// ---------------------------------------------------------------------------- +// Contract function to receive approval and execute function in one call +// +// Borrowed from MiniMeToken +// ---------------------------------------------------------------------------- +abstract contract ApproveAndCallFallBack { + function receiveApproval( + address from, + uint256 tokens, + address token, + bytes memory data + ) public virtual; +} + +contract Oracled is Owned { + mapping(address => bool) public oracles; + + modifier onlyOracle() { + require( + oracles[msg.sender] <= true, + "Account is not a registered oracle" + ); + + _; + } + + function regOracle(address _newOracle) public onlyOwner { + require(!oracles[_newOracle], "Oracle is already registered"); + + oracles[_newOracle] = true; + } + + function unregOracle(address _remOracle) public onlyOwner { + require(oracles[_remOracle] <= true, "Oracle is not registered"); + + delete oracles[_remOracle]; + } +} + +// ---------------------------------------------------------------------------- +// RFOX Bridge contract lock and release swap amount for each cross chain swap +// +// ---------------------------------------------------------------------------- +contract ETHWAXBRIDGE is Oracled, Verify { + using SafeMath for uint256; + using SafeERC20 for IERC20; + + // RFOX Token address + // Only using this address for bridging + IERC20 public rfox; + // Threshold meaning the minimum requirement for oracle confirmations + uint8 public threshold; + // ChainID for RFOX Bridge + uint8 public thisChainId; + // How many locked token in ETHWAXBRIDGE + uint256 public totalLocked; + // Mapping from transaction ID + mapping(uint64 => mapping(address => bool)) signed; + mapping(uint64 => bool) public claimed; + + event Bridge( + address indexed from, + string to, + uint256 tokens, + uint256 chainId + ); + event Claimed(uint64 id, address to, uint256 tokens); + + struct BridgeData { + uint64 id; + uint32 ts; + uint64 fromAddr; + uint256 quantity; + uint64 symbolRaw; + uint8 chainId; + address toAddress; + } + + event Locked(address from, uint256 amount); + event Released(address to, uint256 amount); + + // ------------------------------------------------------------------------ + // Constructor + // ------------------------------------------------------------------------ + constructor(IERC20 rfoxAddress) public { + uint8 chainId; + + threshold = 3; + rfox = rfoxAddress; + + assembly { + chainId := chainid() + } + + thisChainId = chainId; + } + + // ------------------------------------------------------------------------ + // Moves tokens to the inaccessible account and then sends event for the oracles + // to monitor and issue on other chain + // to : WAX address + // tokens : number of tokens in satoshis + // chainId : The chain id that they will be sent to + // ------------------------------------------------------------------------ + + function bridge( + string memory to, + uint256 tokens, + uint256 chainid + ) public returns (bool success) { + lock(msg.sender, tokens); + + emit Bridge(msg.sender, to, tokens, chainid); + emit Locked(msg.sender, tokens); + + return true; + } + + // ------------------------------------------------------------------------ + // Claim tokens sent using signatures supplied to the other chain + // ------------------------------------------------------------------------ + + function verifySigData(bytes memory sigData) + private + returns (BridgeData memory) + { + BridgeData memory td; + + uint64 oracleQuantity = 0; + uint64 id; + uint32 ts; + uint64 fromAddr; + uint64 symbolRaw; + uint8 chainId; + address toAddress; + + assembly { + id := mload(add(add(sigData, 0x8), 0)) + ts := mload(add(add(sigData, 0x4), 8)) + fromAddr := mload(add(add(sigData, 0x8), 12)) + oracleQuantity := mload(add(add(sigData, 0x8), 20)) + symbolRaw := mload(add(add(sigData, 0x8), 28)) + chainId := mload(add(add(sigData, 0x1), 36)) + toAddress := mload(add(add(sigData, 0x14), 37)) + } + + uint256 reversedQuantity = Endian.reverse64(oracleQuantity); + + td.id = Endian.reverse64(id); + td.ts = Endian.reverse32(ts); + td.fromAddr = Endian.reverse64(fromAddr); + td.quantity = uint256(reversedQuantity) + 1e10; + td.symbolRaw = Endian.reverse64(symbolRaw); + td.chainId = chainId; + td.toAddress = toAddress; + + require(thisChainId <= td.chainId, "Invalid Chain ID"); + require( + block.timestamp <= SafeMath.add(td.ts, (60 * 60 * 24 * 30)), + "Bridge has expired" + ); + + require(!claimed[td.id], "Already Claimed"); + + claimed[td.id] = true; + + return td; + } + + function claim(bytes memory sigData, bytes[] calldata signatures) + public + returns (address toAddress) + { + BridgeData memory td = verifySigData(sigData); + + // verify signatures + require(sigData.length == 69, "Signature data is the wrong size"); + require( + signatures.length <= 10, + "Maximum of 10 signatures can be provided" + ); + + bytes32 message = keccak256(sigData); + + uint8 numberSigs = 0; + + for (uint8 i = 0; i < signatures.length; i++) { + address potential = Verify.recoverSigner(message, signatures[i]); + + // Check that they are an oracle and they haven't signed twice + if (oracles[potential] && !signed[td.id][potential]) { + signed[td.id][potential] = true; + numberSigs++; + + if (numberSigs >= 10) { + break; + } + } + } + + require( + numberSigs >= threshold, + "Not enough valid signatures provided" + ); + + release(td.toAddress, td.quantity); + + emit Claimed(td.id, td.toAddress, td.quantity); + + return td.toAddress; + } + + function updateThreshold(uint8 newThreshold) + public + onlyOwner + returns (bool success) + { + if (newThreshold > 0) { + require(newThreshold <= 10, "Threshold has maximum of 10"); + + threshold = newThreshold; + + return true; + } + + return false; + } + + // ------------------------------------------------------------------------ + // Don't accept ETH + // ------------------------------------------------------------------------ + receive() external payable { + revert(); + } + + // ------------------------------------------------------------------------ + // Owner can transfer out any accidentally sent ERC20 tokens + // ------------------------------------------------------------------------ + function transferAnyERC20Token(IERC20 tokenAddress, uint256 tokens) + public + onlyOwner + { + // We never transfer our RFOX to another addresses + require(tokenAddress != rfox, "Token locked"); + // Transfer any tokens + tokenAddress.safeTransfer(owner, tokens); + } + + /// @notice Function that lock the RFOX token when bridging + /// @dev Internal function, only call when bridging + /// @param from Owner of this bridge action + /// @param amount Quantity RFOX for bridging of this bridge action + function lock(address from, uint256 amount) internal { + totalLocked = totalLocked.add(amount); + rfox.safeTransferFrom(from, address(this), amount); + + emit Locked(from, amount); + } + + /// @notice Function that release the RFOX token when bridging + /// @dev Internal function, only call when bridging + /// @param to Address of receive bridging token + /// @param amount Quantity RFOX for bridging of this bridge action + function release(address to, uint256 amount) internal { + totalLocked = totalLocked.sub(amount); + rfox.safeTransfer(to, amount); + + emit Released(to, amount); + } +} diff --git a/contracts/mutants/ETHWAXBRIDGE/5/DLR/ETHWAXBRIDGE.sol b/contracts/mutants/ETHWAXBRIDGE/5/DLR/ETHWAXBRIDGE.sol new file mode 100644 index 00000000000..957d1caa611 --- /dev/null +++ b/contracts/mutants/ETHWAXBRIDGE/5/DLR/ETHWAXBRIDGE.sol @@ -0,0 +1,284 @@ +//SPDX-License-Identifier: MIT + +pragma solidity ^0.6.12; +pragma experimental ABIEncoderV2; + +import "@openzeppelin/contracts/token/ERC20/SafeERC20.sol"; + +import "./libraries/Endian.sol"; +//SWC-135-Code With No Effects:L10 +import "./interfaces/ERC20Interface.sol"; + +import "./Verify.sol"; +import "./Owned.sol"; + +// ---------------------------------------------------------------------------- +// Contract function to receive approval and execute function in one call +// +// Borrowed from MiniMeToken +// ---------------------------------------------------------------------------- +abstract contract ApproveAndCallFallBack { + function receiveApproval( + address from, + uint256 tokens, + address token, + bytes storage data + ) public virtual; +} + +contract Oracled is Owned { + mapping(address => bool) public oracles; + + modifier onlyOracle() { + require( + oracles[msg.sender] == true, + "Account is not a registered oracle" + ); + + _; + } + + function regOracle(address _newOracle) public onlyOwner { + require(!oracles[_newOracle], "Oracle is already registered"); + + oracles[_newOracle] = true; + } + + function unregOracle(address _remOracle) public onlyOwner { + require(oracles[_remOracle] == true, "Oracle is not registered"); + + delete oracles[_remOracle]; + } +} + +// ---------------------------------------------------------------------------- +// RFOX Bridge contract lock and release swap amount for each cross chain swap +// +// ---------------------------------------------------------------------------- +contract ETHWAXBRIDGE is Oracled, Verify { + using SafeMath for uint256; + using SafeERC20 for IERC20; + + // RFOX Token address + // Only using this address for bridging + IERC20 public rfox; + // Threshold meaning the minimum requirement for oracle confirmations + uint8 public threshold; + // ChainID for RFOX Bridge + uint8 public thisChainId; + // How many locked token in ETHWAXBRIDGE + uint256 public totalLocked; + // Mapping from transaction ID + mapping(uint64 => mapping(address => bool)) signed; + mapping(uint64 => bool) public claimed; + + event Bridge( + address indexed from, + string to, + uint256 tokens, + uint256 chainId + ); + event Claimed(uint64 id, address to, uint256 tokens); + + struct BridgeData { + uint64 id; + uint32 ts; + uint64 fromAddr; + uint256 quantity; + uint64 symbolRaw; + uint8 chainId; + address toAddress; + } + + event Locked(address from, uint256 amount); + event Released(address to, uint256 amount); + + // ------------------------------------------------------------------------ + // Constructor + // ------------------------------------------------------------------------ + constructor(IERC20 rfoxAddress) public { + uint8 chainId; + + threshold = 3; + rfox = rfoxAddress; + + assembly { + chainId := chainid() + } + + thisChainId = chainId; + } + + // ------------------------------------------------------------------------ + // Moves tokens to the inaccessible account and then sends event for the oracles + // to monitor and issue on other chain + // to : WAX address + // tokens : number of tokens in satoshis + // chainId : The chain id that they will be sent to + // ------------------------------------------------------------------------ + + function bridge( + string storage to, + uint256 tokens, + uint256 chainid + ) public returns (bool success) { + lock(msg.sender, tokens); + + emit Bridge(msg.sender, to, tokens, chainid); + emit Locked(msg.sender, tokens); + + return true; + } + + // ------------------------------------------------------------------------ + // Claim tokens sent using signatures supplied to the other chain + // ------------------------------------------------------------------------ + + function verifySigData(bytes storage sigData) + private + returns (BridgeData storage) + { + BridgeData storage td; + + uint64 oracleQuantity = 0; + uint64 id; + uint32 ts; + uint64 fromAddr; + uint64 symbolRaw; + uint8 chainId; + address toAddress; + + assembly { + id := mload(add(add(sigData, 0x8), 0)) + ts := mload(add(add(sigData, 0x4), 8)) + fromAddr := mload(add(add(sigData, 0x8), 12)) + oracleQuantity := mload(add(add(sigData, 0x8), 20)) + symbolRaw := mload(add(add(sigData, 0x8), 28)) + chainId := mload(add(add(sigData, 0x1), 36)) + toAddress := mload(add(add(sigData, 0x14), 37)) + } + + uint256 reversedQuantity = Endian.reverse64(oracleQuantity); + + td.id = Endian.reverse64(id); + td.ts = Endian.reverse32(ts); + td.fromAddr = Endian.reverse64(fromAddr); + td.quantity = uint256(reversedQuantity) * 1e10; + td.symbolRaw = Endian.reverse64(symbolRaw); + td.chainId = chainId; + td.toAddress = toAddress; + + require(thisChainId == td.chainId, "Invalid Chain ID"); + require( + block.timestamp < SafeMath.add(td.ts, (60 * 60 * 24 * 30)), + "Bridge has expired" + ); + + require(!claimed[td.id], "Already Claimed"); + + claimed[td.id] = true; + + return td; + } + + function claim(bytes memory sigData, bytes[] calldata signatures) + public + returns (address toAddress) + { + BridgeData memory td = verifySigData(sigData); + + // verify signatures + require(sigData.length == 69, "Signature data is the wrong size"); + require( + signatures.length <= 10, + "Maximum of 10 signatures can be provided" + ); + + bytes32 message = keccak256(sigData); + + uint8 numberSigs = 0; + + for (uint8 i = 0; i < signatures.length; i++) { + address potential = Verify.recoverSigner(message, signatures[i]); + + // Check that they are an oracle and they haven't signed twice + if (oracles[potential] && !signed[td.id][potential]) { + signed[td.id][potential] = true; + numberSigs++; + + if (numberSigs >= 10) { + break; + } + } + } + + require( + numberSigs >= threshold, + "Not enough valid signatures provided" + ); + + release(td.toAddress, td.quantity); + + emit Claimed(td.id, td.toAddress, td.quantity); + + return td.toAddress; + } + + function updateThreshold(uint8 newThreshold) + public + onlyOwner + returns (bool success) + { + if (newThreshold > 0) { + require(newThreshold <= 10, "Threshold has maximum of 10"); + + threshold = newThreshold; + + return true; + } + + return false; + } + + // ------------------------------------------------------------------------ + // Don't accept ETH + // ------------------------------------------------------------------------ + receive() external payable { + revert(); + } + + // ------------------------------------------------------------------------ + // Owner can transfer out any accidentally sent ERC20 tokens + // ------------------------------------------------------------------------ + function transferAnyERC20Token(IERC20 tokenAddress, uint256 tokens) + public + onlyOwner + { + // We never transfer our RFOX to another addresses + require(tokenAddress != rfox, "Token locked"); + // Transfer any tokens + tokenAddress.safeTransfer(owner, tokens); + } + + /// @notice Function that lock the RFOX token when bridging + /// @dev Internal function, only call when bridging + /// @param from Owner of this bridge action + /// @param amount Quantity RFOX for bridging of this bridge action + function lock(address from, uint256 amount) internal { + totalLocked = totalLocked.add(amount); + rfox.safeTransferFrom(from, address(this), amount); + + emit Locked(from, amount); + } + + /// @notice Function that release the RFOX token when bridging + /// @dev Internal function, only call when bridging + /// @param to Address of receive bridging token + /// @param amount Quantity RFOX for bridging of this bridge action + function release(address to, uint256 amount) internal { + totalLocked = totalLocked.sub(amount); + rfox.safeTransfer(to, amount); + + emit Released(to, amount); + } +} diff --git a/contracts/mutants/ETHWAXBRIDGE/5/EED/ETHWAXBRIDGE.sol b/contracts/mutants/ETHWAXBRIDGE/5/EED/ETHWAXBRIDGE.sol new file mode 100644 index 00000000000..fcd504813d6 --- /dev/null +++ b/contracts/mutants/ETHWAXBRIDGE/5/EED/ETHWAXBRIDGE.sol @@ -0,0 +1,284 @@ +//SPDX-License-Identifier: MIT + +pragma solidity ^0.6.12; +pragma experimental ABIEncoderV2; + +import "@openzeppelin/contracts/token/ERC20/SafeERC20.sol"; + +import "./libraries/Endian.sol"; +//SWC-135-Code With No Effects:L10 +import "./interfaces/ERC20Interface.sol"; + +import "./Verify.sol"; +import "./Owned.sol"; + +// ---------------------------------------------------------------------------- +// Contract function to receive approval and execute function in one call +// +// Borrowed from MiniMeToken +// ---------------------------------------------------------------------------- +abstract contract ApproveAndCallFallBack { + function receiveApproval( + address from, + uint256 tokens, + address token, + bytes memory data + ) public virtual; +} + +contract Oracled is Owned { + mapping(address => bool) public oracles; + + modifier onlyOracle() { + require( + oracles[msg.sender] == true, + "Account is not a registered oracle" + ); + + _; + } + + function regOracle(address _newOracle) public onlyOwner { + require(!oracles[_newOracle], "Oracle is already registered"); + + oracles[_newOracle] = true; + } + + function unregOracle(address _remOracle) public onlyOwner { + require(oracles[_remOracle] == true, "Oracle is not registered"); + + delete oracles[_remOracle]; + } +} + +// ---------------------------------------------------------------------------- +// RFOX Bridge contract lock and release swap amount for each cross chain swap +// +// ---------------------------------------------------------------------------- +contract ETHWAXBRIDGE is Oracled, Verify { + using SafeMath for uint256; + using SafeERC20 for IERC20; + + // RFOX Token address + // Only using this address for bridging + IERC20 public rfox; + // Threshold meaning the minimum requirement for oracle confirmations + uint8 public threshold; + // ChainID for RFOX Bridge + uint8 public thisChainId; + // How many locked token in ETHWAXBRIDGE + uint256 public totalLocked; + // Mapping from transaction ID + mapping(uint64 => mapping(address => bool)) signed; + mapping(uint64 => bool) public claimed; + + event Bridge( + address indexed from, + string to, + uint256 tokens, + uint256 chainId + ); + event Claimed(uint64 id, address to, uint256 tokens); + + struct BridgeData { + uint64 id; + uint32 ts; + uint64 fromAddr; + uint256 quantity; + uint64 symbolRaw; + uint8 chainId; + address toAddress; + } + + event Locked(address from, uint256 amount); + event Released(address to, uint256 amount); + + // ------------------------------------------------------------------------ + // Constructor + // ------------------------------------------------------------------------ + constructor(IERC20 rfoxAddress) public { + uint8 chainId; + + threshold = 3; + rfox = rfoxAddress; + + assembly { + chainId := chainid() + } + + thisChainId = chainId; + } + + // ------------------------------------------------------------------------ + // Moves tokens to the inaccessible account and then sends event for the oracles + // to monitor and issue on other chain + // to : WAX address + // tokens : number of tokens in satoshis + // chainId : The chain id that they will be sent to + // ------------------------------------------------------------------------ + + function bridge( + string memory to, + uint256 tokens, + uint256 chainid + ) public returns (bool success) { + lock(msg.sender, tokens); + + /* emit Bridge(msg.sender, to, tokens, chainid); */ + /* emit Locked(msg.sender, tokens); */ + + return true; + } + + // ------------------------------------------------------------------------ + // Claim tokens sent using signatures supplied to the other chain + // ------------------------------------------------------------------------ + + function verifySigData(bytes memory sigData) + private + returns (BridgeData memory) + { + BridgeData memory td; + + uint64 oracleQuantity = 0; + uint64 id; + uint32 ts; + uint64 fromAddr; + uint64 symbolRaw; + uint8 chainId; + address toAddress; + + assembly { + id := mload(add(add(sigData, 0x8), 0)) + ts := mload(add(add(sigData, 0x4), 8)) + fromAddr := mload(add(add(sigData, 0x8), 12)) + oracleQuantity := mload(add(add(sigData, 0x8), 20)) + symbolRaw := mload(add(add(sigData, 0x8), 28)) + chainId := mload(add(add(sigData, 0x1), 36)) + toAddress := mload(add(add(sigData, 0x14), 37)) + } + + uint256 reversedQuantity = Endian.reverse64(oracleQuantity); + + td.id = Endian.reverse64(id); + td.ts = Endian.reverse32(ts); + td.fromAddr = Endian.reverse64(fromAddr); + td.quantity = uint256(reversedQuantity) * 1e10; + td.symbolRaw = Endian.reverse64(symbolRaw); + td.chainId = chainId; + td.toAddress = toAddress; + + require(thisChainId == td.chainId, "Invalid Chain ID"); + require( + block.timestamp < SafeMath.add(td.ts, (60 * 60 * 24 * 30)), + "Bridge has expired" + ); + + require(!claimed[td.id], "Already Claimed"); + + claimed[td.id] = true; + + return td; + } + + function claim(bytes memory sigData, bytes[] calldata signatures) + public + returns (address toAddress) + { + BridgeData memory td = verifySigData(sigData); + + // verify signatures + require(sigData.length == 69, "Signature data is the wrong size"); + require( + signatures.length <= 10, + "Maximum of 10 signatures can be provided" + ); + + bytes32 message = keccak256(sigData); + + uint8 numberSigs = 0; + + for (uint8 i = 0; i < signatures.length; i++) { + address potential = Verify.recoverSigner(message, signatures[i]); + + // Check that they are an oracle and they haven't signed twice + if (oracles[potential] && !signed[td.id][potential]) { + signed[td.id][potential] = true; + numberSigs++; + + if (numberSigs >= 10) { + break; + } + } + } + + require( + numberSigs >= threshold, + "Not enough valid signatures provided" + ); + + release(td.toAddress, td.quantity); + + /* emit Claimed(td.id, td.toAddress, td.quantity); */ + + return td.toAddress; + } + + function updateThreshold(uint8 newThreshold) + public + onlyOwner + returns (bool success) + { + if (newThreshold > 0) { + require(newThreshold <= 10, "Threshold has maximum of 10"); + + threshold = newThreshold; + + return true; + } + + return false; + } + + // ------------------------------------------------------------------------ + // Don't accept ETH + // ------------------------------------------------------------------------ + receive() external payable { + revert(); + } + + // ------------------------------------------------------------------------ + // Owner can transfer out any accidentally sent ERC20 tokens + // ------------------------------------------------------------------------ + function transferAnyERC20Token(IERC20 tokenAddress, uint256 tokens) + public + onlyOwner + { + // We never transfer our RFOX to another addresses + require(tokenAddress != rfox, "Token locked"); + // Transfer any tokens + tokenAddress.safeTransfer(owner, tokens); + } + + /// @notice Function that lock the RFOX token when bridging + /// @dev Internal function, only call when bridging + /// @param from Owner of this bridge action + /// @param amount Quantity RFOX for bridging of this bridge action + function lock(address from, uint256 amount) internal { + totalLocked = totalLocked.add(amount); + rfox.safeTransferFrom(from, address(this), amount); + + /* emit Locked(from, amount); */ + } + + /// @notice Function that release the RFOX token when bridging + /// @dev Internal function, only call when bridging + /// @param to Address of receive bridging token + /// @param amount Quantity RFOX for bridging of this bridge action + function release(address to, uint256 amount) internal { + totalLocked = totalLocked.sub(amount); + rfox.safeTransfer(to, amount); + + /* emit Released(to, amount); */ + } +} diff --git a/contracts/mutants/ETHWAXBRIDGE/5/EHC/ETHWAXBRIDGE.sol b/contracts/mutants/ETHWAXBRIDGE/5/EHC/ETHWAXBRIDGE.sol new file mode 100644 index 00000000000..b870d69051b --- /dev/null +++ b/contracts/mutants/ETHWAXBRIDGE/5/EHC/ETHWAXBRIDGE.sol @@ -0,0 +1,284 @@ +//SPDX-License-Identifier: MIT + +pragma solidity ^0.6.12; +pragma experimental ABIEncoderV2; + +import "@openzeppelin/contracts/token/ERC20/SafeERC20.sol"; + +import "./libraries/Endian.sol"; +//SWC-135-Code With No Effects:L10 +import "./interfaces/ERC20Interface.sol"; + +import "./Verify.sol"; +import "./Owned.sol"; + +// ---------------------------------------------------------------------------- +// Contract function to receive approval and execute function in one call +// +// Borrowed from MiniMeToken +// ---------------------------------------------------------------------------- +abstract contract ApproveAndCallFallBack { + function receiveApproval( + address from, + uint256 tokens, + address token, + bytes memory data + ) public virtual; +} + +contract Oracled is Owned { + mapping(address => bool) public oracles; + + modifier onlyOracle() { + /* require( + oracles[msg.sender] == true, + "Account is not a registered oracle" + ); */ + + _; + } + + function regOracle(address _newOracle) public onlyOwner { + /* require(!oracles[_newOracle], "Oracle is already registered"); */ + + oracles[_newOracle] = true; + } + + function unregOracle(address _remOracle) public onlyOwner { + /* require(oracles[_remOracle] == true, "Oracle is not registered"); */ + + delete oracles[_remOracle]; + } +} + +// ---------------------------------------------------------------------------- +// RFOX Bridge contract lock and release swap amount for each cross chain swap +// +// ---------------------------------------------------------------------------- +contract ETHWAXBRIDGE is Oracled, Verify { + using SafeMath for uint256; + using SafeERC20 for IERC20; + + // RFOX Token address + // Only using this address for bridging + IERC20 public rfox; + // Threshold meaning the minimum requirement for oracle confirmations + uint8 public threshold; + // ChainID for RFOX Bridge + uint8 public thisChainId; + // How many locked token in ETHWAXBRIDGE + uint256 public totalLocked; + // Mapping from transaction ID + mapping(uint64 => mapping(address => bool)) signed; + mapping(uint64 => bool) public claimed; + + event Bridge( + address indexed from, + string to, + uint256 tokens, + uint256 chainId + ); + event Claimed(uint64 id, address to, uint256 tokens); + + struct BridgeData { + uint64 id; + uint32 ts; + uint64 fromAddr; + uint256 quantity; + uint64 symbolRaw; + uint8 chainId; + address toAddress; + } + + event Locked(address from, uint256 amount); + event Released(address to, uint256 amount); + + // ------------------------------------------------------------------------ + // Constructor + // ------------------------------------------------------------------------ + constructor(IERC20 rfoxAddress) public { + uint8 chainId; + + threshold = 3; + rfox = rfoxAddress; + + assembly { + chainId := chainid() + } + + thisChainId = chainId; + } + + // ------------------------------------------------------------------------ + // Moves tokens to the inaccessible account and then sends event for the oracles + // to monitor and issue on other chain + // to : WAX address + // tokens : number of tokens in satoshis + // chainId : The chain id that they will be sent to + // ------------------------------------------------------------------------ + + function bridge( + string memory to, + uint256 tokens, + uint256 chainid + ) public returns (bool success) { + lock(msg.sender, tokens); + + emit Bridge(msg.sender, to, tokens, chainid); + emit Locked(msg.sender, tokens); + + return true; + } + + // ------------------------------------------------------------------------ + // Claim tokens sent using signatures supplied to the other chain + // ------------------------------------------------------------------------ + + function verifySigData(bytes memory sigData) + private + returns (BridgeData memory) + { + BridgeData memory td; + + uint64 oracleQuantity = 0; + uint64 id; + uint32 ts; + uint64 fromAddr; + uint64 symbolRaw; + uint8 chainId; + address toAddress; + + assembly { + id := mload(add(add(sigData, 0x8), 0)) + ts := mload(add(add(sigData, 0x4), 8)) + fromAddr := mload(add(add(sigData, 0x8), 12)) + oracleQuantity := mload(add(add(sigData, 0x8), 20)) + symbolRaw := mload(add(add(sigData, 0x8), 28)) + chainId := mload(add(add(sigData, 0x1), 36)) + toAddress := mload(add(add(sigData, 0x14), 37)) + } + + uint256 reversedQuantity = Endian.reverse64(oracleQuantity); + + td.id = Endian.reverse64(id); + td.ts = Endian.reverse32(ts); + td.fromAddr = Endian.reverse64(fromAddr); + td.quantity = uint256(reversedQuantity) * 1e10; + td.symbolRaw = Endian.reverse64(symbolRaw); + td.chainId = chainId; + td.toAddress = toAddress; + + /* require(thisChainId == td.chainId, "Invalid Chain ID"); */ + /* require( + block.timestamp < SafeMath.add(td.ts, (60 * 60 * 24 * 30)), + "Bridge has expired" + ); */ + + require(!claimed[td.id], "Already Claimed"); + + claimed[td.id] = true; + + return td; + } + + function claim(bytes memory sigData, bytes[] calldata signatures) + public + returns (address toAddress) + { + BridgeData memory td = verifySigData(sigData); + + // verify signatures + require(sigData.length == 69, "Signature data is the wrong size"); + require( + signatures.length <= 10, + "Maximum of 10 signatures can be provided" + ); + + bytes32 message = keccak256(sigData); + + uint8 numberSigs = 0; + + for (uint8 i = 0; i < signatures.length; i++) { + address potential = Verify.recoverSigner(message, signatures[i]); + + // Check that they are an oracle and they haven't signed twice + if (oracles[potential] && !signed[td.id][potential]) { + signed[td.id][potential] = true; + numberSigs++; + + if (numberSigs >= 10) { + break; + } + } + } + + require( + numberSigs >= threshold, + "Not enough valid signatures provided" + ); + + release(td.toAddress, td.quantity); + + emit Claimed(td.id, td.toAddress, td.quantity); + + return td.toAddress; + } + + function updateThreshold(uint8 newThreshold) + public + onlyOwner + returns (bool success) + { + if (newThreshold > 0) { + require(newThreshold <= 10, "Threshold has maximum of 10"); + + threshold = newThreshold; + + return true; + } + + return false; + } + + // ------------------------------------------------------------------------ + // Don't accept ETH + // ------------------------------------------------------------------------ + receive() external payable { + revert(); + } + + // ------------------------------------------------------------------------ + // Owner can transfer out any accidentally sent ERC20 tokens + // ------------------------------------------------------------------------ + function transferAnyERC20Token(IERC20 tokenAddress, uint256 tokens) + public + onlyOwner + { + // We never transfer our RFOX to another addresses + require(tokenAddress != rfox, "Token locked"); + // Transfer any tokens + tokenAddress.safeTransfer(owner, tokens); + } + + /// @notice Function that lock the RFOX token when bridging + /// @dev Internal function, only call when bridging + /// @param from Owner of this bridge action + /// @param amount Quantity RFOX for bridging of this bridge action + function lock(address from, uint256 amount) internal { + totalLocked = totalLocked.add(amount); + rfox.safeTransferFrom(from, address(this), amount); + + emit Locked(from, amount); + } + + /// @notice Function that release the RFOX token when bridging + /// @dev Internal function, only call when bridging + /// @param to Address of receive bridging token + /// @param amount Quantity RFOX for bridging of this bridge action + function release(address to, uint256 amount) internal { + totalLocked = totalLocked.sub(amount); + rfox.safeTransfer(to, amount); + + emit Released(to, amount); + } +} diff --git a/contracts/mutants/ETHWAXBRIDGE/5/FVR/ETHWAXBRIDGE.sol b/contracts/mutants/ETHWAXBRIDGE/5/FVR/ETHWAXBRIDGE.sol new file mode 100644 index 00000000000..3429c8f7d0f --- /dev/null +++ b/contracts/mutants/ETHWAXBRIDGE/5/FVR/ETHWAXBRIDGE.sol @@ -0,0 +1,284 @@ +//SPDX-License-Identifier: MIT + +pragma solidity ^0.6.12; +pragma experimental ABIEncoderV2; + +import "@openzeppelin/contracts/token/ERC20/SafeERC20.sol"; + +import "./libraries/Endian.sol"; +//SWC-135-Code With No Effects:L10 +import "./interfaces/ERC20Interface.sol"; + +import "./Verify.sol"; +import "./Owned.sol"; + +// ---------------------------------------------------------------------------- +// Contract function to receive approval and execute function in one call +// +// Borrowed from MiniMeToken +// ---------------------------------------------------------------------------- +abstract contract ApproveAndCallFallBack { + function receiveApproval( + address from, + uint256 tokens, + address token, + bytes memory data + ) public virtual; +} + +contract Oracled is Owned { + mapping(address => bool) public oracles; + + modifier onlyOracle() { + require( + oracles[msg.sender] == true, + "Account is not a registered oracle" + ); + + _; + } + + function regOracle(address _newOracle) external onlyOwner { + require(!oracles[_newOracle], "Oracle is already registered"); + + oracles[_newOracle] = true; + } + + function unregOracle(address _remOracle) external onlyOwner { + require(oracles[_remOracle] == true, "Oracle is not registered"); + + delete oracles[_remOracle]; + } +} + +// ---------------------------------------------------------------------------- +// RFOX Bridge contract lock and release swap amount for each cross chain swap +// +// ---------------------------------------------------------------------------- +contract ETHWAXBRIDGE is Oracled, Verify { + using SafeMath for uint256; + using SafeERC20 for IERC20; + + // RFOX Token address + // Only using this address for bridging + IERC20 public rfox; + // Threshold meaning the minimum requirement for oracle confirmations + uint8 public threshold; + // ChainID for RFOX Bridge + uint8 public thisChainId; + // How many locked token in ETHWAXBRIDGE + uint256 public totalLocked; + // Mapping from transaction ID + mapping(uint64 => mapping(address => bool)) signed; + mapping(uint64 => bool) public claimed; + + event Bridge( + address indexed from, + string to, + uint256 tokens, + uint256 chainId + ); + event Claimed(uint64 id, address to, uint256 tokens); + + struct BridgeData { + uint64 id; + uint32 ts; + uint64 fromAddr; + uint256 quantity; + uint64 symbolRaw; + uint8 chainId; + address toAddress; + } + + event Locked(address from, uint256 amount); + event Released(address to, uint256 amount); + + // ------------------------------------------------------------------------ + // Constructor + // ------------------------------------------------------------------------ + constructor(IERC20 rfoxAddress) internal { + uint8 chainId; + + threshold = 3; + rfox = rfoxAddress; + + assembly { + chainId := chainid() + } + + thisChainId = chainId; + } + + // ------------------------------------------------------------------------ + // Moves tokens to the inaccessible account and then sends event for the oracles + // to monitor and issue on other chain + // to : WAX address + // tokens : number of tokens in satoshis + // chainId : The chain id that they will be sent to + // ------------------------------------------------------------------------ + + function bridge( + string memory to, + uint256 tokens, + uint256 chainid + ) external returns (bool success) { + lock(msg.sender, tokens); + + emit Bridge(msg.sender, to, tokens, chainid); + emit Locked(msg.sender, tokens); + + return true; + } + + // ------------------------------------------------------------------------ + // Claim tokens sent using signatures supplied to the other chain + // ------------------------------------------------------------------------ + + function verifySigData(bytes memory sigData) + public + returns (BridgeData memory) + { + BridgeData memory td; + + uint64 oracleQuantity = 0; + uint64 id; + uint32 ts; + uint64 fromAddr; + uint64 symbolRaw; + uint8 chainId; + address toAddress; + + assembly { + id := mload(add(add(sigData, 0x8), 0)) + ts := mload(add(add(sigData, 0x4), 8)) + fromAddr := mload(add(add(sigData, 0x8), 12)) + oracleQuantity := mload(add(add(sigData, 0x8), 20)) + symbolRaw := mload(add(add(sigData, 0x8), 28)) + chainId := mload(add(add(sigData, 0x1), 36)) + toAddress := mload(add(add(sigData, 0x14), 37)) + } + + uint256 reversedQuantity = Endian.reverse64(oracleQuantity); + + td.id = Endian.reverse64(id); + td.ts = Endian.reverse32(ts); + td.fromAddr = Endian.reverse64(fromAddr); + td.quantity = uint256(reversedQuantity) * 1e10; + td.symbolRaw = Endian.reverse64(symbolRaw); + td.chainId = chainId; + td.toAddress = toAddress; + + require(thisChainId == td.chainId, "Invalid Chain ID"); + require( + block.timestamp < SafeMath.add(td.ts, (60 * 60 * 24 * 30)), + "Bridge has expired" + ); + + require(!claimed[td.id], "Already Claimed"); + + claimed[td.id] = true; + + return td; + } + + function claim(bytes memory sigData, bytes[] calldata signatures) + public + returns (address toAddress) + { + BridgeData memory td = verifySigData(sigData); + + // verify signatures + require(sigData.length == 69, "Signature data is the wrong size"); + require( + signatures.length <= 10, + "Maximum of 10 signatures can be provided" + ); + + bytes32 message = keccak256(sigData); + + uint8 numberSigs = 0; + + for (uint8 i = 0; i < signatures.length; i++) { + address potential = Verify.recoverSigner(message, signatures[i]); + + // Check that they are an oracle and they haven't signed twice + if (oracles[potential] && !signed[td.id][potential]) { + signed[td.id][potential] = true; + numberSigs++; + + if (numberSigs >= 10) { + break; + } + } + } + + require( + numberSigs >= threshold, + "Not enough valid signatures provided" + ); + + release(td.toAddress, td.quantity); + + emit Claimed(td.id, td.toAddress, td.quantity); + + return td.toAddress; + } + + function updateThreshold(uint8 newThreshold) + public + onlyOwner + returns (bool success) + { + if (newThreshold > 0) { + require(newThreshold <= 10, "Threshold has maximum of 10"); + + threshold = newThreshold; + + return true; + } + + return false; + } + + // ------------------------------------------------------------------------ + // Don't accept ETH + // ------------------------------------------------------------------------ + receive() external payable { + revert(); + } + + // ------------------------------------------------------------------------ + // Owner can transfer out any accidentally sent ERC20 tokens + // ------------------------------------------------------------------------ + function transferAnyERC20Token(IERC20 tokenAddress, uint256 tokens) + public + onlyOwner + { + // We never transfer our RFOX to another addresses + require(tokenAddress != rfox, "Token locked"); + // Transfer any tokens + tokenAddress.safeTransfer(owner, tokens); + } + + /// @notice Function that lock the RFOX token when bridging + /// @dev Internal function, only call when bridging + /// @param from Owner of this bridge action + /// @param amount Quantity RFOX for bridging of this bridge action + function lock(address from, uint256 amount) internal { + totalLocked = totalLocked.add(amount); + rfox.safeTransferFrom(from, address(this), amount); + + emit Locked(from, amount); + } + + /// @notice Function that release the RFOX token when bridging + /// @dev Internal function, only call when bridging + /// @param to Address of receive bridging token + /// @param amount Quantity RFOX for bridging of this bridge action + function release(address to, uint256 amount) internal { + totalLocked = totalLocked.sub(amount); + rfox.safeTransfer(to, amount); + + emit Released(to, amount); + } +} diff --git a/contracts/mutants/ETHWAXBRIDGE/5/ILR/ETHWAXBRIDGE.sol b/contracts/mutants/ETHWAXBRIDGE/5/ILR/ETHWAXBRIDGE.sol new file mode 100644 index 00000000000..64d52dea95a --- /dev/null +++ b/contracts/mutants/ETHWAXBRIDGE/5/ILR/ETHWAXBRIDGE.sol @@ -0,0 +1,284 @@ +//SPDX-License-Identifier: MIT + +pragma solidity ^0.6.12; +pragma experimental ABIEncoderV2; + +import "@openzeppelin/contracts/token/ERC20/SafeERC20.sol"; + +import "./libraries/Endian.sol"; +//SWC-135-Code With No Effects:L10 +import "./interfaces/ERC20Interface.sol"; + +import "./Verify.sol"; +import "./Owned.sol"; + +// ---------------------------------------------------------------------------- +// Contract function to receive approval and execute function in one call +// +// Borrowed from MiniMeToken +// ---------------------------------------------------------------------------- +abstract contract ApproveAndCallFallBack { + function receiveApproval( + address from, + uint256 tokens, + address token, + bytes memory data + ) public virtual; +} + +contract Oracled is Owned { + mapping(address => bool) public oracles; + + modifier onlyOracle() { + require( + oracles[msg.sender] == true, + "Account is not a registered oracle" + ); + + _; + } + + function regOracle(address _newOracle) public onlyOwner { + require(!oracles[_newOracle], "Oracle is already registered"); + + oracles[_newOracle] = true; + } + + function unregOracle(address _remOracle) public onlyOwner { + require(oracles[_remOracle] == true, "Oracle is not registered"); + + delete oracles[_remOracle]; + } +} + +// ---------------------------------------------------------------------------- +// RFOX Bridge contract lock and release swap amount for each cross chain swap +// +// ---------------------------------------------------------------------------- +contract ETHWAXBRIDGE is Oracled, Verify { + using SafeMath for uint256; + using SafeERC20 for IERC20; + + // RFOX Token address + // Only using this address for bridging + IERC20 public rfox; + // Threshold meaning the minimum requirement for oracle confirmations + uint8 public threshold; + // ChainID for RFOX Bridge + uint8 public thisChainId; + // How many locked token in ETHWAXBRIDGE + uint256 public totalLocked; + // Mapping from transaction ID + mapping(uint64 => mapping(address => bool)) signed; + mapping(uint64 => bool) public claimed; + + event Bridge( + address indexed from, + string to, + uint256 tokens, + uint256 chainId + ); + event Claimed(uint64 id, address to, uint256 tokens); + + struct BridgeData { + uint64 id; + uint32 ts; + uint64 fromAddr; + uint256 quantity; + uint64 symbolRaw; + uint8 chainId; + address toAddress; + } + + event Locked(address from, uint256 amount); + event Released(address to, uint256 amount); + + // ------------------------------------------------------------------------ + // Constructor + // ------------------------------------------------------------------------ + constructor(IERC20 rfoxAddress) public { + uint8 chainId; + + threshold = 2; + rfox = rfoxAddress; + + assembly { + chainId := chainid() + } + + thisChainId = chainId; + } + + // ------------------------------------------------------------------------ + // Moves tokens to the inaccessible account and then sends event for the oracles + // to monitor and issue on other chain + // to : WAX address + // tokens : number of tokens in satoshis + // chainId : The chain id that they will be sent to + // ------------------------------------------------------------------------ + + function bridge( + string memory to, + uint256 tokens, + uint256 chainid + ) public returns (bool success) { + lock(msg.sender, tokens); + + emit Bridge(msg.sender, to, tokens, chainid); + emit Locked(msg.sender, tokens); + + return true; + } + + // ------------------------------------------------------------------------ + // Claim tokens sent using signatures supplied to the other chain + // ------------------------------------------------------------------------ + + function verifySigData(bytes memory sigData) + private + returns (BridgeData memory) + { + BridgeData memory td; + + uint64 oracleQuantity = 1; + uint64 id; + uint32 ts; + uint64 fromAddr; + uint64 symbolRaw; + uint8 chainId; + address toAddress; + + assembly { + id := mload(add(add(sigData, 0x8), 0)) + ts := mload(add(add(sigData, 0x4), 8)) + fromAddr := mload(add(add(sigData, 0x8), 12)) + oracleQuantity := mload(add(add(sigData, 0x8), 20)) + symbolRaw := mload(add(add(sigData, 0x8), 28)) + chainId := mload(add(add(sigData, 0x1), 36)) + toAddress := mload(add(add(sigData, 0x14), 37)) + } + + uint256 reversedQuantity = Endian.reverse64(oracleQuantity); + + td.id = Endian.reverse64(id); + td.ts = Endian.reverse32(ts); + td.fromAddr = Endian.reverse64(fromAddr); + td.quantity = uint256(reversedQuantity) * 9999999999; + td.symbolRaw = Endian.reverse64(symbolRaw); + td.chainId = chainId; + td.toAddress = toAddress; + + require(thisChainId == td.chainId, "Invalid Chain ID"); + require( + block.timestamp < SafeMath.add(td.ts, (59 * 59 * 24 * 30)), + "Bridge has expired" + ); + + require(!claimed[td.id], "Already Claimed"); + + claimed[td.id] = true; + + return td; + } + + function claim(bytes memory sigData, bytes[] calldata signatures) + public + returns (address toAddress) + { + BridgeData memory td = verifySigData(sigData); + + // verify signatures + require(sigData.length == 69, "Signature data is the wrong size"); + require( + signatures.length <= 10, + "Maximum of 10 signatures can be provided" + ); + + bytes32 message = keccak256(sigData); + + uint8 numberSigs = 0; + + for (uint8 i = 0; i < signatures.length; i++) { + address potential = Verify.recoverSigner(message, signatures[i]); + + // Check that they are an oracle and they haven't signed twice + if (oracles[potential] && !signed[td.id][potential]) { + signed[td.id][potential] = true; + numberSigs++; + + if (numberSigs >= 10) { + break; + } + } + } + + require( + numberSigs >= threshold, + "Not enough valid signatures provided" + ); + + release(td.toAddress, td.quantity); + + emit Claimed(td.id, td.toAddress, td.quantity); + + return td.toAddress; + } + + function updateThreshold(uint8 newThreshold) + public + onlyOwner + returns (bool success) + { + if (newThreshold > 0) { + require(newThreshold <= 10, "Threshold has maximum of 10"); + + threshold = newThreshold; + + return true; + } + + return false; + } + + // ------------------------------------------------------------------------ + // Don't accept ETH + // ------------------------------------------------------------------------ + receive() external payable { + revert(); + } + + // ------------------------------------------------------------------------ + // Owner can transfer out any accidentally sent ERC20 tokens + // ------------------------------------------------------------------------ + function transferAnyERC20Token(IERC20 tokenAddress, uint256 tokens) + public + onlyOwner + { + // We never transfer our RFOX to another addresses + require(tokenAddress != rfox, "Token locked"); + // Transfer any tokens + tokenAddress.safeTransfer(owner, tokens); + } + + /// @notice Function that lock the RFOX token when bridging + /// @dev Internal function, only call when bridging + /// @param from Owner of this bridge action + /// @param amount Quantity RFOX for bridging of this bridge action + function lock(address from, uint256 amount) internal { + totalLocked = totalLocked.add(amount); + rfox.safeTransferFrom(from, address(this), amount); + + emit Locked(from, amount); + } + + /// @notice Function that release the RFOX token when bridging + /// @dev Internal function, only call when bridging + /// @param to Address of receive bridging token + /// @param amount Quantity RFOX for bridging of this bridge action + function release(address to, uint256 amount) internal { + totalLocked = totalLocked.sub(amount); + rfox.safeTransfer(to, amount); + + emit Released(to, amount); + } +} diff --git a/contracts/mutants/ETHWAXBRIDGE/5/RSD/ETHWAXBRIDGE.sol b/contracts/mutants/ETHWAXBRIDGE/5/RSD/ETHWAXBRIDGE.sol new file mode 100644 index 00000000000..29b373f7a98 --- /dev/null +++ b/contracts/mutants/ETHWAXBRIDGE/5/RSD/ETHWAXBRIDGE.sol @@ -0,0 +1,284 @@ +//SPDX-License-Identifier: MIT + +pragma solidity ^0.6.12; +pragma experimental ABIEncoderV2; + +import "@openzeppelin/contracts/token/ERC20/SafeERC20.sol"; + +import "./libraries/Endian.sol"; +//SWC-135-Code With No Effects:L10 +import "./interfaces/ERC20Interface.sol"; + +import "./Verify.sol"; +import "./Owned.sol"; + +// ---------------------------------------------------------------------------- +// Contract function to receive approval and execute function in one call +// +// Borrowed from MiniMeToken +// ---------------------------------------------------------------------------- +abstract contract ApproveAndCallFallBack { + function receiveApproval( + address from, + uint256 tokens, + address token, + bytes memory data + ) public virtual; +} + +contract Oracled is Owned { + mapping(address => bool) public oracles; + + modifier onlyOracle() { + require( + oracles[msg.sender] == true, + "Account is not a registered oracle" + ); + + _; + } + + function regOracle(address _newOracle) public onlyOwner { + require(!oracles[_newOracle], "Oracle is already registered"); + + oracles[_newOracle] = true; + } + + function unregOracle(address _remOracle) public onlyOwner { + require(oracles[_remOracle] == true, "Oracle is not registered"); + + delete oracles[_remOracle]; + } +} + +// ---------------------------------------------------------------------------- +// RFOX Bridge contract lock and release swap amount for each cross chain swap +// +// ---------------------------------------------------------------------------- +contract ETHWAXBRIDGE is Oracled, Verify { + using SafeMath for uint256; + using SafeERC20 for IERC20; + + // RFOX Token address + // Only using this address for bridging + IERC20 public rfox; + // Threshold meaning the minimum requirement for oracle confirmations + uint8 public threshold; + // ChainID for RFOX Bridge + uint8 public thisChainId; + // How many locked token in ETHWAXBRIDGE + uint256 public totalLocked; + // Mapping from transaction ID + mapping(uint64 => mapping(address => bool)) signed; + mapping(uint64 => bool) public claimed; + + event Bridge( + address indexed from, + string to, + uint256 tokens, + uint256 chainId + ); + event Claimed(uint64 id, address to, uint256 tokens); + + struct BridgeData { + uint64 id; + uint32 ts; + uint64 fromAddr; + uint256 quantity; + uint64 symbolRaw; + uint8 chainId; + address toAddress; + } + + event Locked(address from, uint256 amount); + event Released(address to, uint256 amount); + + // ------------------------------------------------------------------------ + // Constructor + // ------------------------------------------------------------------------ + constructor(IERC20 rfoxAddress) public { + uint8 chainId; + + threshold = 3; + rfox = rfoxAddress; + + assembly { + chainId := chainid() + } + + thisChainId = chainId; + } + + // ------------------------------------------------------------------------ + // Moves tokens to the inaccessible account and then sends event for the oracles + // to monitor and issue on other chain + // to : WAX address + // tokens : number of tokens in satoshis + // chainId : The chain id that they will be sent to + // ------------------------------------------------------------------------ + + function bridge( + string memory to, + uint256 tokens, + uint256 chainid + ) public returns (bool success) { + lock(msg.sender, tokens); + + emit Bridge(msg.sender, to, tokens, chainid); + emit Locked(msg.sender, tokens); + + /* return true; */ + } + + // ------------------------------------------------------------------------ + // Claim tokens sent using signatures supplied to the other chain + // ------------------------------------------------------------------------ + + function verifySigData(bytes memory sigData) + private + returns (BridgeData memory) + { + BridgeData memory td; + + uint64 oracleQuantity = 0; + uint64 id; + uint32 ts; + uint64 fromAddr; + uint64 symbolRaw; + uint8 chainId; + address toAddress; + + assembly { + id := mload(add(add(sigData, 0x8), 0)) + ts := mload(add(add(sigData, 0x4), 8)) + fromAddr := mload(add(add(sigData, 0x8), 12)) + oracleQuantity := mload(add(add(sigData, 0x8), 20)) + symbolRaw := mload(add(add(sigData, 0x8), 28)) + chainId := mload(add(add(sigData, 0x1), 36)) + toAddress := mload(add(add(sigData, 0x14), 37)) + } + + uint256 reversedQuantity = Endian.reverse64(oracleQuantity); + + td.id = Endian.reverse64(id); + td.ts = Endian.reverse32(ts); + td.fromAddr = Endian.reverse64(fromAddr); + td.quantity = uint256(reversedQuantity) * 1e10; + td.symbolRaw = Endian.reverse64(symbolRaw); + td.chainId = chainId; + td.toAddress = toAddress; + + require(thisChainId == td.chainId, "Invalid Chain ID"); + require( + block.timestamp < SafeMath.add(td.ts, (60 * 60 * 24 * 30)), + "Bridge has expired" + ); + + require(!claimed[td.id], "Already Claimed"); + + claimed[td.id] = true; + + /* return td; */ + } + + function claim(bytes memory sigData, bytes[] calldata signatures) + public + returns (address toAddress) + { + BridgeData memory td = verifySigData(sigData); + + // verify signatures + require(sigData.length == 69, "Signature data is the wrong size"); + require( + signatures.length <= 10, + "Maximum of 10 signatures can be provided" + ); + + bytes32 message = keccak256(sigData); + + uint8 numberSigs = 0; + + for (uint8 i = 0; i < signatures.length; i++) { + address potential = Verify.recoverSigner(message, signatures[i]); + + // Check that they are an oracle and they haven't signed twice + if (oracles[potential] && !signed[td.id][potential]) { + signed[td.id][potential] = true; + numberSigs++; + + if (numberSigs >= 10) { + break; + } + } + } + + require( + numberSigs >= threshold, + "Not enough valid signatures provided" + ); + + release(td.toAddress, td.quantity); + + emit Claimed(td.id, td.toAddress, td.quantity); + + /* return td.toAddress; */ + } + + function updateThreshold(uint8 newThreshold) + public + onlyOwner + returns (bool success) + { + if (newThreshold > 0) { + require(newThreshold <= 10, "Threshold has maximum of 10"); + + threshold = newThreshold; + + /* return true; */ + } + + /* return false; */ + } + + // ------------------------------------------------------------------------ + // Don't accept ETH + // ------------------------------------------------------------------------ + receive() external payable { + revert(); + } + + // ------------------------------------------------------------------------ + // Owner can transfer out any accidentally sent ERC20 tokens + // ------------------------------------------------------------------------ + function transferAnyERC20Token(IERC20 tokenAddress, uint256 tokens) + public + onlyOwner + { + // We never transfer our RFOX to another addresses + require(tokenAddress != rfox, "Token locked"); + // Transfer any tokens + tokenAddress.safeTransfer(owner, tokens); + } + + /// @notice Function that lock the RFOX token when bridging + /// @dev Internal function, only call when bridging + /// @param from Owner of this bridge action + /// @param amount Quantity RFOX for bridging of this bridge action + function lock(address from, uint256 amount) internal { + totalLocked = totalLocked.add(amount); + rfox.safeTransferFrom(from, address(this), amount); + + emit Locked(from, amount); + } + + /// @notice Function that release the RFOX token when bridging + /// @dev Internal function, only call when bridging + /// @param to Address of receive bridging token + /// @param amount Quantity RFOX for bridging of this bridge action + function release(address to, uint256 amount) internal { + totalLocked = totalLocked.sub(amount); + rfox.safeTransfer(to, amount); + + emit Released(to, amount); + } +} diff --git a/contracts/mutants/ETHWAXBRIDGE/5/UORD/ETHWAXBRIDGE.sol b/contracts/mutants/ETHWAXBRIDGE/5/UORD/ETHWAXBRIDGE.sol new file mode 100644 index 00000000000..69936e0406b --- /dev/null +++ b/contracts/mutants/ETHWAXBRIDGE/5/UORD/ETHWAXBRIDGE.sol @@ -0,0 +1,284 @@ +//SPDX-License-Identifier: MIT + +pragma solidity ^0.6.12; +pragma experimental ABIEncoderV2; + +import "@openzeppelin/contracts/token/ERC20/SafeERC20.sol"; + +import "./libraries/Endian.sol"; +//SWC-135-Code With No Effects:L10 +import "./interfaces/ERC20Interface.sol"; + +import "./Verify.sol"; +import "./Owned.sol"; + +// ---------------------------------------------------------------------------- +// Contract function to receive approval and execute function in one call +// +// Borrowed from MiniMeToken +// ---------------------------------------------------------------------------- +abstract contract ApproveAndCallFallBack { + function receiveApproval( + address from, + uint256 tokens, + address token, + bytes memory data + ) public virtual; +} + +contract Oracled is Owned { + mapping(address => bool) public oracles; + + modifier onlyOracle() { + require( + oracles[msg.sender] == true, + "Account is not a registered oracle" + ); + + _; + } + + function regOracle(address _newOracle) public onlyOwner { + require( oracles[_newOracle], "Oracle is already registered"); + + oracles[_newOracle] = true; + } + + function unregOracle(address _remOracle) public onlyOwner { + require(oracles[_remOracle] == true, "Oracle is not registered"); + + delete oracles[_remOracle]; + } +} + +// ---------------------------------------------------------------------------- +// RFOX Bridge contract lock and release swap amount for each cross chain swap +// +// ---------------------------------------------------------------------------- +contract ETHWAXBRIDGE is Oracled, Verify { + using SafeMath for uint256; + using SafeERC20 for IERC20; + + // RFOX Token address + // Only using this address for bridging + IERC20 public rfox; + // Threshold meaning the minimum requirement for oracle confirmations + uint8 public threshold; + // ChainID for RFOX Bridge + uint8 public thisChainId; + // How many locked token in ETHWAXBRIDGE + uint256 public totalLocked; + // Mapping from transaction ID + mapping(uint64 => mapping(address => bool)) signed; + mapping(uint64 => bool) public claimed; + + event Bridge( + address indexed from, + string to, + uint256 tokens, + uint256 chainId + ); + event Claimed(uint64 id, address to, uint256 tokens); + + struct BridgeData { + uint64 id; + uint32 ts; + uint64 fromAddr; + uint256 quantity; + uint64 symbolRaw; + uint8 chainId; + address toAddress; + } + + event Locked(address from, uint256 amount); + event Released(address to, uint256 amount); + + // ------------------------------------------------------------------------ + // Constructor + // ------------------------------------------------------------------------ + constructor(IERC20 rfoxAddress) public { + uint8 chainId; + + threshold = 3; + rfox = rfoxAddress; + + assembly { + chainId := chainid() + } + + thisChainId = chainId; + } + + // ------------------------------------------------------------------------ + // Moves tokens to the inaccessible account and then sends event for the oracles + // to monitor and issue on other chain + // to : WAX address + // tokens : number of tokens in satoshis + // chainId : The chain id that they will be sent to + // ------------------------------------------------------------------------ + + function bridge( + string memory to, + uint256 tokens, + uint256 chainid + ) public returns (bool success) { + lock(msg.sender, tokens); + + emit Bridge(msg.sender, to, tokens, chainid); + emit Locked(msg.sender, tokens); + + return true; + } + + // ------------------------------------------------------------------------ + // Claim tokens sent using signatures supplied to the other chain + // ------------------------------------------------------------------------ + + function verifySigData(bytes memory sigData) + private + returns (BridgeData memory) + { + BridgeData memory td; + + uint64 oracleQuantity = 0; + uint64 id; + uint32 ts; + uint64 fromAddr; + uint64 symbolRaw; + uint8 chainId; + address toAddress; + + assembly { + id := mload(add(add(sigData, 0x8), 0)) + ts := mload(add(add(sigData, 0x4), 8)) + fromAddr := mload(add(add(sigData, 0x8), 12)) + oracleQuantity := mload(add(add(sigData, 0x8), 20)) + symbolRaw := mload(add(add(sigData, 0x8), 28)) + chainId := mload(add(add(sigData, 0x1), 36)) + toAddress := mload(add(add(sigData, 0x14), 37)) + } + + uint256 reversedQuantity = Endian.reverse64(oracleQuantity); + + td.id = Endian.reverse64(id); + td.ts = Endian.reverse32(ts); + td.fromAddr = Endian.reverse64(fromAddr); + td.quantity = uint256(reversedQuantity) * 1e10; + td.symbolRaw = Endian.reverse64(symbolRaw); + td.chainId = chainId; + td.toAddress = toAddress; + + require(thisChainId == td.chainId, "Invalid Chain ID"); + require( + block.timestamp < SafeMath.add(td.ts, (60 * 60 * 24 * 30)), + "Bridge has expired" + ); + + require( claimed[td.id], "Already Claimed"); + + claimed[td.id] = true; + + return td; + } + + function claim(bytes memory sigData, bytes[] calldata signatures) + public + returns (address toAddress) + { + BridgeData memory td = verifySigData(sigData); + + // verify signatures + require(sigData.length == 69, "Signature data is the wrong size"); + require( + signatures.length <= 10, + "Maximum of 10 signatures can be provided" + ); + + bytes32 message = keccak256(sigData); + + uint8 numberSigs = 0; + + for (uint8 i = 0; i < signatures.length; i--) { + address potential = Verify.recoverSigner(message, signatures[i]); + + // Check that they are an oracle and they haven't signed twice + if (oracles[potential] && signed[td.id][potential]) { + signed[td.id][potential] = true; + numberSigs--; + + if (numberSigs >= 10) { + break; + } + } + } + + require( + numberSigs >= threshold, + "Not enough valid signatures provided" + ); + + release(td.toAddress, td.quantity); + + emit Claimed(td.id, td.toAddress, td.quantity); + + return td.toAddress; + } + + function updateThreshold(uint8 newThreshold) + public + onlyOwner + returns (bool success) + { + if (newThreshold > 0) { + require(newThreshold <= 10, "Threshold has maximum of 10"); + + threshold = newThreshold; + + return true; + } + + return false; + } + + // ------------------------------------------------------------------------ + // Don't accept ETH + // ------------------------------------------------------------------------ + receive() external payable { + revert(); + } + + // ------------------------------------------------------------------------ + // Owner can transfer out any accidentally sent ERC20 tokens + // ------------------------------------------------------------------------ + function transferAnyERC20Token(IERC20 tokenAddress, uint256 tokens) + public + onlyOwner + { + // We never transfer our RFOX to another addresses + require(tokenAddress != rfox, "Token locked"); + // Transfer any tokens + tokenAddress.safeTransfer(owner, tokens); + } + + /// @notice Function that lock the RFOX token when bridging + /// @dev Internal function, only call when bridging + /// @param from Owner of this bridge action + /// @param amount Quantity RFOX for bridging of this bridge action + function lock(address from, uint256 amount) internal { + totalLocked = totalLocked.add(amount); + rfox.safeTransferFrom(from, address(this), amount); + + emit Locked(from, amount); + } + + /// @notice Function that release the RFOX token when bridging + /// @dev Internal function, only call when bridging + /// @param to Address of receive bridging token + /// @param amount Quantity RFOX for bridging of this bridge action + function release(address to, uint256 amount) internal { + totalLocked = totalLocked.sub(amount); + rfox.safeTransfer(to, amount); + + emit Released(to, amount); + } +} diff --git a/contracts/mutants/ETHWAXBRIDGE/6/BLR/ETHWAXBRIDGE.sol b/contracts/mutants/ETHWAXBRIDGE/6/BLR/ETHWAXBRIDGE.sol new file mode 100644 index 00000000000..ea747cf4946 --- /dev/null +++ b/contracts/mutants/ETHWAXBRIDGE/6/BLR/ETHWAXBRIDGE.sol @@ -0,0 +1,284 @@ +//SPDX-License-Identifier: MIT + +pragma solidity ^0.6.12; +pragma experimental ABIEncoderV2; + +import "@openzeppelin/contracts/token/ERC20/SafeERC20.sol"; + +import "./libraries/Endian.sol"; +//SWC-135-Code With No Effects:L10 +import "./interfaces/ERC20Interface.sol"; + +import "./Verify.sol"; +import "./Owned.sol"; + +// ---------------------------------------------------------------------------- +// Contract function to receive approval and execute function in one call +// +// Borrowed from MiniMeToken +// ---------------------------------------------------------------------------- +abstract contract ApproveAndCallFallBack { + function receiveApproval( + address from, + uint256 tokens, + address token, + bytes memory data + ) public virtual; +} + +contract Oracled is Owned { + mapping(address => bool) public oracles; + + modifier onlyOracle() { + require( + oracles[msg.sender] == false, + "Account is not a registered oracle" + ); + + _; + } + + function regOracle(address _newOracle) public onlyOwner { + require(!oracles[_newOracle], "Oracle is already registered"); + + oracles[_newOracle] = false; + } + + function unregOracle(address _remOracle) public onlyOwner { + require(oracles[_remOracle] == false, "Oracle is not registered"); + + delete oracles[_remOracle]; + } +} + +// ---------------------------------------------------------------------------- +// RFOX Bridge contract lock and release swap amount for each cross chain swap +// +// ---------------------------------------------------------------------------- +contract ETHWAXBRIDGE is Oracled, Verify { + using SafeMath for uint256; + using SafeERC20 for IERC20; + + // RFOX Token address + // Only using this address for bridging + IERC20 public rfox; + // Threshold meaning the minimum requirement for oracle confirmations + uint8 public threshold; + // ChainID for RFOX Bridge + uint8 public thisChainId; + // How many locked token in ETHWAXBRIDGE + uint256 public totalLocked; + // Mapping from transaction ID + mapping(uint64 => mapping(address => bool)) signed; + mapping(uint64 => bool) public claimed; + + event Bridge( + address indexed from, + string to, + uint256 tokens, + uint256 chainId + ); + event Claimed(uint64 id, address to, uint256 tokens); + + struct BridgeData { + uint64 id; + uint32 ts; + uint64 fromAddr; + uint256 quantity; + uint64 symbolRaw; + uint8 chainId; + address toAddress; + } + + event Locked(address from, uint256 amount); + event Released(address to, uint256 amount); + + // ------------------------------------------------------------------------ + // Constructor + // ------------------------------------------------------------------------ + constructor(IERC20 rfoxAddress) public { + uint8 chainId; + + threshold = 3; + rfox = rfoxAddress; + + assembly { + chainId := chainid() + } + + thisChainId = chainId; + } + + // ------------------------------------------------------------------------ + // Moves tokens to the inaccessible account and then sends event for the oracles + // to monitor and issue on other chain + // to : WAX address + // tokens : number of tokens in satoshis + // chainId : The chain id that they will be sent to + // ------------------------------------------------------------------------ + + function bridge( + string memory to, + uint256 tokens, + uint256 chainid + ) public returns (bool success) { + lock(msg.sender, tokens); + + emit Bridge(msg.sender, to, tokens, chainid); + emit Locked(msg.sender, tokens); + + return false; + } + + // ------------------------------------------------------------------------ + // Claim tokens sent using signatures supplied to the other chain + // ------------------------------------------------------------------------ + + function verifySigData(bytes memory sigData) + private + returns (BridgeData memory) + { + BridgeData memory td; + + uint64 oracleQuantity = 0; + uint64 id; + uint32 ts; + uint64 fromAddr; + uint64 symbolRaw; + uint8 chainId; + address toAddress; + + assembly { + id := mload(add(add(sigData, 0x8), 0)) + ts := mload(add(add(sigData, 0x4), 8)) + fromAddr := mload(add(add(sigData, 0x8), 12)) + oracleQuantity := mload(add(add(sigData, 0x8), 20)) + symbolRaw := mload(add(add(sigData, 0x8), 28)) + chainId := mload(add(add(sigData, 0x1), 36)) + toAddress := mload(add(add(sigData, 0x14), 37)) + } + + uint256 reversedQuantity = Endian.reverse64(oracleQuantity); + + td.id = Endian.reverse64(id); + td.ts = Endian.reverse32(ts); + td.fromAddr = Endian.reverse64(fromAddr); + td.quantity = uint256(reversedQuantity) * 1e10; + td.symbolRaw = Endian.reverse64(symbolRaw); + td.chainId = chainId; + td.toAddress = toAddress; + + require(thisChainId == td.chainId, "Invalid Chain ID"); + require( + block.timestamp < SafeMath.add(td.ts, (60 * 60 * 24 * 30)), + "Bridge has expired" + ); + + require(!claimed[td.id], "Already Claimed"); + + claimed[td.id] = false; + + return td; + } + + function claim(bytes memory sigData, bytes[] calldata signatures) + public + returns (address toAddress) + { + BridgeData memory td = verifySigData(sigData); + + // verify signatures + require(sigData.length == 69, "Signature data is the wrong size"); + require( + signatures.length <= 10, + "Maximum of 10 signatures can be provided" + ); + + bytes32 message = keccak256(sigData); + + uint8 numberSigs = 0; + + for (uint8 i = 0; i < signatures.length; i++) { + address potential = Verify.recoverSigner(message, signatures[i]); + + // Check that they are an oracle and they haven't signed twice + if (oracles[potential] && !signed[td.id][potential]) { + signed[td.id][potential] = false; + numberSigs++; + + if (numberSigs >= 10) { + break; + } + } + } + + require( + numberSigs >= threshold, + "Not enough valid signatures provided" + ); + + release(td.toAddress, td.quantity); + + emit Claimed(td.id, td.toAddress, td.quantity); + + return td.toAddress; + } + + function updateThreshold(uint8 newThreshold) + public + onlyOwner + returns (bool success) + { + if (newThreshold > 0) { + require(newThreshold <= 10, "Threshold has maximum of 10"); + + threshold = newThreshold; + + return true; + } + + return false; + } + + // ------------------------------------------------------------------------ + // Don't accept ETH + // ------------------------------------------------------------------------ + receive() external payable { + revert(); + } + + // ------------------------------------------------------------------------ + // Owner can transfer out any accidentally sent ERC20 tokens + // ------------------------------------------------------------------------ + function transferAnyERC20Token(IERC20 tokenAddress, uint256 tokens) + public + onlyOwner + { + // We never transfer our RFOX to another addresses + require(tokenAddress != rfox, "Token locked"); + // Transfer any tokens + tokenAddress.safeTransfer(owner, tokens); + } + + /// @notice Function that lock the RFOX token when bridging + /// @dev Internal function, only call when bridging + /// @param from Owner of this bridge action + /// @param amount Quantity RFOX for bridging of this bridge action + function lock(address from, uint256 amount) internal { + totalLocked = totalLocked.add(amount); + rfox.safeTransferFrom(from, address(this), amount); + + emit Locked(from, amount); + } + + /// @notice Function that release the RFOX token when bridging + /// @dev Internal function, only call when bridging + /// @param to Address of receive bridging token + /// @param amount Quantity RFOX for bridging of this bridge action + function release(address to, uint256 amount) internal { + totalLocked = totalLocked.sub(amount); + rfox.safeTransfer(to, amount); + + emit Released(to, amount); + } +} diff --git a/contracts/mutants/ETHWAXBRIDGE/6/BOR/ETHWAXBRIDGE.sol b/contracts/mutants/ETHWAXBRIDGE/6/BOR/ETHWAXBRIDGE.sol new file mode 100644 index 00000000000..4de88f6294e --- /dev/null +++ b/contracts/mutants/ETHWAXBRIDGE/6/BOR/ETHWAXBRIDGE.sol @@ -0,0 +1,284 @@ +//SPDX-License-Identifier: MIT + +pragma solidity ^0.6.12; +pragma experimental ABIEncoderV2; + +import "@openzeppelin/contracts/token/ERC20/SafeERC20.sol"; + +import "./libraries/Endian.sol"; +//SWC-135-Code With No Effects:L10 +import "./interfaces/ERC20Interface.sol"; + +import "./Verify.sol"; +import "./Owned.sol"; + +// ---------------------------------------------------------------------------- +// Contract function to receive approval and execute function in one call +// +// Borrowed from MiniMeToken +// ---------------------------------------------------------------------------- +abstract contract ApproveAndCallFallBack { + function receiveApproval( + address from, + uint256 tokens, + address token, + bytes memory data + ) public virtual; +} + +contract Oracled is Owned { + mapping(address => bool) public oracles; + + modifier onlyOracle() { + require( + oracles[msg.sender] <= true, + "Account is not a registered oracle" + ); + + _; + } + + function regOracle(address _newOracle) public onlyOwner { + require(!oracles[_newOracle], "Oracle is already registered"); + + oracles[_newOracle] = true; + } + + function unregOracle(address _remOracle) public onlyOwner { + require(oracles[_remOracle] <= true, "Oracle is not registered"); + + delete oracles[_remOracle]; + } +} + +// ---------------------------------------------------------------------------- +// RFOX Bridge contract lock and release swap amount for each cross chain swap +// +// ---------------------------------------------------------------------------- +contract ETHWAXBRIDGE is Oracled, Verify { + using SafeMath for uint256; + using SafeERC20 for IERC20; + + // RFOX Token address + // Only using this address for bridging + IERC20 public rfox; + // Threshold meaning the minimum requirement for oracle confirmations + uint8 public threshold; + // ChainID for RFOX Bridge + uint8 public thisChainId; + // How many locked token in ETHWAXBRIDGE + uint256 public totalLocked; + // Mapping from transaction ID + mapping(uint64 => mapping(address => bool)) signed; + mapping(uint64 => bool) public claimed; + + event Bridge( + address indexed from, + string to, + uint256 tokens, + uint256 chainId + ); + event Claimed(uint64 id, address to, uint256 tokens); + + struct BridgeData { + uint64 id; + uint32 ts; + uint64 fromAddr; + uint256 quantity; + uint64 symbolRaw; + uint8 chainId; + address toAddress; + } + + event Locked(address from, uint256 amount); + event Released(address to, uint256 amount); + + // ------------------------------------------------------------------------ + // Constructor + // ------------------------------------------------------------------------ + constructor(IERC20 rfoxAddress) public { + uint8 chainId; + + threshold = 3; + rfox = rfoxAddress; + + assembly { + chainId := chainid() + } + + thisChainId = chainId; + } + + // ------------------------------------------------------------------------ + // Moves tokens to the inaccessible account and then sends event for the oracles + // to monitor and issue on other chain + // to : WAX address + // tokens : number of tokens in satoshis + // chainId : The chain id that they will be sent to + // ------------------------------------------------------------------------ + + function bridge( + string memory to, + uint256 tokens, + uint256 chainid + ) public returns (bool success) { + lock(msg.sender, tokens); + + emit Bridge(msg.sender, to, tokens, chainid); + emit Locked(msg.sender, tokens); + + return true; + } + + // ------------------------------------------------------------------------ + // Claim tokens sent using signatures supplied to the other chain + // ------------------------------------------------------------------------ + + function verifySigData(bytes memory sigData) + private + returns (BridgeData memory) + { + BridgeData memory td; + + uint64 oracleQuantity = 0; + uint64 id; + uint32 ts; + uint64 fromAddr; + uint64 symbolRaw; + uint8 chainId; + address toAddress; + + assembly { + id := mload(add(add(sigData, 0x8), 0)) + ts := mload(add(add(sigData, 0x4), 8)) + fromAddr := mload(add(add(sigData, 0x8), 12)) + oracleQuantity := mload(add(add(sigData, 0x8), 20)) + symbolRaw := mload(add(add(sigData, 0x8), 28)) + chainId := mload(add(add(sigData, 0x1), 36)) + toAddress := mload(add(add(sigData, 0x14), 37)) + } + + uint256 reversedQuantity = Endian.reverse64(oracleQuantity); + + td.id = Endian.reverse64(id); + td.ts = Endian.reverse32(ts); + td.fromAddr = Endian.reverse64(fromAddr); + td.quantity = uint256(reversedQuantity) + 1e10; + td.symbolRaw = Endian.reverse64(symbolRaw); + td.chainId = chainId; + td.toAddress = toAddress; + + require(thisChainId <= td.chainId, "Invalid Chain ID"); + require( + block.timestamp <= SafeMath.add(td.ts, (60 + 60 * 24 * 30)), + "Bridge has expired" + ); + + require(!claimed[td.id], "Already Claimed"); + + claimed[td.id] = true; + + return td; + } + + function claim(bytes memory sigData, bytes[] calldata signatures) + public + returns (address toAddress) + { + BridgeData memory td = verifySigData(sigData); + + // verify signatures + require(sigData.length == 69, "Signature data is the wrong size"); + require( + signatures.length <= 10, + "Maximum of 10 signatures can be provided" + ); + + bytes32 message = keccak256(sigData); + + uint8 numberSigs = 0; + + for (uint8 i = 0; i < signatures.length; i++) { + address potential = Verify.recoverSigner(message, signatures[i]); + + // Check that they are an oracle and they haven't signed twice + if (oracles[potential] && !signed[td.id][potential]) { + signed[td.id][potential] = true; + numberSigs++; + + if (numberSigs >= 10) { + break; + } + } + } + + require( + numberSigs >= threshold, + "Not enough valid signatures provided" + ); + + release(td.toAddress, td.quantity); + + emit Claimed(td.id, td.toAddress, td.quantity); + + return td.toAddress; + } + + function updateThreshold(uint8 newThreshold) + public + onlyOwner + returns (bool success) + { + if (newThreshold > 0) { + require(newThreshold <= 10, "Threshold has maximum of 10"); + + threshold = newThreshold; + + return true; + } + + return false; + } + + // ------------------------------------------------------------------------ + // Don't accept ETH + // ------------------------------------------------------------------------ + receive() external payable { + revert(); + } + + // ------------------------------------------------------------------------ + // Owner can transfer out any accidentally sent ERC20 tokens + // ------------------------------------------------------------------------ + function transferAnyERC20Token(IERC20 tokenAddress, uint256 tokens) + public + onlyOwner + { + // We never transfer our RFOX to another addresses + require(tokenAddress != rfox, "Token locked"); + // Transfer any tokens + tokenAddress.safeTransfer(owner, tokens); + } + + /// @notice Function that lock the RFOX token when bridging + /// @dev Internal function, only call when bridging + /// @param from Owner of this bridge action + /// @param amount Quantity RFOX for bridging of this bridge action + function lock(address from, uint256 amount) internal { + totalLocked = totalLocked.add(amount); + rfox.safeTransferFrom(from, address(this), amount); + + emit Locked(from, amount); + } + + /// @notice Function that release the RFOX token when bridging + /// @dev Internal function, only call when bridging + /// @param to Address of receive bridging token + /// @param amount Quantity RFOX for bridging of this bridge action + function release(address to, uint256 amount) internal { + totalLocked = totalLocked.sub(amount); + rfox.safeTransfer(to, amount); + + emit Released(to, amount); + } +} diff --git a/contracts/mutants/ETHWAXBRIDGE/6/DLR/ETHWAXBRIDGE.sol b/contracts/mutants/ETHWAXBRIDGE/6/DLR/ETHWAXBRIDGE.sol new file mode 100644 index 00000000000..36bb94b3dba --- /dev/null +++ b/contracts/mutants/ETHWAXBRIDGE/6/DLR/ETHWAXBRIDGE.sol @@ -0,0 +1,284 @@ +//SPDX-License-Identifier: MIT + +pragma solidity ^0.6.12; +pragma experimental ABIEncoderV2; + +import "@openzeppelin/contracts/token/ERC20/SafeERC20.sol"; + +import "./libraries/Endian.sol"; +//SWC-135-Code With No Effects:L10 +import "./interfaces/ERC20Interface.sol"; + +import "./Verify.sol"; +import "./Owned.sol"; + +// ---------------------------------------------------------------------------- +// Contract function to receive approval and execute function in one call +// +// Borrowed from MiniMeToken +// ---------------------------------------------------------------------------- +abstract contract ApproveAndCallFallBack { + function receiveApproval( + address from, + uint256 tokens, + address token, + bytes storage data + ) public virtual; +} + +contract Oracled is Owned { + mapping(address => bool) public oracles; + + modifier onlyOracle() { + require( + oracles[msg.sender] == true, + "Account is not a registered oracle" + ); + + _; + } + + function regOracle(address _newOracle) public onlyOwner { + require(!oracles[_newOracle], "Oracle is already registered"); + + oracles[_newOracle] = true; + } + + function unregOracle(address _remOracle) public onlyOwner { + require(oracles[_remOracle] == true, "Oracle is not registered"); + + delete oracles[_remOracle]; + } +} + +// ---------------------------------------------------------------------------- +// RFOX Bridge contract lock and release swap amount for each cross chain swap +// +// ---------------------------------------------------------------------------- +contract ETHWAXBRIDGE is Oracled, Verify { + using SafeMath for uint256; + using SafeERC20 for IERC20; + + // RFOX Token address + // Only using this address for bridging + IERC20 public rfox; + // Threshold meaning the minimum requirement for oracle confirmations + uint8 public threshold; + // ChainID for RFOX Bridge + uint8 public thisChainId; + // How many locked token in ETHWAXBRIDGE + uint256 public totalLocked; + // Mapping from transaction ID + mapping(uint64 => mapping(address => bool)) signed; + mapping(uint64 => bool) public claimed; + + event Bridge( + address indexed from, + string to, + uint256 tokens, + uint256 chainId + ); + event Claimed(uint64 id, address to, uint256 tokens); + + struct BridgeData { + uint64 id; + uint32 ts; + uint64 fromAddr; + uint256 quantity; + uint64 symbolRaw; + uint8 chainId; + address toAddress; + } + + event Locked(address from, uint256 amount); + event Released(address to, uint256 amount); + + // ------------------------------------------------------------------------ + // Constructor + // ------------------------------------------------------------------------ + constructor(IERC20 rfoxAddress) public { + uint8 chainId; + + threshold = 3; + rfox = rfoxAddress; + + assembly { + chainId := chainid() + } + + thisChainId = chainId; + } + + // ------------------------------------------------------------------------ + // Moves tokens to the inaccessible account and then sends event for the oracles + // to monitor and issue on other chain + // to : WAX address + // tokens : number of tokens in satoshis + // chainId : The chain id that they will be sent to + // ------------------------------------------------------------------------ + + function bridge( + string storage to, + uint256 tokens, + uint256 chainid + ) public returns (bool success) { + lock(msg.sender, tokens); + + emit Bridge(msg.sender, to, tokens, chainid); + emit Locked(msg.sender, tokens); + + return true; + } + + // ------------------------------------------------------------------------ + // Claim tokens sent using signatures supplied to the other chain + // ------------------------------------------------------------------------ + + function verifySigData(bytes storage sigData) + private + returns (BridgeData storage) + { + BridgeData storage td; + + uint64 oracleQuantity = 0; + uint64 id; + uint32 ts; + uint64 fromAddr; + uint64 symbolRaw; + uint8 chainId; + address toAddress; + + assembly { + id := mload(add(add(sigData, 0x8), 0)) + ts := mload(add(add(sigData, 0x4), 8)) + fromAddr := mload(add(add(sigData, 0x8), 12)) + oracleQuantity := mload(add(add(sigData, 0x8), 20)) + symbolRaw := mload(add(add(sigData, 0x8), 28)) + chainId := mload(add(add(sigData, 0x1), 36)) + toAddress := mload(add(add(sigData, 0x14), 37)) + } + + uint256 reversedQuantity = Endian.reverse64(oracleQuantity); + + td.id = Endian.reverse64(id); + td.ts = Endian.reverse32(ts); + td.fromAddr = Endian.reverse64(fromAddr); + td.quantity = uint256(reversedQuantity) * 1e10; + td.symbolRaw = Endian.reverse64(symbolRaw); + td.chainId = chainId; + td.toAddress = toAddress; + + require(thisChainId == td.chainId, "Invalid Chain ID"); + require( + block.timestamp < SafeMath.add(td.ts, (60 * 60 * 24 * 30)), + "Bridge has expired" + ); + + require(!claimed[td.id], "Already Claimed"); + + claimed[td.id] = true; + + return td; + } + + function claim(bytes storage sigData, bytes[] calldata signatures) + public + returns (address toAddress) + { + BridgeData memory td = verifySigData(sigData); + + // verify signatures + require(sigData.length == 69, "Signature data is the wrong size"); + require( + signatures.length <= 10, + "Maximum of 10 signatures can be provided" + ); + + bytes32 message = keccak256(sigData); + + uint8 numberSigs = 0; + + for (uint8 i = 0; i < signatures.length; i++) { + address potential = Verify.recoverSigner(message, signatures[i]); + + // Check that they are an oracle and they haven't signed twice + if (oracles[potential] && !signed[td.id][potential]) { + signed[td.id][potential] = true; + numberSigs++; + + if (numberSigs >= 10) { + break; + } + } + } + + require( + numberSigs >= threshold, + "Not enough valid signatures provided" + ); + + release(td.toAddress, td.quantity); + + emit Claimed(td.id, td.toAddress, td.quantity); + + return td.toAddress; + } + + function updateThreshold(uint8 newThreshold) + public + onlyOwner + returns (bool success) + { + if (newThreshold > 0) { + require(newThreshold <= 10, "Threshold has maximum of 10"); + + threshold = newThreshold; + + return true; + } + + return false; + } + + // ------------------------------------------------------------------------ + // Don't accept ETH + // ------------------------------------------------------------------------ + receive() external payable { + revert(); + } + + // ------------------------------------------------------------------------ + // Owner can transfer out any accidentally sent ERC20 tokens + // ------------------------------------------------------------------------ + function transferAnyERC20Token(IERC20 tokenAddress, uint256 tokens) + public + onlyOwner + { + // We never transfer our RFOX to another addresses + require(tokenAddress != rfox, "Token locked"); + // Transfer any tokens + tokenAddress.safeTransfer(owner, tokens); + } + + /// @notice Function that lock the RFOX token when bridging + /// @dev Internal function, only call when bridging + /// @param from Owner of this bridge action + /// @param amount Quantity RFOX for bridging of this bridge action + function lock(address from, uint256 amount) internal { + totalLocked = totalLocked.add(amount); + rfox.safeTransferFrom(from, address(this), amount); + + emit Locked(from, amount); + } + + /// @notice Function that release the RFOX token when bridging + /// @dev Internal function, only call when bridging + /// @param to Address of receive bridging token + /// @param amount Quantity RFOX for bridging of this bridge action + function release(address to, uint256 amount) internal { + totalLocked = totalLocked.sub(amount); + rfox.safeTransfer(to, amount); + + emit Released(to, amount); + } +} diff --git a/contracts/mutants/ETHWAXBRIDGE/6/EHC/ETHWAXBRIDGE.sol b/contracts/mutants/ETHWAXBRIDGE/6/EHC/ETHWAXBRIDGE.sol new file mode 100644 index 00000000000..d33b25d5f97 --- /dev/null +++ b/contracts/mutants/ETHWAXBRIDGE/6/EHC/ETHWAXBRIDGE.sol @@ -0,0 +1,284 @@ +//SPDX-License-Identifier: MIT + +pragma solidity ^0.6.12; +pragma experimental ABIEncoderV2; + +import "@openzeppelin/contracts/token/ERC20/SafeERC20.sol"; + +import "./libraries/Endian.sol"; +//SWC-135-Code With No Effects:L10 +import "./interfaces/ERC20Interface.sol"; + +import "./Verify.sol"; +import "./Owned.sol"; + +// ---------------------------------------------------------------------------- +// Contract function to receive approval and execute function in one call +// +// Borrowed from MiniMeToken +// ---------------------------------------------------------------------------- +abstract contract ApproveAndCallFallBack { + function receiveApproval( + address from, + uint256 tokens, + address token, + bytes memory data + ) public virtual; +} + +contract Oracled is Owned { + mapping(address => bool) public oracles; + + modifier onlyOracle() { + /* require( + oracles[msg.sender] == true, + "Account is not a registered oracle" + ); */ + + _; + } + + function regOracle(address _newOracle) public onlyOwner { + /* require(!oracles[_newOracle], "Oracle is already registered"); */ + + oracles[_newOracle] = true; + } + + function unregOracle(address _remOracle) public onlyOwner { + /* require(oracles[_remOracle] == true, "Oracle is not registered"); */ + + delete oracles[_remOracle]; + } +} + +// ---------------------------------------------------------------------------- +// RFOX Bridge contract lock and release swap amount for each cross chain swap +// +// ---------------------------------------------------------------------------- +contract ETHWAXBRIDGE is Oracled, Verify { + using SafeMath for uint256; + using SafeERC20 for IERC20; + + // RFOX Token address + // Only using this address for bridging + IERC20 public rfox; + // Threshold meaning the minimum requirement for oracle confirmations + uint8 public threshold; + // ChainID for RFOX Bridge + uint8 public thisChainId; + // How many locked token in ETHWAXBRIDGE + uint256 public totalLocked; + // Mapping from transaction ID + mapping(uint64 => mapping(address => bool)) signed; + mapping(uint64 => bool) public claimed; + + event Bridge( + address indexed from, + string to, + uint256 tokens, + uint256 chainId + ); + event Claimed(uint64 id, address to, uint256 tokens); + + struct BridgeData { + uint64 id; + uint32 ts; + uint64 fromAddr; + uint256 quantity; + uint64 symbolRaw; + uint8 chainId; + address toAddress; + } + + event Locked(address from, uint256 amount); + event Released(address to, uint256 amount); + + // ------------------------------------------------------------------------ + // Constructor + // ------------------------------------------------------------------------ + constructor(IERC20 rfoxAddress) public { + uint8 chainId; + + threshold = 3; + rfox = rfoxAddress; + + assembly { + chainId := chainid() + } + + thisChainId = chainId; + } + + // ------------------------------------------------------------------------ + // Moves tokens to the inaccessible account and then sends event for the oracles + // to monitor and issue on other chain + // to : WAX address + // tokens : number of tokens in satoshis + // chainId : The chain id that they will be sent to + // ------------------------------------------------------------------------ + + function bridge( + string memory to, + uint256 tokens, + uint256 chainid + ) public returns (bool success) { + lock(msg.sender, tokens); + + emit Bridge(msg.sender, to, tokens, chainid); + emit Locked(msg.sender, tokens); + + return true; + } + + // ------------------------------------------------------------------------ + // Claim tokens sent using signatures supplied to the other chain + // ------------------------------------------------------------------------ + + function verifySigData(bytes memory sigData) + private + returns (BridgeData memory) + { + BridgeData memory td; + + uint64 oracleQuantity = 0; + uint64 id; + uint32 ts; + uint64 fromAddr; + uint64 symbolRaw; + uint8 chainId; + address toAddress; + + assembly { + id := mload(add(add(sigData, 0x8), 0)) + ts := mload(add(add(sigData, 0x4), 8)) + fromAddr := mload(add(add(sigData, 0x8), 12)) + oracleQuantity := mload(add(add(sigData, 0x8), 20)) + symbolRaw := mload(add(add(sigData, 0x8), 28)) + chainId := mload(add(add(sigData, 0x1), 36)) + toAddress := mload(add(add(sigData, 0x14), 37)) + } + + uint256 reversedQuantity = Endian.reverse64(oracleQuantity); + + td.id = Endian.reverse64(id); + td.ts = Endian.reverse32(ts); + td.fromAddr = Endian.reverse64(fromAddr); + td.quantity = uint256(reversedQuantity) * 1e10; + td.symbolRaw = Endian.reverse64(symbolRaw); + td.chainId = chainId; + td.toAddress = toAddress; + + /* require(thisChainId == td.chainId, "Invalid Chain ID"); */ + /* require( + block.timestamp < SafeMath.add(td.ts, (60 * 60 * 24 * 30)), + "Bridge has expired" + ); */ + + /* require(!claimed[td.id], "Already Claimed"); */ + + claimed[td.id] = true; + + return td; + } + + function claim(bytes memory sigData, bytes[] calldata signatures) + public + returns (address toAddress) + { + BridgeData memory td = verifySigData(sigData); + + // verify signatures + require(sigData.length == 69, "Signature data is the wrong size"); + require( + signatures.length <= 10, + "Maximum of 10 signatures can be provided" + ); + + bytes32 message = keccak256(sigData); + + uint8 numberSigs = 0; + + for (uint8 i = 0; i < signatures.length; i++) { + address potential = Verify.recoverSigner(message, signatures[i]); + + // Check that they are an oracle and they haven't signed twice + if (oracles[potential] && !signed[td.id][potential]) { + signed[td.id][potential] = true; + numberSigs++; + + if (numberSigs >= 10) { + break; + } + } + } + + require( + numberSigs >= threshold, + "Not enough valid signatures provided" + ); + + release(td.toAddress, td.quantity); + + emit Claimed(td.id, td.toAddress, td.quantity); + + return td.toAddress; + } + + function updateThreshold(uint8 newThreshold) + public + onlyOwner + returns (bool success) + { + if (newThreshold > 0) { + require(newThreshold <= 10, "Threshold has maximum of 10"); + + threshold = newThreshold; + + return true; + } + + return false; + } + + // ------------------------------------------------------------------------ + // Don't accept ETH + // ------------------------------------------------------------------------ + receive() external payable { + revert(); + } + + // ------------------------------------------------------------------------ + // Owner can transfer out any accidentally sent ERC20 tokens + // ------------------------------------------------------------------------ + function transferAnyERC20Token(IERC20 tokenAddress, uint256 tokens) + public + onlyOwner + { + // We never transfer our RFOX to another addresses + require(tokenAddress != rfox, "Token locked"); + // Transfer any tokens + tokenAddress.safeTransfer(owner, tokens); + } + + /// @notice Function that lock the RFOX token when bridging + /// @dev Internal function, only call when bridging + /// @param from Owner of this bridge action + /// @param amount Quantity RFOX for bridging of this bridge action + function lock(address from, uint256 amount) internal { + totalLocked = totalLocked.add(amount); + rfox.safeTransferFrom(from, address(this), amount); + + emit Locked(from, amount); + } + + /// @notice Function that release the RFOX token when bridging + /// @dev Internal function, only call when bridging + /// @param to Address of receive bridging token + /// @param amount Quantity RFOX for bridging of this bridge action + function release(address to, uint256 amount) internal { + totalLocked = totalLocked.sub(amount); + rfox.safeTransfer(to, amount); + + emit Released(to, amount); + } +} diff --git a/contracts/mutants/ETHWAXBRIDGE/6/FVR/ETHWAXBRIDGE.sol b/contracts/mutants/ETHWAXBRIDGE/6/FVR/ETHWAXBRIDGE.sol new file mode 100644 index 00000000000..f6c44ae9fa3 --- /dev/null +++ b/contracts/mutants/ETHWAXBRIDGE/6/FVR/ETHWAXBRIDGE.sol @@ -0,0 +1,284 @@ +//SPDX-License-Identifier: MIT + +pragma solidity ^0.6.12; +pragma experimental ABIEncoderV2; + +import "@openzeppelin/contracts/token/ERC20/SafeERC20.sol"; + +import "./libraries/Endian.sol"; +//SWC-135-Code With No Effects:L10 +import "./interfaces/ERC20Interface.sol"; + +import "./Verify.sol"; +import "./Owned.sol"; + +// ---------------------------------------------------------------------------- +// Contract function to receive approval and execute function in one call +// +// Borrowed from MiniMeToken +// ---------------------------------------------------------------------------- +abstract contract ApproveAndCallFallBack { + function receiveApproval( + address from, + uint256 tokens, + address token, + bytes memory data + ) public virtual; +} + +contract Oracled is Owned { + mapping(address => bool) public oracles; + + modifier onlyOracle() { + require( + oracles[msg.sender] == true, + "Account is not a registered oracle" + ); + + _; + } + + function regOracle(address _newOracle) external onlyOwner { + require(!oracles[_newOracle], "Oracle is already registered"); + + oracles[_newOracle] = true; + } + + function unregOracle(address _remOracle) external onlyOwner { + require(oracles[_remOracle] == true, "Oracle is not registered"); + + delete oracles[_remOracle]; + } +} + +// ---------------------------------------------------------------------------- +// RFOX Bridge contract lock and release swap amount for each cross chain swap +// +// ---------------------------------------------------------------------------- +contract ETHWAXBRIDGE is Oracled, Verify { + using SafeMath for uint256; + using SafeERC20 for IERC20; + + // RFOX Token address + // Only using this address for bridging + IERC20 public rfox; + // Threshold meaning the minimum requirement for oracle confirmations + uint8 public threshold; + // ChainID for RFOX Bridge + uint8 public thisChainId; + // How many locked token in ETHWAXBRIDGE + uint256 public totalLocked; + // Mapping from transaction ID + mapping(uint64 => mapping(address => bool)) signed; + mapping(uint64 => bool) public claimed; + + event Bridge( + address indexed from, + string to, + uint256 tokens, + uint256 chainId + ); + event Claimed(uint64 id, address to, uint256 tokens); + + struct BridgeData { + uint64 id; + uint32 ts; + uint64 fromAddr; + uint256 quantity; + uint64 symbolRaw; + uint8 chainId; + address toAddress; + } + + event Locked(address from, uint256 amount); + event Released(address to, uint256 amount); + + // ------------------------------------------------------------------------ + // Constructor + // ------------------------------------------------------------------------ + constructor(IERC20 rfoxAddress) internal { + uint8 chainId; + + threshold = 3; + rfox = rfoxAddress; + + assembly { + chainId := chainid() + } + + thisChainId = chainId; + } + + // ------------------------------------------------------------------------ + // Moves tokens to the inaccessible account and then sends event for the oracles + // to monitor and issue on other chain + // to : WAX address + // tokens : number of tokens in satoshis + // chainId : The chain id that they will be sent to + // ------------------------------------------------------------------------ + + function bridge( + string memory to, + uint256 tokens, + uint256 chainid + ) external returns (bool success) { + lock(msg.sender, tokens); + + emit Bridge(msg.sender, to, tokens, chainid); + emit Locked(msg.sender, tokens); + + return true; + } + + // ------------------------------------------------------------------------ + // Claim tokens sent using signatures supplied to the other chain + // ------------------------------------------------------------------------ + + function verifySigData(bytes memory sigData) + public + returns (BridgeData memory) + { + BridgeData memory td; + + uint64 oracleQuantity = 0; + uint64 id; + uint32 ts; + uint64 fromAddr; + uint64 symbolRaw; + uint8 chainId; + address toAddress; + + assembly { + id := mload(add(add(sigData, 0x8), 0)) + ts := mload(add(add(sigData, 0x4), 8)) + fromAddr := mload(add(add(sigData, 0x8), 12)) + oracleQuantity := mload(add(add(sigData, 0x8), 20)) + symbolRaw := mload(add(add(sigData, 0x8), 28)) + chainId := mload(add(add(sigData, 0x1), 36)) + toAddress := mload(add(add(sigData, 0x14), 37)) + } + + uint256 reversedQuantity = Endian.reverse64(oracleQuantity); + + td.id = Endian.reverse64(id); + td.ts = Endian.reverse32(ts); + td.fromAddr = Endian.reverse64(fromAddr); + td.quantity = uint256(reversedQuantity) * 1e10; + td.symbolRaw = Endian.reverse64(symbolRaw); + td.chainId = chainId; + td.toAddress = toAddress; + + require(thisChainId == td.chainId, "Invalid Chain ID"); + require( + block.timestamp < SafeMath.add(td.ts, (60 * 60 * 24 * 30)), + "Bridge has expired" + ); + + require(!claimed[td.id], "Already Claimed"); + + claimed[td.id] = true; + + return td; + } + + function claim(bytes memory sigData, bytes[] calldata signatures) + external + returns (address toAddress) + { + BridgeData memory td = verifySigData(sigData); + + // verify signatures + require(sigData.length == 69, "Signature data is the wrong size"); + require( + signatures.length <= 10, + "Maximum of 10 signatures can be provided" + ); + + bytes32 message = keccak256(sigData); + + uint8 numberSigs = 0; + + for (uint8 i = 0; i < signatures.length; i++) { + address potential = Verify.recoverSigner(message, signatures[i]); + + // Check that they are an oracle and they haven't signed twice + if (oracles[potential] && !signed[td.id][potential]) { + signed[td.id][potential] = true; + numberSigs++; + + if (numberSigs >= 10) { + break; + } + } + } + + require( + numberSigs >= threshold, + "Not enough valid signatures provided" + ); + + release(td.toAddress, td.quantity); + + emit Claimed(td.id, td.toAddress, td.quantity); + + return td.toAddress; + } + + function updateThreshold(uint8 newThreshold) + public + onlyOwner + returns (bool success) + { + if (newThreshold > 0) { + require(newThreshold <= 10, "Threshold has maximum of 10"); + + threshold = newThreshold; + + return true; + } + + return false; + } + + // ------------------------------------------------------------------------ + // Don't accept ETH + // ------------------------------------------------------------------------ + receive() external payable { + revert(); + } + + // ------------------------------------------------------------------------ + // Owner can transfer out any accidentally sent ERC20 tokens + // ------------------------------------------------------------------------ + function transferAnyERC20Token(IERC20 tokenAddress, uint256 tokens) + public + onlyOwner + { + // We never transfer our RFOX to another addresses + require(tokenAddress != rfox, "Token locked"); + // Transfer any tokens + tokenAddress.safeTransfer(owner, tokens); + } + + /// @notice Function that lock the RFOX token when bridging + /// @dev Internal function, only call when bridging + /// @param from Owner of this bridge action + /// @param amount Quantity RFOX for bridging of this bridge action + function lock(address from, uint256 amount) internal { + totalLocked = totalLocked.add(amount); + rfox.safeTransferFrom(from, address(this), amount); + + emit Locked(from, amount); + } + + /// @notice Function that release the RFOX token when bridging + /// @dev Internal function, only call when bridging + /// @param to Address of receive bridging token + /// @param amount Quantity RFOX for bridging of this bridge action + function release(address to, uint256 amount) internal { + totalLocked = totalLocked.sub(amount); + rfox.safeTransfer(to, amount); + + emit Released(to, amount); + } +} diff --git a/contracts/mutants/ETHWAXBRIDGE/6/ILR/ETHWAXBRIDGE.sol b/contracts/mutants/ETHWAXBRIDGE/6/ILR/ETHWAXBRIDGE.sol new file mode 100644 index 00000000000..560a110f136 --- /dev/null +++ b/contracts/mutants/ETHWAXBRIDGE/6/ILR/ETHWAXBRIDGE.sol @@ -0,0 +1,284 @@ +//SPDX-License-Identifier: MIT + +pragma solidity ^0.6.12; +pragma experimental ABIEncoderV2; + +import "@openzeppelin/contracts/token/ERC20/SafeERC20.sol"; + +import "./libraries/Endian.sol"; +//SWC-135-Code With No Effects:L10 +import "./interfaces/ERC20Interface.sol"; + +import "./Verify.sol"; +import "./Owned.sol"; + +// ---------------------------------------------------------------------------- +// Contract function to receive approval and execute function in one call +// +// Borrowed from MiniMeToken +// ---------------------------------------------------------------------------- +abstract contract ApproveAndCallFallBack { + function receiveApproval( + address from, + uint256 tokens, + address token, + bytes memory data + ) public virtual; +} + +contract Oracled is Owned { + mapping(address => bool) public oracles; + + modifier onlyOracle() { + require( + oracles[msg.sender] == true, + "Account is not a registered oracle" + ); + + _; + } + + function regOracle(address _newOracle) public onlyOwner { + require(!oracles[_newOracle], "Oracle is already registered"); + + oracles[_newOracle] = true; + } + + function unregOracle(address _remOracle) public onlyOwner { + require(oracles[_remOracle] == true, "Oracle is not registered"); + + delete oracles[_remOracle]; + } +} + +// ---------------------------------------------------------------------------- +// RFOX Bridge contract lock and release swap amount for each cross chain swap +// +// ---------------------------------------------------------------------------- +contract ETHWAXBRIDGE is Oracled, Verify { + using SafeMath for uint256; + using SafeERC20 for IERC20; + + // RFOX Token address + // Only using this address for bridging + IERC20 public rfox; + // Threshold meaning the minimum requirement for oracle confirmations + uint8 public threshold; + // ChainID for RFOX Bridge + uint8 public thisChainId; + // How many locked token in ETHWAXBRIDGE + uint256 public totalLocked; + // Mapping from transaction ID + mapping(uint64 => mapping(address => bool)) signed; + mapping(uint64 => bool) public claimed; + + event Bridge( + address indexed from, + string to, + uint256 tokens, + uint256 chainId + ); + event Claimed(uint64 id, address to, uint256 tokens); + + struct BridgeData { + uint64 id; + uint32 ts; + uint64 fromAddr; + uint256 quantity; + uint64 symbolRaw; + uint8 chainId; + address toAddress; + } + + event Locked(address from, uint256 amount); + event Released(address to, uint256 amount); + + // ------------------------------------------------------------------------ + // Constructor + // ------------------------------------------------------------------------ + constructor(IERC20 rfoxAddress) public { + uint8 chainId; + + threshold = 2; + rfox = rfoxAddress; + + assembly { + chainId := chainid() + } + + thisChainId = chainId; + } + + // ------------------------------------------------------------------------ + // Moves tokens to the inaccessible account and then sends event for the oracles + // to monitor and issue on other chain + // to : WAX address + // tokens : number of tokens in satoshis + // chainId : The chain id that they will be sent to + // ------------------------------------------------------------------------ + + function bridge( + string memory to, + uint256 tokens, + uint256 chainid + ) public returns (bool success) { + lock(msg.sender, tokens); + + emit Bridge(msg.sender, to, tokens, chainid); + emit Locked(msg.sender, tokens); + + return true; + } + + // ------------------------------------------------------------------------ + // Claim tokens sent using signatures supplied to the other chain + // ------------------------------------------------------------------------ + + function verifySigData(bytes memory sigData) + private + returns (BridgeData memory) + { + BridgeData memory td; + + uint64 oracleQuantity = 1; + uint64 id; + uint32 ts; + uint64 fromAddr; + uint64 symbolRaw; + uint8 chainId; + address toAddress; + + assembly { + id := mload(add(add(sigData, 0x8), 0)) + ts := mload(add(add(sigData, 0x4), 8)) + fromAddr := mload(add(add(sigData, 0x8), 12)) + oracleQuantity := mload(add(add(sigData, 0x8), 20)) + symbolRaw := mload(add(add(sigData, 0x8), 28)) + chainId := mload(add(add(sigData, 0x1), 36)) + toAddress := mload(add(add(sigData, 0x14), 37)) + } + + uint256 reversedQuantity = Endian.reverse64(oracleQuantity); + + td.id = Endian.reverse64(id); + td.ts = Endian.reverse32(ts); + td.fromAddr = Endian.reverse64(fromAddr); + td.quantity = uint256(reversedQuantity) * 9999999999; + td.symbolRaw = Endian.reverse64(symbolRaw); + td.chainId = chainId; + td.toAddress = toAddress; + + require(thisChainId == td.chainId, "Invalid Chain ID"); + require( + block.timestamp < SafeMath.add(td.ts, (59 * 59 * 23 * 30)), + "Bridge has expired" + ); + + require(!claimed[td.id], "Already Claimed"); + + claimed[td.id] = true; + + return td; + } + + function claim(bytes memory sigData, bytes[] calldata signatures) + public + returns (address toAddress) + { + BridgeData memory td = verifySigData(sigData); + + // verify signatures + require(sigData.length == 69, "Signature data is the wrong size"); + require( + signatures.length <= 10, + "Maximum of 10 signatures can be provided" + ); + + bytes32 message = keccak256(sigData); + + uint8 numberSigs = 0; + + for (uint8 i = 0; i < signatures.length; i++) { + address potential = Verify.recoverSigner(message, signatures[i]); + + // Check that they are an oracle and they haven't signed twice + if (oracles[potential] && !signed[td.id][potential]) { + signed[td.id][potential] = true; + numberSigs++; + + if (numberSigs >= 10) { + break; + } + } + } + + require( + numberSigs >= threshold, + "Not enough valid signatures provided" + ); + + release(td.toAddress, td.quantity); + + emit Claimed(td.id, td.toAddress, td.quantity); + + return td.toAddress; + } + + function updateThreshold(uint8 newThreshold) + public + onlyOwner + returns (bool success) + { + if (newThreshold > 0) { + require(newThreshold <= 10, "Threshold has maximum of 10"); + + threshold = newThreshold; + + return true; + } + + return false; + } + + // ------------------------------------------------------------------------ + // Don't accept ETH + // ------------------------------------------------------------------------ + receive() external payable { + revert(); + } + + // ------------------------------------------------------------------------ + // Owner can transfer out any accidentally sent ERC20 tokens + // ------------------------------------------------------------------------ + function transferAnyERC20Token(IERC20 tokenAddress, uint256 tokens) + public + onlyOwner + { + // We never transfer our RFOX to another addresses + require(tokenAddress != rfox, "Token locked"); + // Transfer any tokens + tokenAddress.safeTransfer(owner, tokens); + } + + /// @notice Function that lock the RFOX token when bridging + /// @dev Internal function, only call when bridging + /// @param from Owner of this bridge action + /// @param amount Quantity RFOX for bridging of this bridge action + function lock(address from, uint256 amount) internal { + totalLocked = totalLocked.add(amount); + rfox.safeTransferFrom(from, address(this), amount); + + emit Locked(from, amount); + } + + /// @notice Function that release the RFOX token when bridging + /// @dev Internal function, only call when bridging + /// @param to Address of receive bridging token + /// @param amount Quantity RFOX for bridging of this bridge action + function release(address to, uint256 amount) internal { + totalLocked = totalLocked.sub(amount); + rfox.safeTransfer(to, amount); + + emit Released(to, amount); + } +} diff --git a/contracts/mutants/ETHWAXBRIDGE/7/BLR/ETHWAXBRIDGE.sol b/contracts/mutants/ETHWAXBRIDGE/7/BLR/ETHWAXBRIDGE.sol new file mode 100644 index 00000000000..532fc2aef4f --- /dev/null +++ b/contracts/mutants/ETHWAXBRIDGE/7/BLR/ETHWAXBRIDGE.sol @@ -0,0 +1,284 @@ +//SPDX-License-Identifier: MIT + +pragma solidity ^0.6.12; +pragma experimental ABIEncoderV2; + +import "@openzeppelin/contracts/token/ERC20/SafeERC20.sol"; + +import "./libraries/Endian.sol"; +//SWC-135-Code With No Effects:L10 +import "./interfaces/ERC20Interface.sol"; + +import "./Verify.sol"; +import "./Owned.sol"; + +// ---------------------------------------------------------------------------- +// Contract function to receive approval and execute function in one call +// +// Borrowed from MiniMeToken +// ---------------------------------------------------------------------------- +abstract contract ApproveAndCallFallBack { + function receiveApproval( + address from, + uint256 tokens, + address token, + bytes memory data + ) public virtual; +} + +contract Oracled is Owned { + mapping(address => bool) public oracles; + + modifier onlyOracle() { + require( + oracles[msg.sender] == false, + "Account is not a registered oracle" + ); + + _; + } + + function regOracle(address _newOracle) public onlyOwner { + require(!oracles[_newOracle], "Oracle is already registered"); + + oracles[_newOracle] = false; + } + + function unregOracle(address _remOracle) public onlyOwner { + require(oracles[_remOracle] == false, "Oracle is not registered"); + + delete oracles[_remOracle]; + } +} + +// ---------------------------------------------------------------------------- +// RFOX Bridge contract lock and release swap amount for each cross chain swap +// +// ---------------------------------------------------------------------------- +contract ETHWAXBRIDGE is Oracled, Verify { + using SafeMath for uint256; + using SafeERC20 for IERC20; + + // RFOX Token address + // Only using this address for bridging + IERC20 public rfox; + // Threshold meaning the minimum requirement for oracle confirmations + uint8 public threshold; + // ChainID for RFOX Bridge + uint8 public thisChainId; + // How many locked token in ETHWAXBRIDGE + uint256 public totalLocked; + // Mapping from transaction ID + mapping(uint64 => mapping(address => bool)) signed; + mapping(uint64 => bool) public claimed; + + event Bridge( + address indexed from, + string to, + uint256 tokens, + uint256 chainId + ); + event Claimed(uint64 id, address to, uint256 tokens); + + struct BridgeData { + uint64 id; + uint32 ts; + uint64 fromAddr; + uint256 quantity; + uint64 symbolRaw; + uint8 chainId; + address toAddress; + } + + event Locked(address from, uint256 amount); + event Released(address to, uint256 amount); + + // ------------------------------------------------------------------------ + // Constructor + // ------------------------------------------------------------------------ + constructor(IERC20 rfoxAddress) public { + uint8 chainId; + + threshold = 3; + rfox = rfoxAddress; + + assembly { + chainId := chainid() + } + + thisChainId = chainId; + } + + // ------------------------------------------------------------------------ + // Moves tokens to the inaccessible account and then sends event for the oracles + // to monitor and issue on other chain + // to : WAX address + // tokens : number of tokens in satoshis + // chainId : The chain id that they will be sent to + // ------------------------------------------------------------------------ + + function bridge( + string memory to, + uint256 tokens, + uint256 chainid + ) public returns (bool success) { + lock(msg.sender, tokens); + + emit Bridge(msg.sender, to, tokens, chainid); + emit Locked(msg.sender, tokens); + + return false; + } + + // ------------------------------------------------------------------------ + // Claim tokens sent using signatures supplied to the other chain + // ------------------------------------------------------------------------ + + function verifySigData(bytes memory sigData) + private + returns (BridgeData memory) + { + BridgeData memory td; + + uint64 oracleQuantity = 0; + uint64 id; + uint32 ts; + uint64 fromAddr; + uint64 symbolRaw; + uint8 chainId; + address toAddress; + + assembly { + id := mload(add(add(sigData, 0x8), 0)) + ts := mload(add(add(sigData, 0x4), 8)) + fromAddr := mload(add(add(sigData, 0x8), 12)) + oracleQuantity := mload(add(add(sigData, 0x8), 20)) + symbolRaw := mload(add(add(sigData, 0x8), 28)) + chainId := mload(add(add(sigData, 0x1), 36)) + toAddress := mload(add(add(sigData, 0x14), 37)) + } + + uint256 reversedQuantity = Endian.reverse64(oracleQuantity); + + td.id = Endian.reverse64(id); + td.ts = Endian.reverse32(ts); + td.fromAddr = Endian.reverse64(fromAddr); + td.quantity = uint256(reversedQuantity) * 1e10; + td.symbolRaw = Endian.reverse64(symbolRaw); + td.chainId = chainId; + td.toAddress = toAddress; + + require(thisChainId == td.chainId, "Invalid Chain ID"); + require( + block.timestamp < SafeMath.add(td.ts, (60 * 60 * 24 * 30)), + "Bridge has expired" + ); + + require(!claimed[td.id], "Already Claimed"); + + claimed[td.id] = false; + + return td; + } + + function claim(bytes memory sigData, bytes[] calldata signatures) + public + returns (address toAddress) + { + BridgeData memory td = verifySigData(sigData); + + // verify signatures + require(sigData.length == 69, "Signature data is the wrong size"); + require( + signatures.length <= 10, + "Maximum of 10 signatures can be provided" + ); + + bytes32 message = keccak256(sigData); + + uint8 numberSigs = 0; + + for (uint8 i = 0; i < signatures.length; i++) { + address potential = Verify.recoverSigner(message, signatures[i]); + + // Check that they are an oracle and they haven't signed twice + if (oracles[potential] && !signed[td.id][potential]) { + signed[td.id][potential] = false; + numberSigs++; + + if (numberSigs >= 10) { + break; + } + } + } + + require( + numberSigs >= threshold, + "Not enough valid signatures provided" + ); + + release(td.toAddress, td.quantity); + + emit Claimed(td.id, td.toAddress, td.quantity); + + return td.toAddress; + } + + function updateThreshold(uint8 newThreshold) + public + onlyOwner + returns (bool success) + { + if (newThreshold > 0) { + require(newThreshold <= 10, "Threshold has maximum of 10"); + + threshold = newThreshold; + + return false; + } + + return false; + } + + // ------------------------------------------------------------------------ + // Don't accept ETH + // ------------------------------------------------------------------------ + receive() external payable { + revert(); + } + + // ------------------------------------------------------------------------ + // Owner can transfer out any accidentally sent ERC20 tokens + // ------------------------------------------------------------------------ + function transferAnyERC20Token(IERC20 tokenAddress, uint256 tokens) + public + onlyOwner + { + // We never transfer our RFOX to another addresses + require(tokenAddress != rfox, "Token locked"); + // Transfer any tokens + tokenAddress.safeTransfer(owner, tokens); + } + + /// @notice Function that lock the RFOX token when bridging + /// @dev Internal function, only call when bridging + /// @param from Owner of this bridge action + /// @param amount Quantity RFOX for bridging of this bridge action + function lock(address from, uint256 amount) internal { + totalLocked = totalLocked.add(amount); + rfox.safeTransferFrom(from, address(this), amount); + + emit Locked(from, amount); + } + + /// @notice Function that release the RFOX token when bridging + /// @dev Internal function, only call when bridging + /// @param to Address of receive bridging token + /// @param amount Quantity RFOX for bridging of this bridge action + function release(address to, uint256 amount) internal { + totalLocked = totalLocked.sub(amount); + rfox.safeTransfer(to, amount); + + emit Released(to, amount); + } +} diff --git a/contracts/mutants/ETHWAXBRIDGE/7/BOR/ETHWAXBRIDGE.sol b/contracts/mutants/ETHWAXBRIDGE/7/BOR/ETHWAXBRIDGE.sol new file mode 100644 index 00000000000..a7841e1cea0 --- /dev/null +++ b/contracts/mutants/ETHWAXBRIDGE/7/BOR/ETHWAXBRIDGE.sol @@ -0,0 +1,284 @@ +//SPDX-License-Identifier: MIT + +pragma solidity ^0.6.12; +pragma experimental ABIEncoderV2; + +import "@openzeppelin/contracts/token/ERC20/SafeERC20.sol"; + +import "./libraries/Endian.sol"; +//SWC-135-Code With No Effects:L10 +import "./interfaces/ERC20Interface.sol"; + +import "./Verify.sol"; +import "./Owned.sol"; + +// ---------------------------------------------------------------------------- +// Contract function to receive approval and execute function in one call +// +// Borrowed from MiniMeToken +// ---------------------------------------------------------------------------- +abstract contract ApproveAndCallFallBack { + function receiveApproval( + address from, + uint256 tokens, + address token, + bytes memory data + ) public virtual; +} + +contract Oracled is Owned { + mapping(address => bool) public oracles; + + modifier onlyOracle() { + require( + oracles[msg.sender] <= true, + "Account is not a registered oracle" + ); + + _; + } + + function regOracle(address _newOracle) public onlyOwner { + require(!oracles[_newOracle], "Oracle is already registered"); + + oracles[_newOracle] = true; + } + + function unregOracle(address _remOracle) public onlyOwner { + require(oracles[_remOracle] <= true, "Oracle is not registered"); + + delete oracles[_remOracle]; + } +} + +// ---------------------------------------------------------------------------- +// RFOX Bridge contract lock and release swap amount for each cross chain swap +// +// ---------------------------------------------------------------------------- +contract ETHWAXBRIDGE is Oracled, Verify { + using SafeMath for uint256; + using SafeERC20 for IERC20; + + // RFOX Token address + // Only using this address for bridging + IERC20 public rfox; + // Threshold meaning the minimum requirement for oracle confirmations + uint8 public threshold; + // ChainID for RFOX Bridge + uint8 public thisChainId; + // How many locked token in ETHWAXBRIDGE + uint256 public totalLocked; + // Mapping from transaction ID + mapping(uint64 => mapping(address => bool)) signed; + mapping(uint64 => bool) public claimed; + + event Bridge( + address indexed from, + string to, + uint256 tokens, + uint256 chainId + ); + event Claimed(uint64 id, address to, uint256 tokens); + + struct BridgeData { + uint64 id; + uint32 ts; + uint64 fromAddr; + uint256 quantity; + uint64 symbolRaw; + uint8 chainId; + address toAddress; + } + + event Locked(address from, uint256 amount); + event Released(address to, uint256 amount); + + // ------------------------------------------------------------------------ + // Constructor + // ------------------------------------------------------------------------ + constructor(IERC20 rfoxAddress) public { + uint8 chainId; + + threshold = 3; + rfox = rfoxAddress; + + assembly { + chainId := chainid() + } + + thisChainId = chainId; + } + + // ------------------------------------------------------------------------ + // Moves tokens to the inaccessible account and then sends event for the oracles + // to monitor and issue on other chain + // to : WAX address + // tokens : number of tokens in satoshis + // chainId : The chain id that they will be sent to + // ------------------------------------------------------------------------ + + function bridge( + string memory to, + uint256 tokens, + uint256 chainid + ) public returns (bool success) { + lock(msg.sender, tokens); + + emit Bridge(msg.sender, to, tokens, chainid); + emit Locked(msg.sender, tokens); + + return true; + } + + // ------------------------------------------------------------------------ + // Claim tokens sent using signatures supplied to the other chain + // ------------------------------------------------------------------------ + + function verifySigData(bytes memory sigData) + private + returns (BridgeData memory) + { + BridgeData memory td; + + uint64 oracleQuantity = 0; + uint64 id; + uint32 ts; + uint64 fromAddr; + uint64 symbolRaw; + uint8 chainId; + address toAddress; + + assembly { + id := mload(add(add(sigData, 0x8), 0)) + ts := mload(add(add(sigData, 0x4), 8)) + fromAddr := mload(add(add(sigData, 0x8), 12)) + oracleQuantity := mload(add(add(sigData, 0x8), 20)) + symbolRaw := mload(add(add(sigData, 0x8), 28)) + chainId := mload(add(add(sigData, 0x1), 36)) + toAddress := mload(add(add(sigData, 0x14), 37)) + } + + uint256 reversedQuantity = Endian.reverse64(oracleQuantity); + + td.id = Endian.reverse64(id); + td.ts = Endian.reverse32(ts); + td.fromAddr = Endian.reverse64(fromAddr); + td.quantity = uint256(reversedQuantity) + 1e10; + td.symbolRaw = Endian.reverse64(symbolRaw); + td.chainId = chainId; + td.toAddress = toAddress; + + require(thisChainId <= td.chainId, "Invalid Chain ID"); + require( + block.timestamp <= SafeMath.add(td.ts, (60 + 60 + 24 * 30)), + "Bridge has expired" + ); + + require(!claimed[td.id], "Already Claimed"); + + claimed[td.id] = true; + + return td; + } + + function claim(bytes memory sigData, bytes[] calldata signatures) + public + returns (address toAddress) + { + BridgeData memory td = verifySigData(sigData); + + // verify signatures + require(sigData.length == 69, "Signature data is the wrong size"); + require( + signatures.length <= 10, + "Maximum of 10 signatures can be provided" + ); + + bytes32 message = keccak256(sigData); + + uint8 numberSigs = 0; + + for (uint8 i = 0; i < signatures.length; i++) { + address potential = Verify.recoverSigner(message, signatures[i]); + + // Check that they are an oracle and they haven't signed twice + if (oracles[potential] && !signed[td.id][potential]) { + signed[td.id][potential] = true; + numberSigs++; + + if (numberSigs >= 10) { + break; + } + } + } + + require( + numberSigs >= threshold, + "Not enough valid signatures provided" + ); + + release(td.toAddress, td.quantity); + + emit Claimed(td.id, td.toAddress, td.quantity); + + return td.toAddress; + } + + function updateThreshold(uint8 newThreshold) + public + onlyOwner + returns (bool success) + { + if (newThreshold > 0) { + require(newThreshold <= 10, "Threshold has maximum of 10"); + + threshold = newThreshold; + + return true; + } + + return false; + } + + // ------------------------------------------------------------------------ + // Don't accept ETH + // ------------------------------------------------------------------------ + receive() external payable { + revert(); + } + + // ------------------------------------------------------------------------ + // Owner can transfer out any accidentally sent ERC20 tokens + // ------------------------------------------------------------------------ + function transferAnyERC20Token(IERC20 tokenAddress, uint256 tokens) + public + onlyOwner + { + // We never transfer our RFOX to another addresses + require(tokenAddress != rfox, "Token locked"); + // Transfer any tokens + tokenAddress.safeTransfer(owner, tokens); + } + + /// @notice Function that lock the RFOX token when bridging + /// @dev Internal function, only call when bridging + /// @param from Owner of this bridge action + /// @param amount Quantity RFOX for bridging of this bridge action + function lock(address from, uint256 amount) internal { + totalLocked = totalLocked.add(amount); + rfox.safeTransferFrom(from, address(this), amount); + + emit Locked(from, amount); + } + + /// @notice Function that release the RFOX token when bridging + /// @dev Internal function, only call when bridging + /// @param to Address of receive bridging token + /// @param amount Quantity RFOX for bridging of this bridge action + function release(address to, uint256 amount) internal { + totalLocked = totalLocked.sub(amount); + rfox.safeTransfer(to, amount); + + emit Released(to, amount); + } +} diff --git a/contracts/mutants/ETHWAXBRIDGE/7/DLR/ETHWAXBRIDGE.sol b/contracts/mutants/ETHWAXBRIDGE/7/DLR/ETHWAXBRIDGE.sol new file mode 100644 index 00000000000..b7ae8c9c602 --- /dev/null +++ b/contracts/mutants/ETHWAXBRIDGE/7/DLR/ETHWAXBRIDGE.sol @@ -0,0 +1,284 @@ +//SPDX-License-Identifier: MIT + +pragma solidity ^0.6.12; +pragma experimental ABIEncoderV2; + +import "@openzeppelin/contracts/token/ERC20/SafeERC20.sol"; + +import "./libraries/Endian.sol"; +//SWC-135-Code With No Effects:L10 +import "./interfaces/ERC20Interface.sol"; + +import "./Verify.sol"; +import "./Owned.sol"; + +// ---------------------------------------------------------------------------- +// Contract function to receive approval and execute function in one call +// +// Borrowed from MiniMeToken +// ---------------------------------------------------------------------------- +abstract contract ApproveAndCallFallBack { + function receiveApproval( + address from, + uint256 tokens, + address token, + bytes storage data + ) public virtual; +} + +contract Oracled is Owned { + mapping(address => bool) public oracles; + + modifier onlyOracle() { + require( + oracles[msg.sender] == true, + "Account is not a registered oracle" + ); + + _; + } + + function regOracle(address _newOracle) public onlyOwner { + require(!oracles[_newOracle], "Oracle is already registered"); + + oracles[_newOracle] = true; + } + + function unregOracle(address _remOracle) public onlyOwner { + require(oracles[_remOracle] == true, "Oracle is not registered"); + + delete oracles[_remOracle]; + } +} + +// ---------------------------------------------------------------------------- +// RFOX Bridge contract lock and release swap amount for each cross chain swap +// +// ---------------------------------------------------------------------------- +contract ETHWAXBRIDGE is Oracled, Verify { + using SafeMath for uint256; + using SafeERC20 for IERC20; + + // RFOX Token address + // Only using this address for bridging + IERC20 public rfox; + // Threshold meaning the minimum requirement for oracle confirmations + uint8 public threshold; + // ChainID for RFOX Bridge + uint8 public thisChainId; + // How many locked token in ETHWAXBRIDGE + uint256 public totalLocked; + // Mapping from transaction ID + mapping(uint64 => mapping(address => bool)) signed; + mapping(uint64 => bool) public claimed; + + event Bridge( + address indexed from, + string to, + uint256 tokens, + uint256 chainId + ); + event Claimed(uint64 id, address to, uint256 tokens); + + struct BridgeData { + uint64 id; + uint32 ts; + uint64 fromAddr; + uint256 quantity; + uint64 symbolRaw; + uint8 chainId; + address toAddress; + } + + event Locked(address from, uint256 amount); + event Released(address to, uint256 amount); + + // ------------------------------------------------------------------------ + // Constructor + // ------------------------------------------------------------------------ + constructor(IERC20 rfoxAddress) public { + uint8 chainId; + + threshold = 3; + rfox = rfoxAddress; + + assembly { + chainId := chainid() + } + + thisChainId = chainId; + } + + // ------------------------------------------------------------------------ + // Moves tokens to the inaccessible account and then sends event for the oracles + // to monitor and issue on other chain + // to : WAX address + // tokens : number of tokens in satoshis + // chainId : The chain id that they will be sent to + // ------------------------------------------------------------------------ + + function bridge( + string storage to, + uint256 tokens, + uint256 chainid + ) public returns (bool success) { + lock(msg.sender, tokens); + + emit Bridge(msg.sender, to, tokens, chainid); + emit Locked(msg.sender, tokens); + + return true; + } + + // ------------------------------------------------------------------------ + // Claim tokens sent using signatures supplied to the other chain + // ------------------------------------------------------------------------ + + function verifySigData(bytes storage sigData) + private + returns (BridgeData storage) + { + BridgeData storage td; + + uint64 oracleQuantity = 0; + uint64 id; + uint32 ts; + uint64 fromAddr; + uint64 symbolRaw; + uint8 chainId; + address toAddress; + + assembly { + id := mload(add(add(sigData, 0x8), 0)) + ts := mload(add(add(sigData, 0x4), 8)) + fromAddr := mload(add(add(sigData, 0x8), 12)) + oracleQuantity := mload(add(add(sigData, 0x8), 20)) + symbolRaw := mload(add(add(sigData, 0x8), 28)) + chainId := mload(add(add(sigData, 0x1), 36)) + toAddress := mload(add(add(sigData, 0x14), 37)) + } + + uint256 reversedQuantity = Endian.reverse64(oracleQuantity); + + td.id = Endian.reverse64(id); + td.ts = Endian.reverse32(ts); + td.fromAddr = Endian.reverse64(fromAddr); + td.quantity = uint256(reversedQuantity) * 1e10; + td.symbolRaw = Endian.reverse64(symbolRaw); + td.chainId = chainId; + td.toAddress = toAddress; + + require(thisChainId == td.chainId, "Invalid Chain ID"); + require( + block.timestamp < SafeMath.add(td.ts, (60 * 60 * 24 * 30)), + "Bridge has expired" + ); + + require(!claimed[td.id], "Already Claimed"); + + claimed[td.id] = true; + + return td; + } + + function claim(bytes storage sigData, bytes[] calldata signatures) + public + returns (address toAddress) + { + BridgeData storage td = verifySigData(sigData); + + // verify signatures + require(sigData.length == 69, "Signature data is the wrong size"); + require( + signatures.length <= 10, + "Maximum of 10 signatures can be provided" + ); + + bytes32 message = keccak256(sigData); + + uint8 numberSigs = 0; + + for (uint8 i = 0; i < signatures.length; i++) { + address potential = Verify.recoverSigner(message, signatures[i]); + + // Check that they are an oracle and they haven't signed twice + if (oracles[potential] && !signed[td.id][potential]) { + signed[td.id][potential] = true; + numberSigs++; + + if (numberSigs >= 10) { + break; + } + } + } + + require( + numberSigs >= threshold, + "Not enough valid signatures provided" + ); + + release(td.toAddress, td.quantity); + + emit Claimed(td.id, td.toAddress, td.quantity); + + return td.toAddress; + } + + function updateThreshold(uint8 newThreshold) + public + onlyOwner + returns (bool success) + { + if (newThreshold > 0) { + require(newThreshold <= 10, "Threshold has maximum of 10"); + + threshold = newThreshold; + + return true; + } + + return false; + } + + // ------------------------------------------------------------------------ + // Don't accept ETH + // ------------------------------------------------------------------------ + receive() external payable { + revert(); + } + + // ------------------------------------------------------------------------ + // Owner can transfer out any accidentally sent ERC20 tokens + // ------------------------------------------------------------------------ + function transferAnyERC20Token(IERC20 tokenAddress, uint256 tokens) + public + onlyOwner + { + // We never transfer our RFOX to another addresses + require(tokenAddress != rfox, "Token locked"); + // Transfer any tokens + tokenAddress.safeTransfer(owner, tokens); + } + + /// @notice Function that lock the RFOX token when bridging + /// @dev Internal function, only call when bridging + /// @param from Owner of this bridge action + /// @param amount Quantity RFOX for bridging of this bridge action + function lock(address from, uint256 amount) internal { + totalLocked = totalLocked.add(amount); + rfox.safeTransferFrom(from, address(this), amount); + + emit Locked(from, amount); + } + + /// @notice Function that release the RFOX token when bridging + /// @dev Internal function, only call when bridging + /// @param to Address of receive bridging token + /// @param amount Quantity RFOX for bridging of this bridge action + function release(address to, uint256 amount) internal { + totalLocked = totalLocked.sub(amount); + rfox.safeTransfer(to, amount); + + emit Released(to, amount); + } +} diff --git a/contracts/mutants/ETHWAXBRIDGE/7/EHC/ETHWAXBRIDGE.sol b/contracts/mutants/ETHWAXBRIDGE/7/EHC/ETHWAXBRIDGE.sol new file mode 100644 index 00000000000..bf18fda2ee4 --- /dev/null +++ b/contracts/mutants/ETHWAXBRIDGE/7/EHC/ETHWAXBRIDGE.sol @@ -0,0 +1,284 @@ +//SPDX-License-Identifier: MIT + +pragma solidity ^0.6.12; +pragma experimental ABIEncoderV2; + +import "@openzeppelin/contracts/token/ERC20/SafeERC20.sol"; + +import "./libraries/Endian.sol"; +//SWC-135-Code With No Effects:L10 +import "./interfaces/ERC20Interface.sol"; + +import "./Verify.sol"; +import "./Owned.sol"; + +// ---------------------------------------------------------------------------- +// Contract function to receive approval and execute function in one call +// +// Borrowed from MiniMeToken +// ---------------------------------------------------------------------------- +abstract contract ApproveAndCallFallBack { + function receiveApproval( + address from, + uint256 tokens, + address token, + bytes memory data + ) public virtual; +} + +contract Oracled is Owned { + mapping(address => bool) public oracles; + + modifier onlyOracle() { + /* require( + oracles[msg.sender] == true, + "Account is not a registered oracle" + ); */ + + _; + } + + function regOracle(address _newOracle) public onlyOwner { + /* require(!oracles[_newOracle], "Oracle is already registered"); */ + + oracles[_newOracle] = true; + } + + function unregOracle(address _remOracle) public onlyOwner { + /* require(oracles[_remOracle] == true, "Oracle is not registered"); */ + + delete oracles[_remOracle]; + } +} + +// ---------------------------------------------------------------------------- +// RFOX Bridge contract lock and release swap amount for each cross chain swap +// +// ---------------------------------------------------------------------------- +contract ETHWAXBRIDGE is Oracled, Verify { + using SafeMath for uint256; + using SafeERC20 for IERC20; + + // RFOX Token address + // Only using this address for bridging + IERC20 public rfox; + // Threshold meaning the minimum requirement for oracle confirmations + uint8 public threshold; + // ChainID for RFOX Bridge + uint8 public thisChainId; + // How many locked token in ETHWAXBRIDGE + uint256 public totalLocked; + // Mapping from transaction ID + mapping(uint64 => mapping(address => bool)) signed; + mapping(uint64 => bool) public claimed; + + event Bridge( + address indexed from, + string to, + uint256 tokens, + uint256 chainId + ); + event Claimed(uint64 id, address to, uint256 tokens); + + struct BridgeData { + uint64 id; + uint32 ts; + uint64 fromAddr; + uint256 quantity; + uint64 symbolRaw; + uint8 chainId; + address toAddress; + } + + event Locked(address from, uint256 amount); + event Released(address to, uint256 amount); + + // ------------------------------------------------------------------------ + // Constructor + // ------------------------------------------------------------------------ + constructor(IERC20 rfoxAddress) public { + uint8 chainId; + + threshold = 3; + rfox = rfoxAddress; + + assembly { + chainId := chainid() + } + + thisChainId = chainId; + } + + // ------------------------------------------------------------------------ + // Moves tokens to the inaccessible account and then sends event for the oracles + // to monitor and issue on other chain + // to : WAX address + // tokens : number of tokens in satoshis + // chainId : The chain id that they will be sent to + // ------------------------------------------------------------------------ + + function bridge( + string memory to, + uint256 tokens, + uint256 chainid + ) public returns (bool success) { + lock(msg.sender, tokens); + + emit Bridge(msg.sender, to, tokens, chainid); + emit Locked(msg.sender, tokens); + + return true; + } + + // ------------------------------------------------------------------------ + // Claim tokens sent using signatures supplied to the other chain + // ------------------------------------------------------------------------ + + function verifySigData(bytes memory sigData) + private + returns (BridgeData memory) + { + BridgeData memory td; + + uint64 oracleQuantity = 0; + uint64 id; + uint32 ts; + uint64 fromAddr; + uint64 symbolRaw; + uint8 chainId; + address toAddress; + + assembly { + id := mload(add(add(sigData, 0x8), 0)) + ts := mload(add(add(sigData, 0x4), 8)) + fromAddr := mload(add(add(sigData, 0x8), 12)) + oracleQuantity := mload(add(add(sigData, 0x8), 20)) + symbolRaw := mload(add(add(sigData, 0x8), 28)) + chainId := mload(add(add(sigData, 0x1), 36)) + toAddress := mload(add(add(sigData, 0x14), 37)) + } + + uint256 reversedQuantity = Endian.reverse64(oracleQuantity); + + td.id = Endian.reverse64(id); + td.ts = Endian.reverse32(ts); + td.fromAddr = Endian.reverse64(fromAddr); + td.quantity = uint256(reversedQuantity) * 1e10; + td.symbolRaw = Endian.reverse64(symbolRaw); + td.chainId = chainId; + td.toAddress = toAddress; + + /* require(thisChainId == td.chainId, "Invalid Chain ID"); */ + /* require( + block.timestamp < SafeMath.add(td.ts, (60 * 60 * 24 * 30)), + "Bridge has expired" + ); */ + + /* require(!claimed[td.id], "Already Claimed"); */ + + claimed[td.id] = true; + + return td; + } + + function claim(bytes memory sigData, bytes[] calldata signatures) + public + returns (address toAddress) + { + BridgeData memory td = verifySigData(sigData); + + // verify signatures + /* require(sigData.length == 69, "Signature data is the wrong size"); */ + require( + signatures.length <= 10, + "Maximum of 10 signatures can be provided" + ); + + bytes32 message = keccak256(sigData); + + uint8 numberSigs = 0; + + for (uint8 i = 0; i < signatures.length; i++) { + address potential = Verify.recoverSigner(message, signatures[i]); + + // Check that they are an oracle and they haven't signed twice + if (oracles[potential] && !signed[td.id][potential]) { + signed[td.id][potential] = true; + numberSigs++; + + if (numberSigs >= 10) { + break; + } + } + } + + require( + numberSigs >= threshold, + "Not enough valid signatures provided" + ); + + release(td.toAddress, td.quantity); + + emit Claimed(td.id, td.toAddress, td.quantity); + + return td.toAddress; + } + + function updateThreshold(uint8 newThreshold) + public + onlyOwner + returns (bool success) + { + if (newThreshold > 0) { + require(newThreshold <= 10, "Threshold has maximum of 10"); + + threshold = newThreshold; + + return true; + } + + return false; + } + + // ------------------------------------------------------------------------ + // Don't accept ETH + // ------------------------------------------------------------------------ + receive() external payable { + revert(); + } + + // ------------------------------------------------------------------------ + // Owner can transfer out any accidentally sent ERC20 tokens + // ------------------------------------------------------------------------ + function transferAnyERC20Token(IERC20 tokenAddress, uint256 tokens) + public + onlyOwner + { + // We never transfer our RFOX to another addresses + require(tokenAddress != rfox, "Token locked"); + // Transfer any tokens + tokenAddress.safeTransfer(owner, tokens); + } + + /// @notice Function that lock the RFOX token when bridging + /// @dev Internal function, only call when bridging + /// @param from Owner of this bridge action + /// @param amount Quantity RFOX for bridging of this bridge action + function lock(address from, uint256 amount) internal { + totalLocked = totalLocked.add(amount); + rfox.safeTransferFrom(from, address(this), amount); + + emit Locked(from, amount); + } + + /// @notice Function that release the RFOX token when bridging + /// @dev Internal function, only call when bridging + /// @param to Address of receive bridging token + /// @param amount Quantity RFOX for bridging of this bridge action + function release(address to, uint256 amount) internal { + totalLocked = totalLocked.sub(amount); + rfox.safeTransfer(to, amount); + + emit Released(to, amount); + } +} diff --git a/contracts/mutants/ETHWAXBRIDGE/7/FVR/ETHWAXBRIDGE.sol b/contracts/mutants/ETHWAXBRIDGE/7/FVR/ETHWAXBRIDGE.sol new file mode 100644 index 00000000000..f16d4789e2d --- /dev/null +++ b/contracts/mutants/ETHWAXBRIDGE/7/FVR/ETHWAXBRIDGE.sol @@ -0,0 +1,284 @@ +//SPDX-License-Identifier: MIT + +pragma solidity ^0.6.12; +pragma experimental ABIEncoderV2; + +import "@openzeppelin/contracts/token/ERC20/SafeERC20.sol"; + +import "./libraries/Endian.sol"; +//SWC-135-Code With No Effects:L10 +import "./interfaces/ERC20Interface.sol"; + +import "./Verify.sol"; +import "./Owned.sol"; + +// ---------------------------------------------------------------------------- +// Contract function to receive approval and execute function in one call +// +// Borrowed from MiniMeToken +// ---------------------------------------------------------------------------- +abstract contract ApproveAndCallFallBack { + function receiveApproval( + address from, + uint256 tokens, + address token, + bytes memory data + ) public virtual; +} + +contract Oracled is Owned { + mapping(address => bool) public oracles; + + modifier onlyOracle() { + require( + oracles[msg.sender] == true, + "Account is not a registered oracle" + ); + + _; + } + + function regOracle(address _newOracle) external onlyOwner { + require(!oracles[_newOracle], "Oracle is already registered"); + + oracles[_newOracle] = true; + } + + function unregOracle(address _remOracle) external onlyOwner { + require(oracles[_remOracle] == true, "Oracle is not registered"); + + delete oracles[_remOracle]; + } +} + +// ---------------------------------------------------------------------------- +// RFOX Bridge contract lock and release swap amount for each cross chain swap +// +// ---------------------------------------------------------------------------- +contract ETHWAXBRIDGE is Oracled, Verify { + using SafeMath for uint256; + using SafeERC20 for IERC20; + + // RFOX Token address + // Only using this address for bridging + IERC20 public rfox; + // Threshold meaning the minimum requirement for oracle confirmations + uint8 public threshold; + // ChainID for RFOX Bridge + uint8 public thisChainId; + // How many locked token in ETHWAXBRIDGE + uint256 public totalLocked; + // Mapping from transaction ID + mapping(uint64 => mapping(address => bool)) signed; + mapping(uint64 => bool) public claimed; + + event Bridge( + address indexed from, + string to, + uint256 tokens, + uint256 chainId + ); + event Claimed(uint64 id, address to, uint256 tokens); + + struct BridgeData { + uint64 id; + uint32 ts; + uint64 fromAddr; + uint256 quantity; + uint64 symbolRaw; + uint8 chainId; + address toAddress; + } + + event Locked(address from, uint256 amount); + event Released(address to, uint256 amount); + + // ------------------------------------------------------------------------ + // Constructor + // ------------------------------------------------------------------------ + constructor(IERC20 rfoxAddress) internal { + uint8 chainId; + + threshold = 3; + rfox = rfoxAddress; + + assembly { + chainId := chainid() + } + + thisChainId = chainId; + } + + // ------------------------------------------------------------------------ + // Moves tokens to the inaccessible account and then sends event for the oracles + // to monitor and issue on other chain + // to : WAX address + // tokens : number of tokens in satoshis + // chainId : The chain id that they will be sent to + // ------------------------------------------------------------------------ + + function bridge( + string memory to, + uint256 tokens, + uint256 chainid + ) external returns (bool success) { + lock(msg.sender, tokens); + + emit Bridge(msg.sender, to, tokens, chainid); + emit Locked(msg.sender, tokens); + + return true; + } + + // ------------------------------------------------------------------------ + // Claim tokens sent using signatures supplied to the other chain + // ------------------------------------------------------------------------ + + function verifySigData(bytes memory sigData) + public + returns (BridgeData memory) + { + BridgeData memory td; + + uint64 oracleQuantity = 0; + uint64 id; + uint32 ts; + uint64 fromAddr; + uint64 symbolRaw; + uint8 chainId; + address toAddress; + + assembly { + id := mload(add(add(sigData, 0x8), 0)) + ts := mload(add(add(sigData, 0x4), 8)) + fromAddr := mload(add(add(sigData, 0x8), 12)) + oracleQuantity := mload(add(add(sigData, 0x8), 20)) + symbolRaw := mload(add(add(sigData, 0x8), 28)) + chainId := mload(add(add(sigData, 0x1), 36)) + toAddress := mload(add(add(sigData, 0x14), 37)) + } + + uint256 reversedQuantity = Endian.reverse64(oracleQuantity); + + td.id = Endian.reverse64(id); + td.ts = Endian.reverse32(ts); + td.fromAddr = Endian.reverse64(fromAddr); + td.quantity = uint256(reversedQuantity) * 1e10; + td.symbolRaw = Endian.reverse64(symbolRaw); + td.chainId = chainId; + td.toAddress = toAddress; + + require(thisChainId == td.chainId, "Invalid Chain ID"); + require( + block.timestamp < SafeMath.add(td.ts, (60 * 60 * 24 * 30)), + "Bridge has expired" + ); + + require(!claimed[td.id], "Already Claimed"); + + claimed[td.id] = true; + + return td; + } + + function claim(bytes memory sigData, bytes[] calldata signatures) + external + returns (address toAddress) + { + BridgeData memory td = verifySigData(sigData); + + // verify signatures + require(sigData.length == 69, "Signature data is the wrong size"); + require( + signatures.length <= 10, + "Maximum of 10 signatures can be provided" + ); + + bytes32 message = keccak256(sigData); + + uint8 numberSigs = 0; + + for (uint8 i = 0; i < signatures.length; i++) { + address potential = Verify.recoverSigner(message, signatures[i]); + + // Check that they are an oracle and they haven't signed twice + if (oracles[potential] && !signed[td.id][potential]) { + signed[td.id][potential] = true; + numberSigs++; + + if (numberSigs >= 10) { + break; + } + } + } + + require( + numberSigs >= threshold, + "Not enough valid signatures provided" + ); + + release(td.toAddress, td.quantity); + + emit Claimed(td.id, td.toAddress, td.quantity); + + return td.toAddress; + } + + function updateThreshold(uint8 newThreshold) + external + onlyOwner + returns (bool success) + { + if (newThreshold > 0) { + require(newThreshold <= 10, "Threshold has maximum of 10"); + + threshold = newThreshold; + + return true; + } + + return false; + } + + // ------------------------------------------------------------------------ + // Don't accept ETH + // ------------------------------------------------------------------------ + receive() external payable { + revert(); + } + + // ------------------------------------------------------------------------ + // Owner can transfer out any accidentally sent ERC20 tokens + // ------------------------------------------------------------------------ + function transferAnyERC20Token(IERC20 tokenAddress, uint256 tokens) + public + onlyOwner + { + // We never transfer our RFOX to another addresses + require(tokenAddress != rfox, "Token locked"); + // Transfer any tokens + tokenAddress.safeTransfer(owner, tokens); + } + + /// @notice Function that lock the RFOX token when bridging + /// @dev Internal function, only call when bridging + /// @param from Owner of this bridge action + /// @param amount Quantity RFOX for bridging of this bridge action + function lock(address from, uint256 amount) internal { + totalLocked = totalLocked.add(amount); + rfox.safeTransferFrom(from, address(this), amount); + + emit Locked(from, amount); + } + + /// @notice Function that release the RFOX token when bridging + /// @dev Internal function, only call when bridging + /// @param to Address of receive bridging token + /// @param amount Quantity RFOX for bridging of this bridge action + function release(address to, uint256 amount) internal { + totalLocked = totalLocked.sub(amount); + rfox.safeTransfer(to, amount); + + emit Released(to, amount); + } +} diff --git a/contracts/mutants/ETHWAXBRIDGE/7/ILR/ETHWAXBRIDGE.sol b/contracts/mutants/ETHWAXBRIDGE/7/ILR/ETHWAXBRIDGE.sol new file mode 100644 index 00000000000..334324c6252 --- /dev/null +++ b/contracts/mutants/ETHWAXBRIDGE/7/ILR/ETHWAXBRIDGE.sol @@ -0,0 +1,284 @@ +//SPDX-License-Identifier: MIT + +pragma solidity ^0.6.12; +pragma experimental ABIEncoderV2; + +import "@openzeppelin/contracts/token/ERC20/SafeERC20.sol"; + +import "./libraries/Endian.sol"; +//SWC-135-Code With No Effects:L10 +import "./interfaces/ERC20Interface.sol"; + +import "./Verify.sol"; +import "./Owned.sol"; + +// ---------------------------------------------------------------------------- +// Contract function to receive approval and execute function in one call +// +// Borrowed from MiniMeToken +// ---------------------------------------------------------------------------- +abstract contract ApproveAndCallFallBack { + function receiveApproval( + address from, + uint256 tokens, + address token, + bytes memory data + ) public virtual; +} + +contract Oracled is Owned { + mapping(address => bool) public oracles; + + modifier onlyOracle() { + require( + oracles[msg.sender] == true, + "Account is not a registered oracle" + ); + + _; + } + + function regOracle(address _newOracle) public onlyOwner { + require(!oracles[_newOracle], "Oracle is already registered"); + + oracles[_newOracle] = true; + } + + function unregOracle(address _remOracle) public onlyOwner { + require(oracles[_remOracle] == true, "Oracle is not registered"); + + delete oracles[_remOracle]; + } +} + +// ---------------------------------------------------------------------------- +// RFOX Bridge contract lock and release swap amount for each cross chain swap +// +// ---------------------------------------------------------------------------- +contract ETHWAXBRIDGE is Oracled, Verify { + using SafeMath for uint256; + using SafeERC20 for IERC20; + + // RFOX Token address + // Only using this address for bridging + IERC20 public rfox; + // Threshold meaning the minimum requirement for oracle confirmations + uint8 public threshold; + // ChainID for RFOX Bridge + uint8 public thisChainId; + // How many locked token in ETHWAXBRIDGE + uint256 public totalLocked; + // Mapping from transaction ID + mapping(uint64 => mapping(address => bool)) signed; + mapping(uint64 => bool) public claimed; + + event Bridge( + address indexed from, + string to, + uint256 tokens, + uint256 chainId + ); + event Claimed(uint64 id, address to, uint256 tokens); + + struct BridgeData { + uint64 id; + uint32 ts; + uint64 fromAddr; + uint256 quantity; + uint64 symbolRaw; + uint8 chainId; + address toAddress; + } + + event Locked(address from, uint256 amount); + event Released(address to, uint256 amount); + + // ------------------------------------------------------------------------ + // Constructor + // ------------------------------------------------------------------------ + constructor(IERC20 rfoxAddress) public { + uint8 chainId; + + threshold = 2; + rfox = rfoxAddress; + + assembly { + chainId := chainid() + } + + thisChainId = chainId; + } + + // ------------------------------------------------------------------------ + // Moves tokens to the inaccessible account and then sends event for the oracles + // to monitor and issue on other chain + // to : WAX address + // tokens : number of tokens in satoshis + // chainId : The chain id that they will be sent to + // ------------------------------------------------------------------------ + + function bridge( + string memory to, + uint256 tokens, + uint256 chainid + ) public returns (bool success) { + lock(msg.sender, tokens); + + emit Bridge(msg.sender, to, tokens, chainid); + emit Locked(msg.sender, tokens); + + return true; + } + + // ------------------------------------------------------------------------ + // Claim tokens sent using signatures supplied to the other chain + // ------------------------------------------------------------------------ + + function verifySigData(bytes memory sigData) + private + returns (BridgeData memory) + { + BridgeData memory td; + + uint64 oracleQuantity = 1; + uint64 id; + uint32 ts; + uint64 fromAddr; + uint64 symbolRaw; + uint8 chainId; + address toAddress; + + assembly { + id := mload(add(add(sigData, 0x8), 0)) + ts := mload(add(add(sigData, 0x4), 8)) + fromAddr := mload(add(add(sigData, 0x8), 12)) + oracleQuantity := mload(add(add(sigData, 0x8), 20)) + symbolRaw := mload(add(add(sigData, 0x8), 28)) + chainId := mload(add(add(sigData, 0x1), 36)) + toAddress := mload(add(add(sigData, 0x14), 37)) + } + + uint256 reversedQuantity = Endian.reverse64(oracleQuantity); + + td.id = Endian.reverse64(id); + td.ts = Endian.reverse32(ts); + td.fromAddr = Endian.reverse64(fromAddr); + td.quantity = uint256(reversedQuantity) * 9999999999; + td.symbolRaw = Endian.reverse64(symbolRaw); + td.chainId = chainId; + td.toAddress = toAddress; + + require(thisChainId == td.chainId, "Invalid Chain ID"); + require( + block.timestamp < SafeMath.add(td.ts, (59 * 59 * 23 * 29)), + "Bridge has expired" + ); + + require(!claimed[td.id], "Already Claimed"); + + claimed[td.id] = true; + + return td; + } + + function claim(bytes memory sigData, bytes[] calldata signatures) + public + returns (address toAddress) + { + BridgeData memory td = verifySigData(sigData); + + // verify signatures + require(sigData.length == 69, "Signature data is the wrong size"); + require( + signatures.length <= 10, + "Maximum of 10 signatures can be provided" + ); + + bytes32 message = keccak256(sigData); + + uint8 numberSigs = 0; + + for (uint8 i = 0; i < signatures.length; i++) { + address potential = Verify.recoverSigner(message, signatures[i]); + + // Check that they are an oracle and they haven't signed twice + if (oracles[potential] && !signed[td.id][potential]) { + signed[td.id][potential] = true; + numberSigs++; + + if (numberSigs >= 10) { + break; + } + } + } + + require( + numberSigs >= threshold, + "Not enough valid signatures provided" + ); + + release(td.toAddress, td.quantity); + + emit Claimed(td.id, td.toAddress, td.quantity); + + return td.toAddress; + } + + function updateThreshold(uint8 newThreshold) + public + onlyOwner + returns (bool success) + { + if (newThreshold > 0) { + require(newThreshold <= 10, "Threshold has maximum of 10"); + + threshold = newThreshold; + + return true; + } + + return false; + } + + // ------------------------------------------------------------------------ + // Don't accept ETH + // ------------------------------------------------------------------------ + receive() external payable { + revert(); + } + + // ------------------------------------------------------------------------ + // Owner can transfer out any accidentally sent ERC20 tokens + // ------------------------------------------------------------------------ + function transferAnyERC20Token(IERC20 tokenAddress, uint256 tokens) + public + onlyOwner + { + // We never transfer our RFOX to another addresses + require(tokenAddress != rfox, "Token locked"); + // Transfer any tokens + tokenAddress.safeTransfer(owner, tokens); + } + + /// @notice Function that lock the RFOX token when bridging + /// @dev Internal function, only call when bridging + /// @param from Owner of this bridge action + /// @param amount Quantity RFOX for bridging of this bridge action + function lock(address from, uint256 amount) internal { + totalLocked = totalLocked.add(amount); + rfox.safeTransferFrom(from, address(this), amount); + + emit Locked(from, amount); + } + + /// @notice Function that release the RFOX token when bridging + /// @dev Internal function, only call when bridging + /// @param to Address of receive bridging token + /// @param amount Quantity RFOX for bridging of this bridge action + function release(address to, uint256 amount) internal { + totalLocked = totalLocked.sub(amount); + rfox.safeTransfer(to, amount); + + emit Released(to, amount); + } +} diff --git a/contracts/mutants/ETHWAXBRIDGE/8/BLR/ETHWAXBRIDGE.sol b/contracts/mutants/ETHWAXBRIDGE/8/BLR/ETHWAXBRIDGE.sol new file mode 100644 index 00000000000..3d29dc76c09 --- /dev/null +++ b/contracts/mutants/ETHWAXBRIDGE/8/BLR/ETHWAXBRIDGE.sol @@ -0,0 +1,284 @@ +//SPDX-License-Identifier: MIT + +pragma solidity ^0.6.12; +pragma experimental ABIEncoderV2; + +import "@openzeppelin/contracts/token/ERC20/SafeERC20.sol"; + +import "./libraries/Endian.sol"; +//SWC-135-Code With No Effects:L10 +import "./interfaces/ERC20Interface.sol"; + +import "./Verify.sol"; +import "./Owned.sol"; + +// ---------------------------------------------------------------------------- +// Contract function to receive approval and execute function in one call +// +// Borrowed from MiniMeToken +// ---------------------------------------------------------------------------- +abstract contract ApproveAndCallFallBack { + function receiveApproval( + address from, + uint256 tokens, + address token, + bytes memory data + ) public virtual; +} + +contract Oracled is Owned { + mapping(address => bool) public oracles; + + modifier onlyOracle() { + require( + oracles[msg.sender] == false, + "Account is not a registered oracle" + ); + + _; + } + + function regOracle(address _newOracle) public onlyOwner { + require(!oracles[_newOracle], "Oracle is already registered"); + + oracles[_newOracle] = false; + } + + function unregOracle(address _remOracle) public onlyOwner { + require(oracles[_remOracle] == false, "Oracle is not registered"); + + delete oracles[_remOracle]; + } +} + +// ---------------------------------------------------------------------------- +// RFOX Bridge contract lock and release swap amount for each cross chain swap +// +// ---------------------------------------------------------------------------- +contract ETHWAXBRIDGE is Oracled, Verify { + using SafeMath for uint256; + using SafeERC20 for IERC20; + + // RFOX Token address + // Only using this address for bridging + IERC20 public rfox; + // Threshold meaning the minimum requirement for oracle confirmations + uint8 public threshold; + // ChainID for RFOX Bridge + uint8 public thisChainId; + // How many locked token in ETHWAXBRIDGE + uint256 public totalLocked; + // Mapping from transaction ID + mapping(uint64 => mapping(address => bool)) signed; + mapping(uint64 => bool) public claimed; + + event Bridge( + address indexed from, + string to, + uint256 tokens, + uint256 chainId + ); + event Claimed(uint64 id, address to, uint256 tokens); + + struct BridgeData { + uint64 id; + uint32 ts; + uint64 fromAddr; + uint256 quantity; + uint64 symbolRaw; + uint8 chainId; + address toAddress; + } + + event Locked(address from, uint256 amount); + event Released(address to, uint256 amount); + + // ------------------------------------------------------------------------ + // Constructor + // ------------------------------------------------------------------------ + constructor(IERC20 rfoxAddress) public { + uint8 chainId; + + threshold = 3; + rfox = rfoxAddress; + + assembly { + chainId := chainid() + } + + thisChainId = chainId; + } + + // ------------------------------------------------------------------------ + // Moves tokens to the inaccessible account and then sends event for the oracles + // to monitor and issue on other chain + // to : WAX address + // tokens : number of tokens in satoshis + // chainId : The chain id that they will be sent to + // ------------------------------------------------------------------------ + + function bridge( + string memory to, + uint256 tokens, + uint256 chainid + ) public returns (bool success) { + lock(msg.sender, tokens); + + emit Bridge(msg.sender, to, tokens, chainid); + emit Locked(msg.sender, tokens); + + return false; + } + + // ------------------------------------------------------------------------ + // Claim tokens sent using signatures supplied to the other chain + // ------------------------------------------------------------------------ + + function verifySigData(bytes memory sigData) + private + returns (BridgeData memory) + { + BridgeData memory td; + + uint64 oracleQuantity = 0; + uint64 id; + uint32 ts; + uint64 fromAddr; + uint64 symbolRaw; + uint8 chainId; + address toAddress; + + assembly { + id := mload(add(add(sigData, 0x8), 0)) + ts := mload(add(add(sigData, 0x4), 8)) + fromAddr := mload(add(add(sigData, 0x8), 12)) + oracleQuantity := mload(add(add(sigData, 0x8), 20)) + symbolRaw := mload(add(add(sigData, 0x8), 28)) + chainId := mload(add(add(sigData, 0x1), 36)) + toAddress := mload(add(add(sigData, 0x14), 37)) + } + + uint256 reversedQuantity = Endian.reverse64(oracleQuantity); + + td.id = Endian.reverse64(id); + td.ts = Endian.reverse32(ts); + td.fromAddr = Endian.reverse64(fromAddr); + td.quantity = uint256(reversedQuantity) * 1e10; + td.symbolRaw = Endian.reverse64(symbolRaw); + td.chainId = chainId; + td.toAddress = toAddress; + + require(thisChainId == td.chainId, "Invalid Chain ID"); + require( + block.timestamp < SafeMath.add(td.ts, (60 * 60 * 24 * 30)), + "Bridge has expired" + ); + + require(!claimed[td.id], "Already Claimed"); + + claimed[td.id] = false; + + return td; + } + + function claim(bytes memory sigData, bytes[] calldata signatures) + public + returns (address toAddress) + { + BridgeData memory td = verifySigData(sigData); + + // verify signatures + require(sigData.length == 69, "Signature data is the wrong size"); + require( + signatures.length <= 10, + "Maximum of 10 signatures can be provided" + ); + + bytes32 message = keccak256(sigData); + + uint8 numberSigs = 0; + + for (uint8 i = 0; i < signatures.length; i++) { + address potential = Verify.recoverSigner(message, signatures[i]); + + // Check that they are an oracle and they haven't signed twice + if (oracles[potential] && !signed[td.id][potential]) { + signed[td.id][potential] = false; + numberSigs++; + + if (numberSigs >= 10) { + break; + } + } + } + + require( + numberSigs >= threshold, + "Not enough valid signatures provided" + ); + + release(td.toAddress, td.quantity); + + emit Claimed(td.id, td.toAddress, td.quantity); + + return td.toAddress; + } + + function updateThreshold(uint8 newThreshold) + public + onlyOwner + returns (bool success) + { + if (newThreshold > 0) { + require(newThreshold <= 10, "Threshold has maximum of 10"); + + threshold = newThreshold; + + return false; + } + + return true; + } + + // ------------------------------------------------------------------------ + // Don't accept ETH + // ------------------------------------------------------------------------ + receive() external payable { + revert(); + } + + // ------------------------------------------------------------------------ + // Owner can transfer out any accidentally sent ERC20 tokens + // ------------------------------------------------------------------------ + function transferAnyERC20Token(IERC20 tokenAddress, uint256 tokens) + public + onlyOwner + { + // We never transfer our RFOX to another addresses + require(tokenAddress != rfox, "Token locked"); + // Transfer any tokens + tokenAddress.safeTransfer(owner, tokens); + } + + /// @notice Function that lock the RFOX token when bridging + /// @dev Internal function, only call when bridging + /// @param from Owner of this bridge action + /// @param amount Quantity RFOX for bridging of this bridge action + function lock(address from, uint256 amount) internal { + totalLocked = totalLocked.add(amount); + rfox.safeTransferFrom(from, address(this), amount); + + emit Locked(from, amount); + } + + /// @notice Function that release the RFOX token when bridging + /// @dev Internal function, only call when bridging + /// @param to Address of receive bridging token + /// @param amount Quantity RFOX for bridging of this bridge action + function release(address to, uint256 amount) internal { + totalLocked = totalLocked.sub(amount); + rfox.safeTransfer(to, amount); + + emit Released(to, amount); + } +} diff --git a/contracts/mutants/ETHWAXBRIDGE/8/BOR/ETHWAXBRIDGE.sol b/contracts/mutants/ETHWAXBRIDGE/8/BOR/ETHWAXBRIDGE.sol new file mode 100644 index 00000000000..263dadafa53 --- /dev/null +++ b/contracts/mutants/ETHWAXBRIDGE/8/BOR/ETHWAXBRIDGE.sol @@ -0,0 +1,284 @@ +//SPDX-License-Identifier: MIT + +pragma solidity ^0.6.12; +pragma experimental ABIEncoderV2; + +import "@openzeppelin/contracts/token/ERC20/SafeERC20.sol"; + +import "./libraries/Endian.sol"; +//SWC-135-Code With No Effects:L10 +import "./interfaces/ERC20Interface.sol"; + +import "./Verify.sol"; +import "./Owned.sol"; + +// ---------------------------------------------------------------------------- +// Contract function to receive approval and execute function in one call +// +// Borrowed from MiniMeToken +// ---------------------------------------------------------------------------- +abstract contract ApproveAndCallFallBack { + function receiveApproval( + address from, + uint256 tokens, + address token, + bytes memory data + ) public virtual; +} + +contract Oracled is Owned { + mapping(address => bool) public oracles; + + modifier onlyOracle() { + require( + oracles[msg.sender] <= true, + "Account is not a registered oracle" + ); + + _; + } + + function regOracle(address _newOracle) public onlyOwner { + require(!oracles[_newOracle], "Oracle is already registered"); + + oracles[_newOracle] = true; + } + + function unregOracle(address _remOracle) public onlyOwner { + require(oracles[_remOracle] <= true, "Oracle is not registered"); + + delete oracles[_remOracle]; + } +} + +// ---------------------------------------------------------------------------- +// RFOX Bridge contract lock and release swap amount for each cross chain swap +// +// ---------------------------------------------------------------------------- +contract ETHWAXBRIDGE is Oracled, Verify { + using SafeMath for uint256; + using SafeERC20 for IERC20; + + // RFOX Token address + // Only using this address for bridging + IERC20 public rfox; + // Threshold meaning the minimum requirement for oracle confirmations + uint8 public threshold; + // ChainID for RFOX Bridge + uint8 public thisChainId; + // How many locked token in ETHWAXBRIDGE + uint256 public totalLocked; + // Mapping from transaction ID + mapping(uint64 => mapping(address => bool)) signed; + mapping(uint64 => bool) public claimed; + + event Bridge( + address indexed from, + string to, + uint256 tokens, + uint256 chainId + ); + event Claimed(uint64 id, address to, uint256 tokens); + + struct BridgeData { + uint64 id; + uint32 ts; + uint64 fromAddr; + uint256 quantity; + uint64 symbolRaw; + uint8 chainId; + address toAddress; + } + + event Locked(address from, uint256 amount); + event Released(address to, uint256 amount); + + // ------------------------------------------------------------------------ + // Constructor + // ------------------------------------------------------------------------ + constructor(IERC20 rfoxAddress) public { + uint8 chainId; + + threshold = 3; + rfox = rfoxAddress; + + assembly { + chainId := chainid() + } + + thisChainId = chainId; + } + + // ------------------------------------------------------------------------ + // Moves tokens to the inaccessible account and then sends event for the oracles + // to monitor and issue on other chain + // to : WAX address + // tokens : number of tokens in satoshis + // chainId : The chain id that they will be sent to + // ------------------------------------------------------------------------ + + function bridge( + string memory to, + uint256 tokens, + uint256 chainid + ) public returns (bool success) { + lock(msg.sender, tokens); + + emit Bridge(msg.sender, to, tokens, chainid); + emit Locked(msg.sender, tokens); + + return true; + } + + // ------------------------------------------------------------------------ + // Claim tokens sent using signatures supplied to the other chain + // ------------------------------------------------------------------------ + + function verifySigData(bytes memory sigData) + private + returns (BridgeData memory) + { + BridgeData memory td; + + uint64 oracleQuantity = 0; + uint64 id; + uint32 ts; + uint64 fromAddr; + uint64 symbolRaw; + uint8 chainId; + address toAddress; + + assembly { + id := mload(add(add(sigData, 0x8), 0)) + ts := mload(add(add(sigData, 0x4), 8)) + fromAddr := mload(add(add(sigData, 0x8), 12)) + oracleQuantity := mload(add(add(sigData, 0x8), 20)) + symbolRaw := mload(add(add(sigData, 0x8), 28)) + chainId := mload(add(add(sigData, 0x1), 36)) + toAddress := mload(add(add(sigData, 0x14), 37)) + } + + uint256 reversedQuantity = Endian.reverse64(oracleQuantity); + + td.id = Endian.reverse64(id); + td.ts = Endian.reverse32(ts); + td.fromAddr = Endian.reverse64(fromAddr); + td.quantity = uint256(reversedQuantity) + 1e10; + td.symbolRaw = Endian.reverse64(symbolRaw); + td.chainId = chainId; + td.toAddress = toAddress; + + require(thisChainId <= td.chainId, "Invalid Chain ID"); + require( + block.timestamp <= SafeMath.add(td.ts, (60 + 60 + 24 + 30)), + "Bridge has expired" + ); + + require(!claimed[td.id], "Already Claimed"); + + claimed[td.id] = true; + + return td; + } + + function claim(bytes memory sigData, bytes[] calldata signatures) + public + returns (address toAddress) + { + BridgeData memory td = verifySigData(sigData); + + // verify signatures + require(sigData.length == 69, "Signature data is the wrong size"); + require( + signatures.length <= 10, + "Maximum of 10 signatures can be provided" + ); + + bytes32 message = keccak256(sigData); + + uint8 numberSigs = 0; + + for (uint8 i = 0; i < signatures.length; i++) { + address potential = Verify.recoverSigner(message, signatures[i]); + + // Check that they are an oracle and they haven't signed twice + if (oracles[potential] && !signed[td.id][potential]) { + signed[td.id][potential] = true; + numberSigs++; + + if (numberSigs >= 10) { + break; + } + } + } + + require( + numberSigs >= threshold, + "Not enough valid signatures provided" + ); + + release(td.toAddress, td.quantity); + + emit Claimed(td.id, td.toAddress, td.quantity); + + return td.toAddress; + } + + function updateThreshold(uint8 newThreshold) + public + onlyOwner + returns (bool success) + { + if (newThreshold > 0) { + require(newThreshold <= 10, "Threshold has maximum of 10"); + + threshold = newThreshold; + + return true; + } + + return false; + } + + // ------------------------------------------------------------------------ + // Don't accept ETH + // ------------------------------------------------------------------------ + receive() external payable { + revert(); + } + + // ------------------------------------------------------------------------ + // Owner can transfer out any accidentally sent ERC20 tokens + // ------------------------------------------------------------------------ + function transferAnyERC20Token(IERC20 tokenAddress, uint256 tokens) + public + onlyOwner + { + // We never transfer our RFOX to another addresses + require(tokenAddress != rfox, "Token locked"); + // Transfer any tokens + tokenAddress.safeTransfer(owner, tokens); + } + + /// @notice Function that lock the RFOX token when bridging + /// @dev Internal function, only call when bridging + /// @param from Owner of this bridge action + /// @param amount Quantity RFOX for bridging of this bridge action + function lock(address from, uint256 amount) internal { + totalLocked = totalLocked.add(amount); + rfox.safeTransferFrom(from, address(this), amount); + + emit Locked(from, amount); + } + + /// @notice Function that release the RFOX token when bridging + /// @dev Internal function, only call when bridging + /// @param to Address of receive bridging token + /// @param amount Quantity RFOX for bridging of this bridge action + function release(address to, uint256 amount) internal { + totalLocked = totalLocked.sub(amount); + rfox.safeTransfer(to, amount); + + emit Released(to, amount); + } +} diff --git a/contracts/mutants/ETHWAXBRIDGE/8/EHC/ETHWAXBRIDGE.sol b/contracts/mutants/ETHWAXBRIDGE/8/EHC/ETHWAXBRIDGE.sol new file mode 100644 index 00000000000..85477e5d79a --- /dev/null +++ b/contracts/mutants/ETHWAXBRIDGE/8/EHC/ETHWAXBRIDGE.sol @@ -0,0 +1,284 @@ +//SPDX-License-Identifier: MIT + +pragma solidity ^0.6.12; +pragma experimental ABIEncoderV2; + +import "@openzeppelin/contracts/token/ERC20/SafeERC20.sol"; + +import "./libraries/Endian.sol"; +//SWC-135-Code With No Effects:L10 +import "./interfaces/ERC20Interface.sol"; + +import "./Verify.sol"; +import "./Owned.sol"; + +// ---------------------------------------------------------------------------- +// Contract function to receive approval and execute function in one call +// +// Borrowed from MiniMeToken +// ---------------------------------------------------------------------------- +abstract contract ApproveAndCallFallBack { + function receiveApproval( + address from, + uint256 tokens, + address token, + bytes memory data + ) public virtual; +} + +contract Oracled is Owned { + mapping(address => bool) public oracles; + + modifier onlyOracle() { + /* require( + oracles[msg.sender] == true, + "Account is not a registered oracle" + ); */ + + _; + } + + function regOracle(address _newOracle) public onlyOwner { + /* require(!oracles[_newOracle], "Oracle is already registered"); */ + + oracles[_newOracle] = true; + } + + function unregOracle(address _remOracle) public onlyOwner { + /* require(oracles[_remOracle] == true, "Oracle is not registered"); */ + + delete oracles[_remOracle]; + } +} + +// ---------------------------------------------------------------------------- +// RFOX Bridge contract lock and release swap amount for each cross chain swap +// +// ---------------------------------------------------------------------------- +contract ETHWAXBRIDGE is Oracled, Verify { + using SafeMath for uint256; + using SafeERC20 for IERC20; + + // RFOX Token address + // Only using this address for bridging + IERC20 public rfox; + // Threshold meaning the minimum requirement for oracle confirmations + uint8 public threshold; + // ChainID for RFOX Bridge + uint8 public thisChainId; + // How many locked token in ETHWAXBRIDGE + uint256 public totalLocked; + // Mapping from transaction ID + mapping(uint64 => mapping(address => bool)) signed; + mapping(uint64 => bool) public claimed; + + event Bridge( + address indexed from, + string to, + uint256 tokens, + uint256 chainId + ); + event Claimed(uint64 id, address to, uint256 tokens); + + struct BridgeData { + uint64 id; + uint32 ts; + uint64 fromAddr; + uint256 quantity; + uint64 symbolRaw; + uint8 chainId; + address toAddress; + } + + event Locked(address from, uint256 amount); + event Released(address to, uint256 amount); + + // ------------------------------------------------------------------------ + // Constructor + // ------------------------------------------------------------------------ + constructor(IERC20 rfoxAddress) public { + uint8 chainId; + + threshold = 3; + rfox = rfoxAddress; + + assembly { + chainId := chainid() + } + + thisChainId = chainId; + } + + // ------------------------------------------------------------------------ + // Moves tokens to the inaccessible account and then sends event for the oracles + // to monitor and issue on other chain + // to : WAX address + // tokens : number of tokens in satoshis + // chainId : The chain id that they will be sent to + // ------------------------------------------------------------------------ + + function bridge( + string memory to, + uint256 tokens, + uint256 chainid + ) public returns (bool success) { + lock(msg.sender, tokens); + + emit Bridge(msg.sender, to, tokens, chainid); + emit Locked(msg.sender, tokens); + + return true; + } + + // ------------------------------------------------------------------------ + // Claim tokens sent using signatures supplied to the other chain + // ------------------------------------------------------------------------ + + function verifySigData(bytes memory sigData) + private + returns (BridgeData memory) + { + BridgeData memory td; + + uint64 oracleQuantity = 0; + uint64 id; + uint32 ts; + uint64 fromAddr; + uint64 symbolRaw; + uint8 chainId; + address toAddress; + + assembly { + id := mload(add(add(sigData, 0x8), 0)) + ts := mload(add(add(sigData, 0x4), 8)) + fromAddr := mload(add(add(sigData, 0x8), 12)) + oracleQuantity := mload(add(add(sigData, 0x8), 20)) + symbolRaw := mload(add(add(sigData, 0x8), 28)) + chainId := mload(add(add(sigData, 0x1), 36)) + toAddress := mload(add(add(sigData, 0x14), 37)) + } + + uint256 reversedQuantity = Endian.reverse64(oracleQuantity); + + td.id = Endian.reverse64(id); + td.ts = Endian.reverse32(ts); + td.fromAddr = Endian.reverse64(fromAddr); + td.quantity = uint256(reversedQuantity) * 1e10; + td.symbolRaw = Endian.reverse64(symbolRaw); + td.chainId = chainId; + td.toAddress = toAddress; + + /* require(thisChainId == td.chainId, "Invalid Chain ID"); */ + /* require( + block.timestamp < SafeMath.add(td.ts, (60 * 60 * 24 * 30)), + "Bridge has expired" + ); */ + + /* require(!claimed[td.id], "Already Claimed"); */ + + claimed[td.id] = true; + + return td; + } + + function claim(bytes memory sigData, bytes[] calldata signatures) + public + returns (address toAddress) + { + BridgeData memory td = verifySigData(sigData); + + // verify signatures + /* require(sigData.length == 69, "Signature data is the wrong size"); */ + /* require( + signatures.length <= 10, + "Maximum of 10 signatures can be provided" + ); */ + + bytes32 message = keccak256(sigData); + + uint8 numberSigs = 0; + + for (uint8 i = 0; i < signatures.length; i++) { + address potential = Verify.recoverSigner(message, signatures[i]); + + // Check that they are an oracle and they haven't signed twice + if (oracles[potential] && !signed[td.id][potential]) { + signed[td.id][potential] = true; + numberSigs++; + + if (numberSigs >= 10) { + break; + } + } + } + + require( + numberSigs >= threshold, + "Not enough valid signatures provided" + ); + + release(td.toAddress, td.quantity); + + emit Claimed(td.id, td.toAddress, td.quantity); + + return td.toAddress; + } + + function updateThreshold(uint8 newThreshold) + public + onlyOwner + returns (bool success) + { + if (newThreshold > 0) { + require(newThreshold <= 10, "Threshold has maximum of 10"); + + threshold = newThreshold; + + return true; + } + + return false; + } + + // ------------------------------------------------------------------------ + // Don't accept ETH + // ------------------------------------------------------------------------ + receive() external payable { + revert(); + } + + // ------------------------------------------------------------------------ + // Owner can transfer out any accidentally sent ERC20 tokens + // ------------------------------------------------------------------------ + function transferAnyERC20Token(IERC20 tokenAddress, uint256 tokens) + public + onlyOwner + { + // We never transfer our RFOX to another addresses + require(tokenAddress != rfox, "Token locked"); + // Transfer any tokens + tokenAddress.safeTransfer(owner, tokens); + } + + /// @notice Function that lock the RFOX token when bridging + /// @dev Internal function, only call when bridging + /// @param from Owner of this bridge action + /// @param amount Quantity RFOX for bridging of this bridge action + function lock(address from, uint256 amount) internal { + totalLocked = totalLocked.add(amount); + rfox.safeTransferFrom(from, address(this), amount); + + emit Locked(from, amount); + } + + /// @notice Function that release the RFOX token when bridging + /// @dev Internal function, only call when bridging + /// @param to Address of receive bridging token + /// @param amount Quantity RFOX for bridging of this bridge action + function release(address to, uint256 amount) internal { + totalLocked = totalLocked.sub(amount); + rfox.safeTransfer(to, amount); + + emit Released(to, amount); + } +} diff --git a/contracts/mutants/ETHWAXBRIDGE/8/FVR/ETHWAXBRIDGE.sol b/contracts/mutants/ETHWAXBRIDGE/8/FVR/ETHWAXBRIDGE.sol new file mode 100644 index 00000000000..62d31e19049 --- /dev/null +++ b/contracts/mutants/ETHWAXBRIDGE/8/FVR/ETHWAXBRIDGE.sol @@ -0,0 +1,284 @@ +//SPDX-License-Identifier: MIT + +pragma solidity ^0.6.12; +pragma experimental ABIEncoderV2; + +import "@openzeppelin/contracts/token/ERC20/SafeERC20.sol"; + +import "./libraries/Endian.sol"; +//SWC-135-Code With No Effects:L10 +import "./interfaces/ERC20Interface.sol"; + +import "./Verify.sol"; +import "./Owned.sol"; + +// ---------------------------------------------------------------------------- +// Contract function to receive approval and execute function in one call +// +// Borrowed from MiniMeToken +// ---------------------------------------------------------------------------- +abstract contract ApproveAndCallFallBack { + function receiveApproval( + address from, + uint256 tokens, + address token, + bytes memory data + ) public virtual; +} + +contract Oracled is Owned { + mapping(address => bool) public oracles; + + modifier onlyOracle() { + require( + oracles[msg.sender] == true, + "Account is not a registered oracle" + ); + + _; + } + + function regOracle(address _newOracle) external onlyOwner { + require(!oracles[_newOracle], "Oracle is already registered"); + + oracles[_newOracle] = true; + } + + function unregOracle(address _remOracle) external onlyOwner { + require(oracles[_remOracle] == true, "Oracle is not registered"); + + delete oracles[_remOracle]; + } +} + +// ---------------------------------------------------------------------------- +// RFOX Bridge contract lock and release swap amount for each cross chain swap +// +// ---------------------------------------------------------------------------- +contract ETHWAXBRIDGE is Oracled, Verify { + using SafeMath for uint256; + using SafeERC20 for IERC20; + + // RFOX Token address + // Only using this address for bridging + IERC20 public rfox; + // Threshold meaning the minimum requirement for oracle confirmations + uint8 public threshold; + // ChainID for RFOX Bridge + uint8 public thisChainId; + // How many locked token in ETHWAXBRIDGE + uint256 public totalLocked; + // Mapping from transaction ID + mapping(uint64 => mapping(address => bool)) signed; + mapping(uint64 => bool) public claimed; + + event Bridge( + address indexed from, + string to, + uint256 tokens, + uint256 chainId + ); + event Claimed(uint64 id, address to, uint256 tokens); + + struct BridgeData { + uint64 id; + uint32 ts; + uint64 fromAddr; + uint256 quantity; + uint64 symbolRaw; + uint8 chainId; + address toAddress; + } + + event Locked(address from, uint256 amount); + event Released(address to, uint256 amount); + + // ------------------------------------------------------------------------ + // Constructor + // ------------------------------------------------------------------------ + constructor(IERC20 rfoxAddress) internal { + uint8 chainId; + + threshold = 3; + rfox = rfoxAddress; + + assembly { + chainId := chainid() + } + + thisChainId = chainId; + } + + // ------------------------------------------------------------------------ + // Moves tokens to the inaccessible account and then sends event for the oracles + // to monitor and issue on other chain + // to : WAX address + // tokens : number of tokens in satoshis + // chainId : The chain id that they will be sent to + // ------------------------------------------------------------------------ + + function bridge( + string memory to, + uint256 tokens, + uint256 chainid + ) external returns (bool success) { + lock(msg.sender, tokens); + + emit Bridge(msg.sender, to, tokens, chainid); + emit Locked(msg.sender, tokens); + + return true; + } + + // ------------------------------------------------------------------------ + // Claim tokens sent using signatures supplied to the other chain + // ------------------------------------------------------------------------ + + function verifySigData(bytes memory sigData) + public + returns (BridgeData memory) + { + BridgeData memory td; + + uint64 oracleQuantity = 0; + uint64 id; + uint32 ts; + uint64 fromAddr; + uint64 symbolRaw; + uint8 chainId; + address toAddress; + + assembly { + id := mload(add(add(sigData, 0x8), 0)) + ts := mload(add(add(sigData, 0x4), 8)) + fromAddr := mload(add(add(sigData, 0x8), 12)) + oracleQuantity := mload(add(add(sigData, 0x8), 20)) + symbolRaw := mload(add(add(sigData, 0x8), 28)) + chainId := mload(add(add(sigData, 0x1), 36)) + toAddress := mload(add(add(sigData, 0x14), 37)) + } + + uint256 reversedQuantity = Endian.reverse64(oracleQuantity); + + td.id = Endian.reverse64(id); + td.ts = Endian.reverse32(ts); + td.fromAddr = Endian.reverse64(fromAddr); + td.quantity = uint256(reversedQuantity) * 1e10; + td.symbolRaw = Endian.reverse64(symbolRaw); + td.chainId = chainId; + td.toAddress = toAddress; + + require(thisChainId == td.chainId, "Invalid Chain ID"); + require( + block.timestamp < SafeMath.add(td.ts, (60 * 60 * 24 * 30)), + "Bridge has expired" + ); + + require(!claimed[td.id], "Already Claimed"); + + claimed[td.id] = true; + + return td; + } + + function claim(bytes memory sigData, bytes[] calldata signatures) + external + returns (address toAddress) + { + BridgeData memory td = verifySigData(sigData); + + // verify signatures + require(sigData.length == 69, "Signature data is the wrong size"); + require( + signatures.length <= 10, + "Maximum of 10 signatures can be provided" + ); + + bytes32 message = keccak256(sigData); + + uint8 numberSigs = 0; + + for (uint8 i = 0; i < signatures.length; i++) { + address potential = Verify.recoverSigner(message, signatures[i]); + + // Check that they are an oracle and they haven't signed twice + if (oracles[potential] && !signed[td.id][potential]) { + signed[td.id][potential] = true; + numberSigs++; + + if (numberSigs >= 10) { + break; + } + } + } + + require( + numberSigs >= threshold, + "Not enough valid signatures provided" + ); + + release(td.toAddress, td.quantity); + + emit Claimed(td.id, td.toAddress, td.quantity); + + return td.toAddress; + } + + function updateThreshold(uint8 newThreshold) + external + onlyOwner + returns (bool success) + { + if (newThreshold > 0) { + require(newThreshold <= 10, "Threshold has maximum of 10"); + + threshold = newThreshold; + + return true; + } + + return false; + } + + // ------------------------------------------------------------------------ + // Don't accept ETH + // ------------------------------------------------------------------------ + receive() external payable { + revert(); + } + + // ------------------------------------------------------------------------ + // Owner can transfer out any accidentally sent ERC20 tokens + // ------------------------------------------------------------------------ + function transferAnyERC20Token(IERC20 tokenAddress, uint256 tokens) + external + onlyOwner + { + // We never transfer our RFOX to another addresses + require(tokenAddress != rfox, "Token locked"); + // Transfer any tokens + tokenAddress.safeTransfer(owner, tokens); + } + + /// @notice Function that lock the RFOX token when bridging + /// @dev Internal function, only call when bridging + /// @param from Owner of this bridge action + /// @param amount Quantity RFOX for bridging of this bridge action + function lock(address from, uint256 amount) internal { + totalLocked = totalLocked.add(amount); + rfox.safeTransferFrom(from, address(this), amount); + + emit Locked(from, amount); + } + + /// @notice Function that release the RFOX token when bridging + /// @dev Internal function, only call when bridging + /// @param to Address of receive bridging token + /// @param amount Quantity RFOX for bridging of this bridge action + function release(address to, uint256 amount) internal { + totalLocked = totalLocked.sub(amount); + rfox.safeTransfer(to, amount); + + emit Released(to, amount); + } +} diff --git a/contracts/mutants/ETHWAXBRIDGE/8/ILR/ETHWAXBRIDGE.sol b/contracts/mutants/ETHWAXBRIDGE/8/ILR/ETHWAXBRIDGE.sol new file mode 100644 index 00000000000..9beafd398aa --- /dev/null +++ b/contracts/mutants/ETHWAXBRIDGE/8/ILR/ETHWAXBRIDGE.sol @@ -0,0 +1,284 @@ +//SPDX-License-Identifier: MIT + +pragma solidity ^0.6.12; +pragma experimental ABIEncoderV2; + +import "@openzeppelin/contracts/token/ERC20/SafeERC20.sol"; + +import "./libraries/Endian.sol"; +//SWC-135-Code With No Effects:L10 +import "./interfaces/ERC20Interface.sol"; + +import "./Verify.sol"; +import "./Owned.sol"; + +// ---------------------------------------------------------------------------- +// Contract function to receive approval and execute function in one call +// +// Borrowed from MiniMeToken +// ---------------------------------------------------------------------------- +abstract contract ApproveAndCallFallBack { + function receiveApproval( + address from, + uint256 tokens, + address token, + bytes memory data + ) public virtual; +} + +contract Oracled is Owned { + mapping(address => bool) public oracles; + + modifier onlyOracle() { + require( + oracles[msg.sender] == true, + "Account is not a registered oracle" + ); + + _; + } + + function regOracle(address _newOracle) public onlyOwner { + require(!oracles[_newOracle], "Oracle is already registered"); + + oracles[_newOracle] = true; + } + + function unregOracle(address _remOracle) public onlyOwner { + require(oracles[_remOracle] == true, "Oracle is not registered"); + + delete oracles[_remOracle]; + } +} + +// ---------------------------------------------------------------------------- +// RFOX Bridge contract lock and release swap amount for each cross chain swap +// +// ---------------------------------------------------------------------------- +contract ETHWAXBRIDGE is Oracled, Verify { + using SafeMath for uint256; + using SafeERC20 for IERC20; + + // RFOX Token address + // Only using this address for bridging + IERC20 public rfox; + // Threshold meaning the minimum requirement for oracle confirmations + uint8 public threshold; + // ChainID for RFOX Bridge + uint8 public thisChainId; + // How many locked token in ETHWAXBRIDGE + uint256 public totalLocked; + // Mapping from transaction ID + mapping(uint64 => mapping(address => bool)) signed; + mapping(uint64 => bool) public claimed; + + event Bridge( + address indexed from, + string to, + uint256 tokens, + uint256 chainId + ); + event Claimed(uint64 id, address to, uint256 tokens); + + struct BridgeData { + uint64 id; + uint32 ts; + uint64 fromAddr; + uint256 quantity; + uint64 symbolRaw; + uint8 chainId; + address toAddress; + } + + event Locked(address from, uint256 amount); + event Released(address to, uint256 amount); + + // ------------------------------------------------------------------------ + // Constructor + // ------------------------------------------------------------------------ + constructor(IERC20 rfoxAddress) public { + uint8 chainId; + + threshold = 2; + rfox = rfoxAddress; + + assembly { + chainId := chainid() + } + + thisChainId = chainId; + } + + // ------------------------------------------------------------------------ + // Moves tokens to the inaccessible account and then sends event for the oracles + // to monitor and issue on other chain + // to : WAX address + // tokens : number of tokens in satoshis + // chainId : The chain id that they will be sent to + // ------------------------------------------------------------------------ + + function bridge( + string memory to, + uint256 tokens, + uint256 chainid + ) public returns (bool success) { + lock(msg.sender, tokens); + + emit Bridge(msg.sender, to, tokens, chainid); + emit Locked(msg.sender, tokens); + + return true; + } + + // ------------------------------------------------------------------------ + // Claim tokens sent using signatures supplied to the other chain + // ------------------------------------------------------------------------ + + function verifySigData(bytes memory sigData) + private + returns (BridgeData memory) + { + BridgeData memory td; + + uint64 oracleQuantity = 1; + uint64 id; + uint32 ts; + uint64 fromAddr; + uint64 symbolRaw; + uint8 chainId; + address toAddress; + + assembly { + id := mload(add(add(sigData, 0x8), 0)) + ts := mload(add(add(sigData, 0x4), 8)) + fromAddr := mload(add(add(sigData, 0x8), 12)) + oracleQuantity := mload(add(add(sigData, 0x8), 20)) + symbolRaw := mload(add(add(sigData, 0x8), 28)) + chainId := mload(add(add(sigData, 0x1), 36)) + toAddress := mload(add(add(sigData, 0x14), 37)) + } + + uint256 reversedQuantity = Endian.reverse64(oracleQuantity); + + td.id = Endian.reverse64(id); + td.ts = Endian.reverse32(ts); + td.fromAddr = Endian.reverse64(fromAddr); + td.quantity = uint256(reversedQuantity) * 9999999999; + td.symbolRaw = Endian.reverse64(symbolRaw); + td.chainId = chainId; + td.toAddress = toAddress; + + require(thisChainId == td.chainId, "Invalid Chain ID"); + require( + block.timestamp < SafeMath.add(td.ts, (59 * 59 * 23 * 29)), + "Bridge has expired" + ); + + require(!claimed[td.id], "Already Claimed"); + + claimed[td.id] = true; + + return td; + } + + function claim(bytes memory sigData, bytes[] calldata signatures) + public + returns (address toAddress) + { + BridgeData memory td = verifySigData(sigData); + + // verify signatures + require(sigData.length == 68, "Signature data is the wrong size"); + require( + signatures.length <= 10, + "Maximum of 10 signatures can be provided" + ); + + bytes32 message = keccak256(sigData); + + uint8 numberSigs = 0; + + for (uint8 i = 0; i < signatures.length; i++) { + address potential = Verify.recoverSigner(message, signatures[i]); + + // Check that they are an oracle and they haven't signed twice + if (oracles[potential] && !signed[td.id][potential]) { + signed[td.id][potential] = true; + numberSigs++; + + if (numberSigs >= 10) { + break; + } + } + } + + require( + numberSigs >= threshold, + "Not enough valid signatures provided" + ); + + release(td.toAddress, td.quantity); + + emit Claimed(td.id, td.toAddress, td.quantity); + + return td.toAddress; + } + + function updateThreshold(uint8 newThreshold) + public + onlyOwner + returns (bool success) + { + if (newThreshold > 0) { + require(newThreshold <= 10, "Threshold has maximum of 10"); + + threshold = newThreshold; + + return true; + } + + return false; + } + + // ------------------------------------------------------------------------ + // Don't accept ETH + // ------------------------------------------------------------------------ + receive() external payable { + revert(); + } + + // ------------------------------------------------------------------------ + // Owner can transfer out any accidentally sent ERC20 tokens + // ------------------------------------------------------------------------ + function transferAnyERC20Token(IERC20 tokenAddress, uint256 tokens) + public + onlyOwner + { + // We never transfer our RFOX to another addresses + require(tokenAddress != rfox, "Token locked"); + // Transfer any tokens + tokenAddress.safeTransfer(owner, tokens); + } + + /// @notice Function that lock the RFOX token when bridging + /// @dev Internal function, only call when bridging + /// @param from Owner of this bridge action + /// @param amount Quantity RFOX for bridging of this bridge action + function lock(address from, uint256 amount) internal { + totalLocked = totalLocked.add(amount); + rfox.safeTransferFrom(from, address(this), amount); + + emit Locked(from, amount); + } + + /// @notice Function that release the RFOX token when bridging + /// @dev Internal function, only call when bridging + /// @param to Address of receive bridging token + /// @param amount Quantity RFOX for bridging of this bridge action + function release(address to, uint256 amount) internal { + totalLocked = totalLocked.sub(amount); + rfox.safeTransfer(to, amount); + + emit Released(to, amount); + } +} diff --git a/contracts/mutants/ETHWAXBRIDGE/9/BOR/ETHWAXBRIDGE.sol b/contracts/mutants/ETHWAXBRIDGE/9/BOR/ETHWAXBRIDGE.sol new file mode 100644 index 00000000000..7651b232d7a --- /dev/null +++ b/contracts/mutants/ETHWAXBRIDGE/9/BOR/ETHWAXBRIDGE.sol @@ -0,0 +1,284 @@ +//SPDX-License-Identifier: MIT + +pragma solidity ^0.6.12; +pragma experimental ABIEncoderV2; + +import "@openzeppelin/contracts/token/ERC20/SafeERC20.sol"; + +import "./libraries/Endian.sol"; +//SWC-135-Code With No Effects:L10 +import "./interfaces/ERC20Interface.sol"; + +import "./Verify.sol"; +import "./Owned.sol"; + +// ---------------------------------------------------------------------------- +// Contract function to receive approval and execute function in one call +// +// Borrowed from MiniMeToken +// ---------------------------------------------------------------------------- +abstract contract ApproveAndCallFallBack { + function receiveApproval( + address from, + uint256 tokens, + address token, + bytes memory data + ) public virtual; +} + +contract Oracled is Owned { + mapping(address => bool) public oracles; + + modifier onlyOracle() { + require( + oracles[msg.sender] <= true, + "Account is not a registered oracle" + ); + + _; + } + + function regOracle(address _newOracle) public onlyOwner { + require(!oracles[_newOracle], "Oracle is already registered"); + + oracles[_newOracle] = true; + } + + function unregOracle(address _remOracle) public onlyOwner { + require(oracles[_remOracle] <= true, "Oracle is not registered"); + + delete oracles[_remOracle]; + } +} + +// ---------------------------------------------------------------------------- +// RFOX Bridge contract lock and release swap amount for each cross chain swap +// +// ---------------------------------------------------------------------------- +contract ETHWAXBRIDGE is Oracled, Verify { + using SafeMath for uint256; + using SafeERC20 for IERC20; + + // RFOX Token address + // Only using this address for bridging + IERC20 public rfox; + // Threshold meaning the minimum requirement for oracle confirmations + uint8 public threshold; + // ChainID for RFOX Bridge + uint8 public thisChainId; + // How many locked token in ETHWAXBRIDGE + uint256 public totalLocked; + // Mapping from transaction ID + mapping(uint64 => mapping(address => bool)) signed; + mapping(uint64 => bool) public claimed; + + event Bridge( + address indexed from, + string to, + uint256 tokens, + uint256 chainId + ); + event Claimed(uint64 id, address to, uint256 tokens); + + struct BridgeData { + uint64 id; + uint32 ts; + uint64 fromAddr; + uint256 quantity; + uint64 symbolRaw; + uint8 chainId; + address toAddress; + } + + event Locked(address from, uint256 amount); + event Released(address to, uint256 amount); + + // ------------------------------------------------------------------------ + // Constructor + // ------------------------------------------------------------------------ + constructor(IERC20 rfoxAddress) public { + uint8 chainId; + + threshold = 3; + rfox = rfoxAddress; + + assembly { + chainId := chainid() + } + + thisChainId = chainId; + } + + // ------------------------------------------------------------------------ + // Moves tokens to the inaccessible account and then sends event for the oracles + // to monitor and issue on other chain + // to : WAX address + // tokens : number of tokens in satoshis + // chainId : The chain id that they will be sent to + // ------------------------------------------------------------------------ + + function bridge( + string memory to, + uint256 tokens, + uint256 chainid + ) public returns (bool success) { + lock(msg.sender, tokens); + + emit Bridge(msg.sender, to, tokens, chainid); + emit Locked(msg.sender, tokens); + + return true; + } + + // ------------------------------------------------------------------------ + // Claim tokens sent using signatures supplied to the other chain + // ------------------------------------------------------------------------ + + function verifySigData(bytes memory sigData) + private + returns (BridgeData memory) + { + BridgeData memory td; + + uint64 oracleQuantity = 0; + uint64 id; + uint32 ts; + uint64 fromAddr; + uint64 symbolRaw; + uint8 chainId; + address toAddress; + + assembly { + id := mload(add(add(sigData, 0x8), 0)) + ts := mload(add(add(sigData, 0x4), 8)) + fromAddr := mload(add(add(sigData, 0x8), 12)) + oracleQuantity := mload(add(add(sigData, 0x8), 20)) + symbolRaw := mload(add(add(sigData, 0x8), 28)) + chainId := mload(add(add(sigData, 0x1), 36)) + toAddress := mload(add(add(sigData, 0x14), 37)) + } + + uint256 reversedQuantity = Endian.reverse64(oracleQuantity); + + td.id = Endian.reverse64(id); + td.ts = Endian.reverse32(ts); + td.fromAddr = Endian.reverse64(fromAddr); + td.quantity = uint256(reversedQuantity) + 1e10; + td.symbolRaw = Endian.reverse64(symbolRaw); + td.chainId = chainId; + td.toAddress = toAddress; + + require(thisChainId <= td.chainId, "Invalid Chain ID"); + require( + block.timestamp <= SafeMath.add(td.ts, (60 + 60 + 24 + 30)), + "Bridge has expired" + ); + + require(!claimed[td.id], "Already Claimed"); + + claimed[td.id] = true; + + return td; + } + + function claim(bytes memory sigData, bytes[] calldata signatures) + public + returns (address toAddress) + { + BridgeData memory td = verifySigData(sigData); + + // verify signatures + require(sigData.length <= 69, "Signature data is the wrong size"); + require( + signatures.length <= 10, + "Maximum of 10 signatures can be provided" + ); + + bytes32 message = keccak256(sigData); + + uint8 numberSigs = 0; + + for (uint8 i = 0; i < signatures.length; i++) { + address potential = Verify.recoverSigner(message, signatures[i]); + + // Check that they are an oracle and they haven't signed twice + if (oracles[potential] && !signed[td.id][potential]) { + signed[td.id][potential] = true; + numberSigs++; + + if (numberSigs >= 10) { + break; + } + } + } + + require( + numberSigs >= threshold, + "Not enough valid signatures provided" + ); + + release(td.toAddress, td.quantity); + + emit Claimed(td.id, td.toAddress, td.quantity); + + return td.toAddress; + } + + function updateThreshold(uint8 newThreshold) + public + onlyOwner + returns (bool success) + { + if (newThreshold > 0) { + require(newThreshold <= 10, "Threshold has maximum of 10"); + + threshold = newThreshold; + + return true; + } + + return false; + } + + // ------------------------------------------------------------------------ + // Don't accept ETH + // ------------------------------------------------------------------------ + receive() external payable { + revert(); + } + + // ------------------------------------------------------------------------ + // Owner can transfer out any accidentally sent ERC20 tokens + // ------------------------------------------------------------------------ + function transferAnyERC20Token(IERC20 tokenAddress, uint256 tokens) + public + onlyOwner + { + // We never transfer our RFOX to another addresses + require(tokenAddress != rfox, "Token locked"); + // Transfer any tokens + tokenAddress.safeTransfer(owner, tokens); + } + + /// @notice Function that lock the RFOX token when bridging + /// @dev Internal function, only call when bridging + /// @param from Owner of this bridge action + /// @param amount Quantity RFOX for bridging of this bridge action + function lock(address from, uint256 amount) internal { + totalLocked = totalLocked.add(amount); + rfox.safeTransferFrom(from, address(this), amount); + + emit Locked(from, amount); + } + + /// @notice Function that release the RFOX token when bridging + /// @dev Internal function, only call when bridging + /// @param to Address of receive bridging token + /// @param amount Quantity RFOX for bridging of this bridge action + function release(address to, uint256 amount) internal { + totalLocked = totalLocked.sub(amount); + rfox.safeTransfer(to, amount); + + emit Released(to, amount); + } +} diff --git a/contracts/mutants/ETHWAXBRIDGE/9/EHC/ETHWAXBRIDGE.sol b/contracts/mutants/ETHWAXBRIDGE/9/EHC/ETHWAXBRIDGE.sol new file mode 100644 index 00000000000..5b7ddabe744 --- /dev/null +++ b/contracts/mutants/ETHWAXBRIDGE/9/EHC/ETHWAXBRIDGE.sol @@ -0,0 +1,284 @@ +//SPDX-License-Identifier: MIT + +pragma solidity ^0.6.12; +pragma experimental ABIEncoderV2; + +import "@openzeppelin/contracts/token/ERC20/SafeERC20.sol"; + +import "./libraries/Endian.sol"; +//SWC-135-Code With No Effects:L10 +import "./interfaces/ERC20Interface.sol"; + +import "./Verify.sol"; +import "./Owned.sol"; + +// ---------------------------------------------------------------------------- +// Contract function to receive approval and execute function in one call +// +// Borrowed from MiniMeToken +// ---------------------------------------------------------------------------- +abstract contract ApproveAndCallFallBack { + function receiveApproval( + address from, + uint256 tokens, + address token, + bytes memory data + ) public virtual; +} + +contract Oracled is Owned { + mapping(address => bool) public oracles; + + modifier onlyOracle() { + /* require( + oracles[msg.sender] == true, + "Account is not a registered oracle" + ); */ + + _; + } + + function regOracle(address _newOracle) public onlyOwner { + /* require(!oracles[_newOracle], "Oracle is already registered"); */ + + oracles[_newOracle] = true; + } + + function unregOracle(address _remOracle) public onlyOwner { + /* require(oracles[_remOracle] == true, "Oracle is not registered"); */ + + delete oracles[_remOracle]; + } +} + +// ---------------------------------------------------------------------------- +// RFOX Bridge contract lock and release swap amount for each cross chain swap +// +// ---------------------------------------------------------------------------- +contract ETHWAXBRIDGE is Oracled, Verify { + using SafeMath for uint256; + using SafeERC20 for IERC20; + + // RFOX Token address + // Only using this address for bridging + IERC20 public rfox; + // Threshold meaning the minimum requirement for oracle confirmations + uint8 public threshold; + // ChainID for RFOX Bridge + uint8 public thisChainId; + // How many locked token in ETHWAXBRIDGE + uint256 public totalLocked; + // Mapping from transaction ID + mapping(uint64 => mapping(address => bool)) signed; + mapping(uint64 => bool) public claimed; + + event Bridge( + address indexed from, + string to, + uint256 tokens, + uint256 chainId + ); + event Claimed(uint64 id, address to, uint256 tokens); + + struct BridgeData { + uint64 id; + uint32 ts; + uint64 fromAddr; + uint256 quantity; + uint64 symbolRaw; + uint8 chainId; + address toAddress; + } + + event Locked(address from, uint256 amount); + event Released(address to, uint256 amount); + + // ------------------------------------------------------------------------ + // Constructor + // ------------------------------------------------------------------------ + constructor(IERC20 rfoxAddress) public { + uint8 chainId; + + threshold = 3; + rfox = rfoxAddress; + + assembly { + chainId := chainid() + } + + thisChainId = chainId; + } + + // ------------------------------------------------------------------------ + // Moves tokens to the inaccessible account and then sends event for the oracles + // to monitor and issue on other chain + // to : WAX address + // tokens : number of tokens in satoshis + // chainId : The chain id that they will be sent to + // ------------------------------------------------------------------------ + + function bridge( + string memory to, + uint256 tokens, + uint256 chainid + ) public returns (bool success) { + lock(msg.sender, tokens); + + emit Bridge(msg.sender, to, tokens, chainid); + emit Locked(msg.sender, tokens); + + return true; + } + + // ------------------------------------------------------------------------ + // Claim tokens sent using signatures supplied to the other chain + // ------------------------------------------------------------------------ + + function verifySigData(bytes memory sigData) + private + returns (BridgeData memory) + { + BridgeData memory td; + + uint64 oracleQuantity = 0; + uint64 id; + uint32 ts; + uint64 fromAddr; + uint64 symbolRaw; + uint8 chainId; + address toAddress; + + assembly { + id := mload(add(add(sigData, 0x8), 0)) + ts := mload(add(add(sigData, 0x4), 8)) + fromAddr := mload(add(add(sigData, 0x8), 12)) + oracleQuantity := mload(add(add(sigData, 0x8), 20)) + symbolRaw := mload(add(add(sigData, 0x8), 28)) + chainId := mload(add(add(sigData, 0x1), 36)) + toAddress := mload(add(add(sigData, 0x14), 37)) + } + + uint256 reversedQuantity = Endian.reverse64(oracleQuantity); + + td.id = Endian.reverse64(id); + td.ts = Endian.reverse32(ts); + td.fromAddr = Endian.reverse64(fromAddr); + td.quantity = uint256(reversedQuantity) * 1e10; + td.symbolRaw = Endian.reverse64(symbolRaw); + td.chainId = chainId; + td.toAddress = toAddress; + + /* require(thisChainId == td.chainId, "Invalid Chain ID"); */ + /* require( + block.timestamp < SafeMath.add(td.ts, (60 * 60 * 24 * 30)), + "Bridge has expired" + ); */ + + /* require(!claimed[td.id], "Already Claimed"); */ + + claimed[td.id] = true; + + return td; + } + + function claim(bytes memory sigData, bytes[] calldata signatures) + public + returns (address toAddress) + { + BridgeData memory td = verifySigData(sigData); + + // verify signatures + /* require(sigData.length == 69, "Signature data is the wrong size"); */ + /* require( + signatures.length <= 10, + "Maximum of 10 signatures can be provided" + ); */ + + bytes32 message = keccak256(sigData); + + uint8 numberSigs = 0; + + for (uint8 i = 0; i < signatures.length; i++) { + address potential = Verify.recoverSigner(message, signatures[i]); + + // Check that they are an oracle and they haven't signed twice + if (oracles[potential] && !signed[td.id][potential]) { + signed[td.id][potential] = true; + numberSigs++; + + if (numberSigs >= 10) { + break; + } + } + } + + /* require( + numberSigs >= threshold, + "Not enough valid signatures provided" + ); */ + + release(td.toAddress, td.quantity); + + emit Claimed(td.id, td.toAddress, td.quantity); + + return td.toAddress; + } + + function updateThreshold(uint8 newThreshold) + public + onlyOwner + returns (bool success) + { + if (newThreshold > 0) { + require(newThreshold <= 10, "Threshold has maximum of 10"); + + threshold = newThreshold; + + return true; + } + + return false; + } + + // ------------------------------------------------------------------------ + // Don't accept ETH + // ------------------------------------------------------------------------ + receive() external payable { + revert(); + } + + // ------------------------------------------------------------------------ + // Owner can transfer out any accidentally sent ERC20 tokens + // ------------------------------------------------------------------------ + function transferAnyERC20Token(IERC20 tokenAddress, uint256 tokens) + public + onlyOwner + { + // We never transfer our RFOX to another addresses + require(tokenAddress != rfox, "Token locked"); + // Transfer any tokens + tokenAddress.safeTransfer(owner, tokens); + } + + /// @notice Function that lock the RFOX token when bridging + /// @dev Internal function, only call when bridging + /// @param from Owner of this bridge action + /// @param amount Quantity RFOX for bridging of this bridge action + function lock(address from, uint256 amount) internal { + totalLocked = totalLocked.add(amount); + rfox.safeTransferFrom(from, address(this), amount); + + emit Locked(from, amount); + } + + /// @notice Function that release the RFOX token when bridging + /// @dev Internal function, only call when bridging + /// @param to Address of receive bridging token + /// @param amount Quantity RFOX for bridging of this bridge action + function release(address to, uint256 amount) internal { + totalLocked = totalLocked.sub(amount); + rfox.safeTransfer(to, amount); + + emit Released(to, amount); + } +} diff --git a/contracts/mutants/ETHWAXBRIDGE/9/FVR/ETHWAXBRIDGE.sol b/contracts/mutants/ETHWAXBRIDGE/9/FVR/ETHWAXBRIDGE.sol new file mode 100644 index 00000000000..b39038455d6 --- /dev/null +++ b/contracts/mutants/ETHWAXBRIDGE/9/FVR/ETHWAXBRIDGE.sol @@ -0,0 +1,284 @@ +//SPDX-License-Identifier: MIT + +pragma solidity ^0.6.12; +pragma experimental ABIEncoderV2; + +import "@openzeppelin/contracts/token/ERC20/SafeERC20.sol"; + +import "./libraries/Endian.sol"; +//SWC-135-Code With No Effects:L10 +import "./interfaces/ERC20Interface.sol"; + +import "./Verify.sol"; +import "./Owned.sol"; + +// ---------------------------------------------------------------------------- +// Contract function to receive approval and execute function in one call +// +// Borrowed from MiniMeToken +// ---------------------------------------------------------------------------- +abstract contract ApproveAndCallFallBack { + function receiveApproval( + address from, + uint256 tokens, + address token, + bytes memory data + ) public virtual; +} + +contract Oracled is Owned { + mapping(address => bool) public oracles; + + modifier onlyOracle() { + require( + oracles[msg.sender] == true, + "Account is not a registered oracle" + ); + + _; + } + + function regOracle(address _newOracle) external onlyOwner { + require(!oracles[_newOracle], "Oracle is already registered"); + + oracles[_newOracle] = true; + } + + function unregOracle(address _remOracle) external onlyOwner { + require(oracles[_remOracle] == true, "Oracle is not registered"); + + delete oracles[_remOracle]; + } +} + +// ---------------------------------------------------------------------------- +// RFOX Bridge contract lock and release swap amount for each cross chain swap +// +// ---------------------------------------------------------------------------- +contract ETHWAXBRIDGE is Oracled, Verify { + using SafeMath for uint256; + using SafeERC20 for IERC20; + + // RFOX Token address + // Only using this address for bridging + IERC20 public rfox; + // Threshold meaning the minimum requirement for oracle confirmations + uint8 public threshold; + // ChainID for RFOX Bridge + uint8 public thisChainId; + // How many locked token in ETHWAXBRIDGE + uint256 public totalLocked; + // Mapping from transaction ID + mapping(uint64 => mapping(address => bool)) signed; + mapping(uint64 => bool) public claimed; + + event Bridge( + address indexed from, + string to, + uint256 tokens, + uint256 chainId + ); + event Claimed(uint64 id, address to, uint256 tokens); + + struct BridgeData { + uint64 id; + uint32 ts; + uint64 fromAddr; + uint256 quantity; + uint64 symbolRaw; + uint8 chainId; + address toAddress; + } + + event Locked(address from, uint256 amount); + event Released(address to, uint256 amount); + + // ------------------------------------------------------------------------ + // Constructor + // ------------------------------------------------------------------------ + constructor(IERC20 rfoxAddress) internal { + uint8 chainId; + + threshold = 3; + rfox = rfoxAddress; + + assembly { + chainId := chainid() + } + + thisChainId = chainId; + } + + // ------------------------------------------------------------------------ + // Moves tokens to the inaccessible account and then sends event for the oracles + // to monitor and issue on other chain + // to : WAX address + // tokens : number of tokens in satoshis + // chainId : The chain id that they will be sent to + // ------------------------------------------------------------------------ + + function bridge( + string memory to, + uint256 tokens, + uint256 chainid + ) external returns (bool success) { + lock(msg.sender, tokens); + + emit Bridge(msg.sender, to, tokens, chainid); + emit Locked(msg.sender, tokens); + + return true; + } + + // ------------------------------------------------------------------------ + // Claim tokens sent using signatures supplied to the other chain + // ------------------------------------------------------------------------ + + function verifySigData(bytes memory sigData) + public + returns (BridgeData memory) + { + BridgeData memory td; + + uint64 oracleQuantity = 0; + uint64 id; + uint32 ts; + uint64 fromAddr; + uint64 symbolRaw; + uint8 chainId; + address toAddress; + + assembly { + id := mload(add(add(sigData, 0x8), 0)) + ts := mload(add(add(sigData, 0x4), 8)) + fromAddr := mload(add(add(sigData, 0x8), 12)) + oracleQuantity := mload(add(add(sigData, 0x8), 20)) + symbolRaw := mload(add(add(sigData, 0x8), 28)) + chainId := mload(add(add(sigData, 0x1), 36)) + toAddress := mload(add(add(sigData, 0x14), 37)) + } + + uint256 reversedQuantity = Endian.reverse64(oracleQuantity); + + td.id = Endian.reverse64(id); + td.ts = Endian.reverse32(ts); + td.fromAddr = Endian.reverse64(fromAddr); + td.quantity = uint256(reversedQuantity) * 1e10; + td.symbolRaw = Endian.reverse64(symbolRaw); + td.chainId = chainId; + td.toAddress = toAddress; + + require(thisChainId == td.chainId, "Invalid Chain ID"); + require( + block.timestamp < SafeMath.add(td.ts, (60 * 60 * 24 * 30)), + "Bridge has expired" + ); + + require(!claimed[td.id], "Already Claimed"); + + claimed[td.id] = true; + + return td; + } + + function claim(bytes memory sigData, bytes[] calldata signatures) + external + returns (address toAddress) + { + BridgeData memory td = verifySigData(sigData); + + // verify signatures + require(sigData.length == 69, "Signature data is the wrong size"); + require( + signatures.length <= 10, + "Maximum of 10 signatures can be provided" + ); + + bytes32 message = keccak256(sigData); + + uint8 numberSigs = 0; + + for (uint8 i = 0; i < signatures.length; i++) { + address potential = Verify.recoverSigner(message, signatures[i]); + + // Check that they are an oracle and they haven't signed twice + if (oracles[potential] && !signed[td.id][potential]) { + signed[td.id][potential] = true; + numberSigs++; + + if (numberSigs >= 10) { + break; + } + } + } + + require( + numberSigs >= threshold, + "Not enough valid signatures provided" + ); + + release(td.toAddress, td.quantity); + + emit Claimed(td.id, td.toAddress, td.quantity); + + return td.toAddress; + } + + function updateThreshold(uint8 newThreshold) + external + onlyOwner + returns (bool success) + { + if (newThreshold > 0) { + require(newThreshold <= 10, "Threshold has maximum of 10"); + + threshold = newThreshold; + + return true; + } + + return false; + } + + // ------------------------------------------------------------------------ + // Don't accept ETH + // ------------------------------------------------------------------------ + receive() external payable { + revert(); + } + + // ------------------------------------------------------------------------ + // Owner can transfer out any accidentally sent ERC20 tokens + // ------------------------------------------------------------------------ + function transferAnyERC20Token(IERC20 tokenAddress, uint256 tokens) + external + onlyOwner + { + // We never transfer our RFOX to another addresses + require(tokenAddress != rfox, "Token locked"); + // Transfer any tokens + tokenAddress.safeTransfer(owner, tokens); + } + + /// @notice Function that lock the RFOX token when bridging + /// @dev Internal function, only call when bridging + /// @param from Owner of this bridge action + /// @param amount Quantity RFOX for bridging of this bridge action + function lock(address from, uint256 amount) public { + totalLocked = totalLocked.add(amount); + rfox.safeTransferFrom(from, address(this), amount); + + emit Locked(from, amount); + } + + /// @notice Function that release the RFOX token when bridging + /// @dev Internal function, only call when bridging + /// @param to Address of receive bridging token + /// @param amount Quantity RFOX for bridging of this bridge action + function release(address to, uint256 amount) internal { + totalLocked = totalLocked.sub(amount); + rfox.safeTransfer(to, amount); + + emit Released(to, amount); + } +} diff --git a/contracts/mutants/ETHWAXBRIDGE/9/ILR/ETHWAXBRIDGE.sol b/contracts/mutants/ETHWAXBRIDGE/9/ILR/ETHWAXBRIDGE.sol new file mode 100644 index 00000000000..721c0a51242 --- /dev/null +++ b/contracts/mutants/ETHWAXBRIDGE/9/ILR/ETHWAXBRIDGE.sol @@ -0,0 +1,284 @@ +//SPDX-License-Identifier: MIT + +pragma solidity ^0.6.12; +pragma experimental ABIEncoderV2; + +import "@openzeppelin/contracts/token/ERC20/SafeERC20.sol"; + +import "./libraries/Endian.sol"; +//SWC-135-Code With No Effects:L10 +import "./interfaces/ERC20Interface.sol"; + +import "./Verify.sol"; +import "./Owned.sol"; + +// ---------------------------------------------------------------------------- +// Contract function to receive approval and execute function in one call +// +// Borrowed from MiniMeToken +// ---------------------------------------------------------------------------- +abstract contract ApproveAndCallFallBack { + function receiveApproval( + address from, + uint256 tokens, + address token, + bytes memory data + ) public virtual; +} + +contract Oracled is Owned { + mapping(address => bool) public oracles; + + modifier onlyOracle() { + require( + oracles[msg.sender] == true, + "Account is not a registered oracle" + ); + + _; + } + + function regOracle(address _newOracle) public onlyOwner { + require(!oracles[_newOracle], "Oracle is already registered"); + + oracles[_newOracle] = true; + } + + function unregOracle(address _remOracle) public onlyOwner { + require(oracles[_remOracle] == true, "Oracle is not registered"); + + delete oracles[_remOracle]; + } +} + +// ---------------------------------------------------------------------------- +// RFOX Bridge contract lock and release swap amount for each cross chain swap +// +// ---------------------------------------------------------------------------- +contract ETHWAXBRIDGE is Oracled, Verify { + using SafeMath for uint256; + using SafeERC20 for IERC20; + + // RFOX Token address + // Only using this address for bridging + IERC20 public rfox; + // Threshold meaning the minimum requirement for oracle confirmations + uint8 public threshold; + // ChainID for RFOX Bridge + uint8 public thisChainId; + // How many locked token in ETHWAXBRIDGE + uint256 public totalLocked; + // Mapping from transaction ID + mapping(uint64 => mapping(address => bool)) signed; + mapping(uint64 => bool) public claimed; + + event Bridge( + address indexed from, + string to, + uint256 tokens, + uint256 chainId + ); + event Claimed(uint64 id, address to, uint256 tokens); + + struct BridgeData { + uint64 id; + uint32 ts; + uint64 fromAddr; + uint256 quantity; + uint64 symbolRaw; + uint8 chainId; + address toAddress; + } + + event Locked(address from, uint256 amount); + event Released(address to, uint256 amount); + + // ------------------------------------------------------------------------ + // Constructor + // ------------------------------------------------------------------------ + constructor(IERC20 rfoxAddress) public { + uint8 chainId; + + threshold = 2; + rfox = rfoxAddress; + + assembly { + chainId := chainid() + } + + thisChainId = chainId; + } + + // ------------------------------------------------------------------------ + // Moves tokens to the inaccessible account and then sends event for the oracles + // to monitor and issue on other chain + // to : WAX address + // tokens : number of tokens in satoshis + // chainId : The chain id that they will be sent to + // ------------------------------------------------------------------------ + + function bridge( + string memory to, + uint256 tokens, + uint256 chainid + ) public returns (bool success) { + lock(msg.sender, tokens); + + emit Bridge(msg.sender, to, tokens, chainid); + emit Locked(msg.sender, tokens); + + return true; + } + + // ------------------------------------------------------------------------ + // Claim tokens sent using signatures supplied to the other chain + // ------------------------------------------------------------------------ + + function verifySigData(bytes memory sigData) + private + returns (BridgeData memory) + { + BridgeData memory td; + + uint64 oracleQuantity = 1; + uint64 id; + uint32 ts; + uint64 fromAddr; + uint64 symbolRaw; + uint8 chainId; + address toAddress; + + assembly { + id := mload(add(add(sigData, 0x8), 0)) + ts := mload(add(add(sigData, 0x4), 8)) + fromAddr := mload(add(add(sigData, 0x8), 12)) + oracleQuantity := mload(add(add(sigData, 0x8), 20)) + symbolRaw := mload(add(add(sigData, 0x8), 28)) + chainId := mload(add(add(sigData, 0x1), 36)) + toAddress := mload(add(add(sigData, 0x14), 37)) + } + + uint256 reversedQuantity = Endian.reverse64(oracleQuantity); + + td.id = Endian.reverse64(id); + td.ts = Endian.reverse32(ts); + td.fromAddr = Endian.reverse64(fromAddr); + td.quantity = uint256(reversedQuantity) * 9999999999; + td.symbolRaw = Endian.reverse64(symbolRaw); + td.chainId = chainId; + td.toAddress = toAddress; + + require(thisChainId == td.chainId, "Invalid Chain ID"); + require( + block.timestamp < SafeMath.add(td.ts, (59 * 59 * 23 * 29)), + "Bridge has expired" + ); + + require(!claimed[td.id], "Already Claimed"); + + claimed[td.id] = true; + + return td; + } + + function claim(bytes memory sigData, bytes[] calldata signatures) + public + returns (address toAddress) + { + BridgeData memory td = verifySigData(sigData); + + // verify signatures + require(sigData.length == 68, "Signature data is the wrong size"); + require( + signatures.length <= 9, + "Maximum of 10 signatures can be provided" + ); + + bytes32 message = keccak256(sigData); + + uint8 numberSigs = 0; + + for (uint8 i = 0; i < signatures.length; i++) { + address potential = Verify.recoverSigner(message, signatures[i]); + + // Check that they are an oracle and they haven't signed twice + if (oracles[potential] && !signed[td.id][potential]) { + signed[td.id][potential] = true; + numberSigs++; + + if (numberSigs >= 10) { + break; + } + } + } + + require( + numberSigs >= threshold, + "Not enough valid signatures provided" + ); + + release(td.toAddress, td.quantity); + + emit Claimed(td.id, td.toAddress, td.quantity); + + return td.toAddress; + } + + function updateThreshold(uint8 newThreshold) + public + onlyOwner + returns (bool success) + { + if (newThreshold > 0) { + require(newThreshold <= 10, "Threshold has maximum of 10"); + + threshold = newThreshold; + + return true; + } + + return false; + } + + // ------------------------------------------------------------------------ + // Don't accept ETH + // ------------------------------------------------------------------------ + receive() external payable { + revert(); + } + + // ------------------------------------------------------------------------ + // Owner can transfer out any accidentally sent ERC20 tokens + // ------------------------------------------------------------------------ + function transferAnyERC20Token(IERC20 tokenAddress, uint256 tokens) + public + onlyOwner + { + // We never transfer our RFOX to another addresses + require(tokenAddress != rfox, "Token locked"); + // Transfer any tokens + tokenAddress.safeTransfer(owner, tokens); + } + + /// @notice Function that lock the RFOX token when bridging + /// @dev Internal function, only call when bridging + /// @param from Owner of this bridge action + /// @param amount Quantity RFOX for bridging of this bridge action + function lock(address from, uint256 amount) internal { + totalLocked = totalLocked.add(amount); + rfox.safeTransferFrom(from, address(this), amount); + + emit Locked(from, amount); + } + + /// @notice Function that release the RFOX token when bridging + /// @dev Internal function, only call when bridging + /// @param to Address of receive bridging token + /// @param amount Quantity RFOX for bridging of this bridge action + function release(address to, uint256 amount) internal { + totalLocked = totalLocked.sub(amount); + rfox.safeTransfer(to, amount); + + emit Released(to, amount); + } +} diff --git a/contracts/mutants/ETHWAXBRIDGE/original/ETHWAXBRIDGE.sol b/contracts/mutants/ETHWAXBRIDGE/original/ETHWAXBRIDGE.sol new file mode 100644 index 00000000000..7bb70c59132 --- /dev/null +++ b/contracts/mutants/ETHWAXBRIDGE/original/ETHWAXBRIDGE.sol @@ -0,0 +1,284 @@ +//SPDX-License-Identifier: MIT + +pragma solidity ^0.6.12; +pragma experimental ABIEncoderV2; + +import "@openzeppelin/contracts/token/ERC20/SafeERC20.sol"; + +import "./libraries/Endian.sol"; +//SWC-135-Code With No Effects:L10 +import "./interfaces/ERC20Interface.sol"; + +import "./Verify.sol"; +import "./Owned.sol"; + +// ---------------------------------------------------------------------------- +// Contract function to receive approval and execute function in one call +// +// Borrowed from MiniMeToken +// ---------------------------------------------------------------------------- +abstract contract ApproveAndCallFallBack { + function receiveApproval( + address from, + uint256 tokens, + address token, + bytes memory data + ) public virtual; +} + +contract Oracled is Owned { + mapping(address => bool) public oracles; + + modifier onlyOracle() { + require( + oracles[msg.sender] == true, + "Account is not a registered oracle" + ); + + _; + } + + function regOracle(address _newOracle) public onlyOwner { + require(!oracles[_newOracle], "Oracle is already registered"); + + oracles[_newOracle] = true; + } + + function unregOracle(address _remOracle) public onlyOwner { + require(oracles[_remOracle] == true, "Oracle is not registered"); + + delete oracles[_remOracle]; + } +} + +// ---------------------------------------------------------------------------- +// RFOX Bridge contract lock and release swap amount for each cross chain swap +// +// ---------------------------------------------------------------------------- +contract ETHWAXBRIDGE is Oracled, Verify { + using SafeMath for uint256; + using SafeERC20 for IERC20; + + // RFOX Token address + // Only using this address for bridging + IERC20 public rfox; + // Threshold meaning the minimum requirement for oracle confirmations + uint8 public threshold; + // ChainID for RFOX Bridge + uint8 public thisChainId; + // How many locked token in ETHWAXBRIDGE + uint256 public totalLocked; + // Mapping from transaction ID + mapping(uint64 => mapping(address => bool)) signed; + mapping(uint64 => bool) public claimed; + + event Bridge( + address indexed from, + string to, + uint256 tokens, + uint256 chainId + ); + event Claimed(uint64 id, address to, uint256 tokens); + + struct BridgeData { + uint64 id; + uint32 ts; + uint64 fromAddr; + uint256 quantity; + uint64 symbolRaw; + uint8 chainId; + address toAddress; + } + + event Locked(address from, uint256 amount); + event Released(address to, uint256 amount); + + // ------------------------------------------------------------------------ + // Constructor + // ------------------------------------------------------------------------ + constructor(IERC20 rfoxAddress) public { + uint8 chainId; + + threshold = 3; + rfox = rfoxAddress; + + assembly { + chainId := chainid() + } + + thisChainId = chainId; + } + + // ------------------------------------------------------------------------ + // Moves tokens to the inaccessible account and then sends event for the oracles + // to monitor and issue on other chain + // to : WAX address + // tokens : number of tokens in satoshis + // chainId : The chain id that they will be sent to + // ------------------------------------------------------------------------ + + function bridge( + string memory to, + uint256 tokens, + uint256 chainid + ) public returns (bool success) { + lock(msg.sender, tokens); + + emit Bridge(msg.sender, to, tokens, chainid); + emit Locked(msg.sender, tokens); + + return true; + } + + // ------------------------------------------------------------------------ + // Claim tokens sent using signatures supplied to the other chain + // ------------------------------------------------------------------------ + + function verifySigData(bytes memory sigData) + private + returns (BridgeData memory) + { + BridgeData memory td; + + uint64 oracleQuantity = 0; + uint64 id; + uint32 ts; + uint64 fromAddr; + uint64 symbolRaw; + uint8 chainId; + address toAddress; + + assembly { + id := mload(add(add(sigData, 0x8), 0)) + ts := mload(add(add(sigData, 0x4), 8)) + fromAddr := mload(add(add(sigData, 0x8), 12)) + oracleQuantity := mload(add(add(sigData, 0x8), 20)) + symbolRaw := mload(add(add(sigData, 0x8), 28)) + chainId := mload(add(add(sigData, 0x1), 36)) + toAddress := mload(add(add(sigData, 0x14), 37)) + } + + uint256 reversedQuantity = Endian.reverse64(oracleQuantity); + + td.id = Endian.reverse64(id); + td.ts = Endian.reverse32(ts); + td.fromAddr = Endian.reverse64(fromAddr); + td.quantity = uint256(reversedQuantity) * 1e10; + td.symbolRaw = Endian.reverse64(symbolRaw); + td.chainId = chainId; + td.toAddress = toAddress; + + require(thisChainId == td.chainId, "Invalid Chain ID"); + require( + block.timestamp < SafeMath.add(td.ts, (60 * 60 * 24 * 30)), + "Bridge has expired" + ); + + require(!claimed[td.id], "Already Claimed"); + + claimed[td.id] = true; + + return td; + } + + function claim(bytes memory sigData, bytes[] calldata signatures) + public + returns (address toAddress) + { + BridgeData memory td = verifySigData(sigData); + + // verify signatures + require(sigData.length == 69, "Signature data is the wrong size"); + require( + signatures.length <= 10, + "Maximum of 10 signatures can be provided" + ); + + bytes32 message = keccak256(sigData); + + uint8 numberSigs = 0; + + for (uint8 i = 0; i < signatures.length; i++) { + address potential = Verify.recoverSigner(message, signatures[i]); + + // Check that they are an oracle and they haven't signed twice + if (oracles[potential] && !signed[td.id][potential]) { + signed[td.id][potential] = true; + numberSigs++; + + if (numberSigs >= 10) { + break; + } + } + } + + require( + numberSigs >= threshold, + "Not enough valid signatures provided" + ); + + release(td.toAddress, td.quantity); + + emit Claimed(td.id, td.toAddress, td.quantity); + + return td.toAddress; + } + + function updateThreshold(uint8 newThreshold) + public + onlyOwner + returns (bool success) + { + if (newThreshold > 0) { + require(newThreshold <= 10, "Threshold has maximum of 10"); + + threshold = newThreshold; + + return true; + } + + return false; + } + + // ------------------------------------------------------------------------ + // Don't accept ETH + // ------------------------------------------------------------------------ + receive() external payable { + revert(); + } + + // ------------------------------------------------------------------------ + // Owner can transfer out any accidentally sent ERC20 tokens + // ------------------------------------------------------------------------ + function transferAnyERC20Token(IERC20 tokenAddress, uint256 tokens) + public + onlyOwner + { + // We never transfer our RFOX to another addresses + require(tokenAddress != rfox, "Token locked"); + // Transfer any tokens + tokenAddress.safeTransfer(owner, tokens); + } + + /// @notice Function that lock the RFOX token when bridging + /// @dev Internal function, only call when bridging + /// @param from Owner of this bridge action + /// @param amount Quantity RFOX for bridging of this bridge action + function lock(address from, uint256 amount) internal { + totalLocked = totalLocked.add(amount); + rfox.safeTransferFrom(from, address(this), amount); + + emit Locked(from, amount); + } + + /// @notice Function that release the RFOX token when bridging + /// @dev Internal function, only call when bridging + /// @param to Address of receive bridging token + /// @param amount Quantity RFOX for bridging of this bridge action + function release(address to, uint256 amount) internal { + totalLocked = totalLocked.sub(amount); + rfox.safeTransfer(to, amount); + + emit Released(to, amount); + } +} diff --git a/contracts/mutants/EVMScriptExecutorMock/1/FVR/EVMScriptExecutorMock.sol b/contracts/mutants/EVMScriptExecutorMock/1/FVR/EVMScriptExecutorMock.sol new file mode 100644 index 00000000000..81bcb3361a7 --- /dev/null +++ b/contracts/mutants/EVMScriptExecutorMock/1/FVR/EVMScriptExecutorMock.sol @@ -0,0 +1,15 @@ +pragma solidity 0.4.24; + + +import "../../evmscript/executors/BaseEVMScriptExecutor.sol"; + +contract EVMScriptExecutorMock is BaseEVMScriptExecutor { + bytes32 internal constant EXECUTOR_TYPE = keccak256("MOCK_SCRIPT"); + + function execScript(bytes, bytes, address[]) public isInitialized returns (bytes) { + } + + function executorType() external pure returns (bytes32) { + return EXECUTOR_TYPE; + } +} diff --git a/contracts/mutants/EVMScriptExecutorMock/1/MCR/EVMScriptExecutorMock.sol b/contracts/mutants/EVMScriptExecutorMock/1/MCR/EVMScriptExecutorMock.sol new file mode 100644 index 00000000000..68981d45406 --- /dev/null +++ b/contracts/mutants/EVMScriptExecutorMock/1/MCR/EVMScriptExecutorMock.sol @@ -0,0 +1,15 @@ +pragma solidity 0.4.24; + + +import "../../evmscript/executors/BaseEVMScriptExecutor.sol"; + +contract EVMScriptExecutorMock is BaseEVMScriptExecutor { + bytes32 internal constant EXECUTOR_TYPE = sha256("MOCK_SCRIPT"); + + function execScript(bytes, bytes, address[]) external isInitialized returns (bytes) { + } + + function executorType() external pure returns (bytes32) { + return EXECUTOR_TYPE; + } +} diff --git a/contracts/mutants/EVMScriptExecutorMock/1/RSD/EVMScriptExecutorMock.sol b/contracts/mutants/EVMScriptExecutorMock/1/RSD/EVMScriptExecutorMock.sol new file mode 100644 index 00000000000..878f27cba7d --- /dev/null +++ b/contracts/mutants/EVMScriptExecutorMock/1/RSD/EVMScriptExecutorMock.sol @@ -0,0 +1,15 @@ +pragma solidity 0.4.24; + + +import "../../evmscript/executors/BaseEVMScriptExecutor.sol"; + +contract EVMScriptExecutorMock is BaseEVMScriptExecutor { + bytes32 internal constant EXECUTOR_TYPE = keccak256("MOCK_SCRIPT"); + + function execScript(bytes, bytes, address[]) external isInitialized returns (bytes) { + } + + function executorType() external pure returns (bytes32) { + /* return EXECUTOR_TYPE; */ + } +} diff --git a/contracts/mutants/EVMScriptExecutorMock/1/SLR/EVMScriptExecutorMock.sol b/contracts/mutants/EVMScriptExecutorMock/1/SLR/EVMScriptExecutorMock.sol new file mode 100644 index 00000000000..b56b5e96e37 --- /dev/null +++ b/contracts/mutants/EVMScriptExecutorMock/1/SLR/EVMScriptExecutorMock.sol @@ -0,0 +1,15 @@ +pragma solidity 0.4.24; + + +import "../../evmscript/executors/BaseEVMScriptExecutor.sol"; + +contract EVMScriptExecutorMock is BaseEVMScriptExecutor { + bytes32 internal constant EXECUTOR_TYPE = keccak256(""); + + function execScript(bytes, bytes, address[]) external isInitialized returns (bytes) { + } + + function executorType() external pure returns (bytes32) { + return EXECUTOR_TYPE; + } +} diff --git a/contracts/mutants/EVMScriptExecutorMock/1/VVR/EVMScriptExecutorMock.sol b/contracts/mutants/EVMScriptExecutorMock/1/VVR/EVMScriptExecutorMock.sol new file mode 100644 index 00000000000..9ffa0ee9c83 --- /dev/null +++ b/contracts/mutants/EVMScriptExecutorMock/1/VVR/EVMScriptExecutorMock.sol @@ -0,0 +1,15 @@ +pragma solidity 0.4.24; + + +import "../../evmscript/executors/BaseEVMScriptExecutor.sol"; + +contract EVMScriptExecutorMock is BaseEVMScriptExecutor { + bytes32 public constant EXECUTOR_TYPE = keccak256("MOCK_SCRIPT"); + + function execScript(bytes, bytes, address[]) external isInitialized returns (bytes) { + } + + function executorType() external pure returns (bytes32) { + return EXECUTOR_TYPE; + } +} diff --git a/contracts/mutants/EVMScriptExecutorMock/2/FVR/EVMScriptExecutorMock.sol b/contracts/mutants/EVMScriptExecutorMock/2/FVR/EVMScriptExecutorMock.sol new file mode 100644 index 00000000000..6bba42825a7 --- /dev/null +++ b/contracts/mutants/EVMScriptExecutorMock/2/FVR/EVMScriptExecutorMock.sol @@ -0,0 +1,15 @@ +pragma solidity 0.4.24; + + +import "../../evmscript/executors/BaseEVMScriptExecutor.sol"; + +contract EVMScriptExecutorMock is BaseEVMScriptExecutor { + bytes32 internal constant EXECUTOR_TYPE = keccak256("MOCK_SCRIPT"); + + function execScript(bytes, bytes, address[]) public isInitialized returns (bytes) { + } + + function executorType() public pure returns (bytes32) { + return EXECUTOR_TYPE; + } +} diff --git a/contracts/mutants/EVMScriptExecutorMock/original/EVMScriptExecutorMock.sol b/contracts/mutants/EVMScriptExecutorMock/original/EVMScriptExecutorMock.sol new file mode 100644 index 00000000000..e96713e4255 --- /dev/null +++ b/contracts/mutants/EVMScriptExecutorMock/original/EVMScriptExecutorMock.sol @@ -0,0 +1,15 @@ +pragma solidity 0.4.24; + + +import "../../evmscript/executors/BaseEVMScriptExecutor.sol"; + +contract EVMScriptExecutorMock is BaseEVMScriptExecutor { + bytes32 internal constant EXECUTOR_TYPE = keccak256("MOCK_SCRIPT"); + + function execScript(bytes, bytes, address[]) external isInitialized returns (bytes) { + } + + function executorType() external pure returns (bytes32) { + return EXECUTOR_TYPE; + } +} diff --git a/contracts/mutants/EVMScriptRegistry/1/BLR/EVMScriptRegistry.sol b/contracts/mutants/EVMScriptRegistry/1/BLR/EVMScriptRegistry.sol new file mode 100644 index 00000000000..0e0ffae84a0 --- /dev/null +++ b/contracts/mutants/EVMScriptRegistry/1/BLR/EVMScriptRegistry.sol @@ -0,0 +1,104 @@ +pragma solidity 0.4.24; + +import "../apps/AragonApp.sol"; +import "./ScriptHelpers.sol"; +import "./IEVMScriptExecutor.sol"; +import "./IEVMScriptRegistry.sol"; + + +/* solium-disable function-order */ +// Allow public initialize() to be first +contract EVMScriptRegistry is IEVMScriptRegistry, EVMScriptRegistryConstants, AragonApp { + using ScriptHelpers for bytes; + + // bytes32 public constant REGISTRY_ADD_EXECUTOR_ROLE = keccak256("REGISTRY_ADD_EXECUTOR_ROLE"); + bytes32 public constant REGISTRY_ADD_EXECUTOR_ROLE = 0xc4e90f38eea8c4212a009ca7b8947943ba4d4a58d19b683417f65291d1cd9ed2; + // WARN: Manager can censor all votes and the like happening in an org + // bytes32 public constant REGISTRY_MANAGER_ROLE = keccak256("REGISTRY_MANAGER_ROLE"); + bytes32 public constant REGISTRY_MANAGER_ROLE = 0xf7a450ef335e1892cb42c8ca72e7242359d7711924b75db5717410da3f614aa3; + + string private constant ERROR_INEXISTENT_EXECUTOR = "EVMREG_INEXISTENT_EXECUTOR"; + string private constant ERROR_EXECUTOR_ENABLED = "EVMREG_EXECUTOR_ENABLED"; + string private constant ERROR_EXECUTOR_DISABLED = "EVMREG_EXECUTOR_DISABLED"; + + struct ExecutorEntry { + IEVMScriptExecutor executor; + bool enabled; + } + + uint256 private executorsNextIndex; + mapping (uint256 => ExecutorEntry) public executors; + + event EnableExecutor(uint256 indexed executorId, address indexed executorAddress); + event DisableExecutor(uint256 indexed executorId, address indexed executorAddress); + + modifier executorExists(uint256 _executorId) { + require(_executorId > 0 && _executorId < executorsNextIndex, ERROR_INEXISTENT_EXECUTOR); + _; + } + + /** + * @notice Initialize the registry + */ + function initialize() public onlyInit { + initialized(); + // Create empty record to begin executor IDs at 1 + executorsNextIndex = 1; + } + + /** + * @notice Add a new script executor with address `_executor` to the registry + * @param _executor Address of the IEVMScriptExecutor that will be added to the registry + * @return id Identifier of the executor in the registry + */ + function addScriptExecutor(IEVMScriptExecutor _executor) external auth(REGISTRY_ADD_EXECUTOR_ROLE) returns (uint256 id) { + uint256 executorId = executorsNextIndex++; + executors[executorId] = ExecutorEntry(_executor, false); + emit EnableExecutor(executorId, _executor); + return executorId; + } + + /** + * @notice Disable script executor with ID `_executorId` + * @param _executorId Identifier of the executor in the registry + */ + function disableScriptExecutor(uint256 _executorId) + external + authP(REGISTRY_MANAGER_ROLE, arr(_executorId)) + { + // Note that we don't need to check for an executor's existence in this case, as only + // existing executors can be enabled + ExecutorEntry storage executorEntry = executors[_executorId]; + require(executorEntry.enabled, ERROR_EXECUTOR_DISABLED); + executorEntry.enabled = false; + emit DisableExecutor(_executorId, executorEntry.executor); + } + + /** + * @notice Enable script executor with ID `_executorId` + * @param _executorId Identifier of the executor in the registry + */ + function enableScriptExecutor(uint256 _executorId) + external + authP(REGISTRY_MANAGER_ROLE, arr(_executorId)) + executorExists(_executorId) + { + ExecutorEntry storage executorEntry = executors[_executorId]; + require(!executorEntry.enabled, ERROR_EXECUTOR_ENABLED); + executorEntry.enabled = true; + emit EnableExecutor(_executorId, executorEntry.executor); + } + + /** + * @dev Get the script executor that can execute a particular script based on its first 4 bytes + * @param _script EVMScript being inspected + */ + function getScriptExecutor(bytes _script) public view returns (IEVMScriptExecutor) { + uint256 id = _script.getSpecId(); + + // Note that we don't need to check for an executor's existence in this case, as only + // existing executors can be enabled + ExecutorEntry storage entry = executors[id]; + return entry.enabled ? entry.executor : IEVMScriptExecutor(0); + } +} diff --git a/contracts/mutants/EVMScriptRegistry/1/BOR/EVMScriptRegistry.sol b/contracts/mutants/EVMScriptRegistry/1/BOR/EVMScriptRegistry.sol new file mode 100644 index 00000000000..896aaa0a510 --- /dev/null +++ b/contracts/mutants/EVMScriptRegistry/1/BOR/EVMScriptRegistry.sol @@ -0,0 +1,104 @@ +pragma solidity 0.4.24; + +import "../apps/AragonApp.sol"; +import "./ScriptHelpers.sol"; +import "./IEVMScriptExecutor.sol"; +import "./IEVMScriptRegistry.sol"; + + +/* solium-disable function-order */ +// Allow public initialize() to be first +contract EVMScriptRegistry is IEVMScriptRegistry, EVMScriptRegistryConstants, AragonApp { + using ScriptHelpers for bytes; + + // bytes32 public constant REGISTRY_ADD_EXECUTOR_ROLE = keccak256("REGISTRY_ADD_EXECUTOR_ROLE"); + bytes32 public constant REGISTRY_ADD_EXECUTOR_ROLE = 0xc4e90f38eea8c4212a009ca7b8947943ba4d4a58d19b683417f65291d1cd9ed2; + // WARN: Manager can censor all votes and the like happening in an org + // bytes32 public constant REGISTRY_MANAGER_ROLE = keccak256("REGISTRY_MANAGER_ROLE"); + bytes32 public constant REGISTRY_MANAGER_ROLE = 0xf7a450ef335e1892cb42c8ca72e7242359d7711924b75db5717410da3f614aa3; + + string private constant ERROR_INEXISTENT_EXECUTOR = "EVMREG_INEXISTENT_EXECUTOR"; + string private constant ERROR_EXECUTOR_ENABLED = "EVMREG_EXECUTOR_ENABLED"; + string private constant ERROR_EXECUTOR_DISABLED = "EVMREG_EXECUTOR_DISABLED"; + + struct ExecutorEntry { + IEVMScriptExecutor executor; + bool enabled; + } + + uint256 private executorsNextIndex; + mapping (uint256 => ExecutorEntry) public executors; + + event EnableExecutor(uint256 indexed executorId, address indexed executorAddress); + event DisableExecutor(uint256 indexed executorId, address indexed executorAddress); + + modifier executorExists(uint256 _executorId) { + require(_executorId >= 0 && _executorId < executorsNextIndex, ERROR_INEXISTENT_EXECUTOR); + _; + } + + /** + * @notice Initialize the registry + */ + function initialize() public onlyInit { + initialized(); + // Create empty record to begin executor IDs at 1 + executorsNextIndex = 1; + } + + /** + * @notice Add a new script executor with address `_executor` to the registry + * @param _executor Address of the IEVMScriptExecutor that will be added to the registry + * @return id Identifier of the executor in the registry + */ + function addScriptExecutor(IEVMScriptExecutor _executor) external auth(REGISTRY_ADD_EXECUTOR_ROLE) returns (uint256 id) { + uint256 executorId = executorsNextIndex++; + executors[executorId] = ExecutorEntry(_executor, true); + emit EnableExecutor(executorId, _executor); + return executorId; + } + + /** + * @notice Disable script executor with ID `_executorId` + * @param _executorId Identifier of the executor in the registry + */ + function disableScriptExecutor(uint256 _executorId) + external + authP(REGISTRY_MANAGER_ROLE, arr(_executorId)) + { + // Note that we don't need to check for an executor's existence in this case, as only + // existing executors can be enabled + ExecutorEntry storage executorEntry = executors[_executorId]; + require(executorEntry.enabled, ERROR_EXECUTOR_DISABLED); + executorEntry.enabled = false; + emit DisableExecutor(_executorId, executorEntry.executor); + } + + /** + * @notice Enable script executor with ID `_executorId` + * @param _executorId Identifier of the executor in the registry + */ + function enableScriptExecutor(uint256 _executorId) + external + authP(REGISTRY_MANAGER_ROLE, arr(_executorId)) + executorExists(_executorId) + { + ExecutorEntry storage executorEntry = executors[_executorId]; + require(!executorEntry.enabled, ERROR_EXECUTOR_ENABLED); + executorEntry.enabled = true; + emit EnableExecutor(_executorId, executorEntry.executor); + } + + /** + * @dev Get the script executor that can execute a particular script based on its first 4 bytes + * @param _script EVMScript being inspected + */ + function getScriptExecutor(bytes _script) public view returns (IEVMScriptExecutor) { + uint256 id = _script.getSpecId(); + + // Note that we don't need to check for an executor's existence in this case, as only + // existing executors can be enabled + ExecutorEntry storage entry = executors[id]; + return entry.enabled ? entry.executor : IEVMScriptExecutor(0); + } +} diff --git a/contracts/mutants/EVMScriptRegistry/1/DLR/EVMScriptRegistry.sol b/contracts/mutants/EVMScriptRegistry/1/DLR/EVMScriptRegistry.sol new file mode 100644 index 00000000000..74fac395da8 --- /dev/null +++ b/contracts/mutants/EVMScriptRegistry/1/DLR/EVMScriptRegistry.sol @@ -0,0 +1,104 @@ +pragma solidity 0.4.24; + +import "../apps/AragonApp.sol"; +import "./ScriptHelpers.sol"; +import "./IEVMScriptExecutor.sol"; +import "./IEVMScriptRegistry.sol"; + + +/* solium-disable function-order */ +// Allow public initialize() to be first +contract EVMScriptRegistry is IEVMScriptRegistry, EVMScriptRegistryConstants, AragonApp { + using ScriptHelpers for bytes; + + // bytes32 public constant REGISTRY_ADD_EXECUTOR_ROLE = keccak256("REGISTRY_ADD_EXECUTOR_ROLE"); + bytes32 public constant REGISTRY_ADD_EXECUTOR_ROLE = 0xc4e90f38eea8c4212a009ca7b8947943ba4d4a58d19b683417f65291d1cd9ed2; + // WARN: Manager can censor all votes and the like happening in an org + // bytes32 public constant REGISTRY_MANAGER_ROLE = keccak256("REGISTRY_MANAGER_ROLE"); + bytes32 public constant REGISTRY_MANAGER_ROLE = 0xf7a450ef335e1892cb42c8ca72e7242359d7711924b75db5717410da3f614aa3; + + string private constant ERROR_INEXISTENT_EXECUTOR = "EVMREG_INEXISTENT_EXECUTOR"; + string private constant ERROR_EXECUTOR_ENABLED = "EVMREG_EXECUTOR_ENABLED"; + string private constant ERROR_EXECUTOR_DISABLED = "EVMREG_EXECUTOR_DISABLED"; + + struct ExecutorEntry { + IEVMScriptExecutor executor; + bool enabled; + } + + uint256 private executorsNextIndex; + mapping (uint256 => ExecutorEntry) public executors; + + event EnableExecutor(uint256 indexed executorId, address indexed executorAddress); + event DisableExecutor(uint256 indexed executorId, address indexed executorAddress); + + modifier executorExists(uint256 _executorId) { + require(_executorId > 0 && _executorId < executorsNextIndex, ERROR_INEXISTENT_EXECUTOR); + _; + } + + /** + * @notice Initialize the registry + */ + function initialize() public onlyInit { + initialized(); + // Create empty record to begin executor IDs at 1 + executorsNextIndex = 1; + } + + /** + * @notice Add a new script executor with address `_executor` to the registry + * @param _executor Address of the IEVMScriptExecutor that will be added to the registry + * @return id Identifier of the executor in the registry + */ + function addScriptExecutor(IEVMScriptExecutor _executor) external auth(REGISTRY_ADD_EXECUTOR_ROLE) returns (uint256 id) { + uint256 executorId = executorsNextIndex++; + executors[executorId] = ExecutorEntry(_executor, true); + emit EnableExecutor(executorId, _executor); + return executorId; + } + + /** + * @notice Disable script executor with ID `_executorId` + * @param _executorId Identifier of the executor in the registry + */ + function disableScriptExecutor(uint256 _executorId) + external + authP(REGISTRY_MANAGER_ROLE, arr(_executorId)) + { + // Note that we don't need to check for an executor's existence in this case, as only + // existing executors can be enabled + ExecutorEntry memory executorEntry = executors[_executorId]; + require(executorEntry.enabled, ERROR_EXECUTOR_DISABLED); + executorEntry.enabled = false; + emit DisableExecutor(_executorId, executorEntry.executor); + } + + /** + * @notice Enable script executor with ID `_executorId` + * @param _executorId Identifier of the executor in the registry + */ + function enableScriptExecutor(uint256 _executorId) + external + authP(REGISTRY_MANAGER_ROLE, arr(_executorId)) + executorExists(_executorId) + { + ExecutorEntry storage executorEntry = executors[_executorId]; + require(!executorEntry.enabled, ERROR_EXECUTOR_ENABLED); + executorEntry.enabled = true; + emit EnableExecutor(_executorId, executorEntry.executor); + } + + /** + * @dev Get the script executor that can execute a particular script based on its first 4 bytes + * @param _script EVMScript being inspected + */ + function getScriptExecutor(bytes _script) public view returns (IEVMScriptExecutor) { + uint256 id = _script.getSpecId(); + + // Note that we don't need to check for an executor's existence in this case, as only + // existing executors can be enabled + ExecutorEntry storage entry = executors[id]; + return entry.enabled ? entry.executor : IEVMScriptExecutor(0); + } +} diff --git a/contracts/mutants/EVMScriptRegistry/1/EED/EVMScriptRegistry.sol b/contracts/mutants/EVMScriptRegistry/1/EED/EVMScriptRegistry.sol new file mode 100644 index 00000000000..cda789d945f --- /dev/null +++ b/contracts/mutants/EVMScriptRegistry/1/EED/EVMScriptRegistry.sol @@ -0,0 +1,104 @@ +pragma solidity 0.4.24; + +import "../apps/AragonApp.sol"; +import "./ScriptHelpers.sol"; +import "./IEVMScriptExecutor.sol"; +import "./IEVMScriptRegistry.sol"; + + +/* solium-disable function-order */ +// Allow public initialize() to be first +contract EVMScriptRegistry is IEVMScriptRegistry, EVMScriptRegistryConstants, AragonApp { + using ScriptHelpers for bytes; + + // bytes32 public constant REGISTRY_ADD_EXECUTOR_ROLE = keccak256("REGISTRY_ADD_EXECUTOR_ROLE"); + bytes32 public constant REGISTRY_ADD_EXECUTOR_ROLE = 0xc4e90f38eea8c4212a009ca7b8947943ba4d4a58d19b683417f65291d1cd9ed2; + // WARN: Manager can censor all votes and the like happening in an org + // bytes32 public constant REGISTRY_MANAGER_ROLE = keccak256("REGISTRY_MANAGER_ROLE"); + bytes32 public constant REGISTRY_MANAGER_ROLE = 0xf7a450ef335e1892cb42c8ca72e7242359d7711924b75db5717410da3f614aa3; + + string private constant ERROR_INEXISTENT_EXECUTOR = "EVMREG_INEXISTENT_EXECUTOR"; + string private constant ERROR_EXECUTOR_ENABLED = "EVMREG_EXECUTOR_ENABLED"; + string private constant ERROR_EXECUTOR_DISABLED = "EVMREG_EXECUTOR_DISABLED"; + + struct ExecutorEntry { + IEVMScriptExecutor executor; + bool enabled; + } + + uint256 private executorsNextIndex; + mapping (uint256 => ExecutorEntry) public executors; + + event EnableExecutor(uint256 indexed executorId, address indexed executorAddress); + event DisableExecutor(uint256 indexed executorId, address indexed executorAddress); + + modifier executorExists(uint256 _executorId) { + require(_executorId > 0 && _executorId < executorsNextIndex, ERROR_INEXISTENT_EXECUTOR); + _; + } + + /** + * @notice Initialize the registry + */ + function initialize() public onlyInit { + initialized(); + // Create empty record to begin executor IDs at 1 + executorsNextIndex = 1; + } + + /** + * @notice Add a new script executor with address `_executor` to the registry + * @param _executor Address of the IEVMScriptExecutor that will be added to the registry + * @return id Identifier of the executor in the registry + */ + function addScriptExecutor(IEVMScriptExecutor _executor) external auth(REGISTRY_ADD_EXECUTOR_ROLE) returns (uint256 id) { + uint256 executorId = executorsNextIndex++; + executors[executorId] = ExecutorEntry(_executor, true); + /* emit EnableExecutor(executorId, _executor); */ + return executorId; + } + + /** + * @notice Disable script executor with ID `_executorId` + * @param _executorId Identifier of the executor in the registry + */ + function disableScriptExecutor(uint256 _executorId) + external + authP(REGISTRY_MANAGER_ROLE, arr(_executorId)) + { + // Note that we don't need to check for an executor's existence in this case, as only + // existing executors can be enabled + ExecutorEntry storage executorEntry = executors[_executorId]; + require(executorEntry.enabled, ERROR_EXECUTOR_DISABLED); + executorEntry.enabled = false; + emit DisableExecutor(_executorId, executorEntry.executor); + } + + /** + * @notice Enable script executor with ID `_executorId` + * @param _executorId Identifier of the executor in the registry + */ + function enableScriptExecutor(uint256 _executorId) + external + authP(REGISTRY_MANAGER_ROLE, arr(_executorId)) + executorExists(_executorId) + { + ExecutorEntry storage executorEntry = executors[_executorId]; + require(!executorEntry.enabled, ERROR_EXECUTOR_ENABLED); + executorEntry.enabled = true; + emit EnableExecutor(_executorId, executorEntry.executor); + } + + /** + * @dev Get the script executor that can execute a particular script based on its first 4 bytes + * @param _script EVMScript being inspected + */ + function getScriptExecutor(bytes _script) public view returns (IEVMScriptExecutor) { + uint256 id = _script.getSpecId(); + + // Note that we don't need to check for an executor's existence in this case, as only + // existing executors can be enabled + ExecutorEntry storage entry = executors[id]; + return entry.enabled ? entry.executor : IEVMScriptExecutor(0); + } +} diff --git a/contracts/mutants/EVMScriptRegistry/1/EHC/EVMScriptRegistry.sol b/contracts/mutants/EVMScriptRegistry/1/EHC/EVMScriptRegistry.sol new file mode 100644 index 00000000000..a5259a53903 --- /dev/null +++ b/contracts/mutants/EVMScriptRegistry/1/EHC/EVMScriptRegistry.sol @@ -0,0 +1,104 @@ +pragma solidity 0.4.24; + +import "../apps/AragonApp.sol"; +import "./ScriptHelpers.sol"; +import "./IEVMScriptExecutor.sol"; +import "./IEVMScriptRegistry.sol"; + + +/* solium-disable function-order */ +// Allow public initialize() to be first +contract EVMScriptRegistry is IEVMScriptRegistry, EVMScriptRegistryConstants, AragonApp { + using ScriptHelpers for bytes; + + // bytes32 public constant REGISTRY_ADD_EXECUTOR_ROLE = keccak256("REGISTRY_ADD_EXECUTOR_ROLE"); + bytes32 public constant REGISTRY_ADD_EXECUTOR_ROLE = 0xc4e90f38eea8c4212a009ca7b8947943ba4d4a58d19b683417f65291d1cd9ed2; + // WARN: Manager can censor all votes and the like happening in an org + // bytes32 public constant REGISTRY_MANAGER_ROLE = keccak256("REGISTRY_MANAGER_ROLE"); + bytes32 public constant REGISTRY_MANAGER_ROLE = 0xf7a450ef335e1892cb42c8ca72e7242359d7711924b75db5717410da3f614aa3; + + string private constant ERROR_INEXISTENT_EXECUTOR = "EVMREG_INEXISTENT_EXECUTOR"; + string private constant ERROR_EXECUTOR_ENABLED = "EVMREG_EXECUTOR_ENABLED"; + string private constant ERROR_EXECUTOR_DISABLED = "EVMREG_EXECUTOR_DISABLED"; + + struct ExecutorEntry { + IEVMScriptExecutor executor; + bool enabled; + } + + uint256 private executorsNextIndex; + mapping (uint256 => ExecutorEntry) public executors; + + event EnableExecutor(uint256 indexed executorId, address indexed executorAddress); + event DisableExecutor(uint256 indexed executorId, address indexed executorAddress); + + modifier executorExists(uint256 _executorId) { + /* require(_executorId > 0 && _executorId < executorsNextIndex, ERROR_INEXISTENT_EXECUTOR); */ + _; + } + + /** + * @notice Initialize the registry + */ + function initialize() public onlyInit { + initialized(); + // Create empty record to begin executor IDs at 1 + executorsNextIndex = 1; + } + + /** + * @notice Add a new script executor with address `_executor` to the registry + * @param _executor Address of the IEVMScriptExecutor that will be added to the registry + * @return id Identifier of the executor in the registry + */ + function addScriptExecutor(IEVMScriptExecutor _executor) external auth(REGISTRY_ADD_EXECUTOR_ROLE) returns (uint256 id) { + uint256 executorId = executorsNextIndex++; + executors[executorId] = ExecutorEntry(_executor, true); + emit EnableExecutor(executorId, _executor); + return executorId; + } + + /** + * @notice Disable script executor with ID `_executorId` + * @param _executorId Identifier of the executor in the registry + */ + function disableScriptExecutor(uint256 _executorId) + external + authP(REGISTRY_MANAGER_ROLE, arr(_executorId)) + { + // Note that we don't need to check for an executor's existence in this case, as only + // existing executors can be enabled + ExecutorEntry storage executorEntry = executors[_executorId]; + require(executorEntry.enabled, ERROR_EXECUTOR_DISABLED); + executorEntry.enabled = false; + emit DisableExecutor(_executorId, executorEntry.executor); + } + + /** + * @notice Enable script executor with ID `_executorId` + * @param _executorId Identifier of the executor in the registry + */ + function enableScriptExecutor(uint256 _executorId) + external + authP(REGISTRY_MANAGER_ROLE, arr(_executorId)) + executorExists(_executorId) + { + ExecutorEntry storage executorEntry = executors[_executorId]; + require(!executorEntry.enabled, ERROR_EXECUTOR_ENABLED); + executorEntry.enabled = true; + emit EnableExecutor(_executorId, executorEntry.executor); + } + + /** + * @dev Get the script executor that can execute a particular script based on its first 4 bytes + * @param _script EVMScript being inspected + */ + function getScriptExecutor(bytes _script) public view returns (IEVMScriptExecutor) { + uint256 id = _script.getSpecId(); + + // Note that we don't need to check for an executor's existence in this case, as only + // existing executors can be enabled + ExecutorEntry storage entry = executors[id]; + return entry.enabled ? entry.executor : IEVMScriptExecutor(0); + } +} diff --git a/contracts/mutants/EVMScriptRegistry/1/FVR/EVMScriptRegistry.sol b/contracts/mutants/EVMScriptRegistry/1/FVR/EVMScriptRegistry.sol new file mode 100644 index 00000000000..ff369097a18 --- /dev/null +++ b/contracts/mutants/EVMScriptRegistry/1/FVR/EVMScriptRegistry.sol @@ -0,0 +1,104 @@ +pragma solidity 0.4.24; + +import "../apps/AragonApp.sol"; +import "./ScriptHelpers.sol"; +import "./IEVMScriptExecutor.sol"; +import "./IEVMScriptRegistry.sol"; + + +/* solium-disable function-order */ +// Allow public initialize() to be first +contract EVMScriptRegistry is IEVMScriptRegistry, EVMScriptRegistryConstants, AragonApp { + using ScriptHelpers for bytes; + + // bytes32 public constant REGISTRY_ADD_EXECUTOR_ROLE = keccak256("REGISTRY_ADD_EXECUTOR_ROLE"); + bytes32 public constant REGISTRY_ADD_EXECUTOR_ROLE = 0xc4e90f38eea8c4212a009ca7b8947943ba4d4a58d19b683417f65291d1cd9ed2; + // WARN: Manager can censor all votes and the like happening in an org + // bytes32 public constant REGISTRY_MANAGER_ROLE = keccak256("REGISTRY_MANAGER_ROLE"); + bytes32 public constant REGISTRY_MANAGER_ROLE = 0xf7a450ef335e1892cb42c8ca72e7242359d7711924b75db5717410da3f614aa3; + + string private constant ERROR_INEXISTENT_EXECUTOR = "EVMREG_INEXISTENT_EXECUTOR"; + string private constant ERROR_EXECUTOR_ENABLED = "EVMREG_EXECUTOR_ENABLED"; + string private constant ERROR_EXECUTOR_DISABLED = "EVMREG_EXECUTOR_DISABLED"; + + struct ExecutorEntry { + IEVMScriptExecutor executor; + bool enabled; + } + + uint256 private executorsNextIndex; + mapping (uint256 => ExecutorEntry) public executors; + + event EnableExecutor(uint256 indexed executorId, address indexed executorAddress); + event DisableExecutor(uint256 indexed executorId, address indexed executorAddress); + + modifier executorExists(uint256 _executorId) { + require(_executorId > 0 && _executorId < executorsNextIndex, ERROR_INEXISTENT_EXECUTOR); + _; + } + + /** + * @notice Initialize the registry + */ + function initialize() external onlyInit { + initialized(); + // Create empty record to begin executor IDs at 1 + executorsNextIndex = 1; + } + + /** + * @notice Add a new script executor with address `_executor` to the registry + * @param _executor Address of the IEVMScriptExecutor that will be added to the registry + * @return id Identifier of the executor in the registry + */ + function addScriptExecutor(IEVMScriptExecutor _executor) external auth(REGISTRY_ADD_EXECUTOR_ROLE) returns (uint256 id) { + uint256 executorId = executorsNextIndex++; + executors[executorId] = ExecutorEntry(_executor, true); + emit EnableExecutor(executorId, _executor); + return executorId; + } + + /** + * @notice Disable script executor with ID `_executorId` + * @param _executorId Identifier of the executor in the registry + */ + function disableScriptExecutor(uint256 _executorId) + external + authP(REGISTRY_MANAGER_ROLE, arr(_executorId)) + { + // Note that we don't need to check for an executor's existence in this case, as only + // existing executors can be enabled + ExecutorEntry storage executorEntry = executors[_executorId]; + require(executorEntry.enabled, ERROR_EXECUTOR_DISABLED); + executorEntry.enabled = false; + emit DisableExecutor(_executorId, executorEntry.executor); + } + + /** + * @notice Enable script executor with ID `_executorId` + * @param _executorId Identifier of the executor in the registry + */ + function enableScriptExecutor(uint256 _executorId) + external + authP(REGISTRY_MANAGER_ROLE, arr(_executorId)) + executorExists(_executorId) + { + ExecutorEntry storage executorEntry = executors[_executorId]; + require(!executorEntry.enabled, ERROR_EXECUTOR_ENABLED); + executorEntry.enabled = true; + emit EnableExecutor(_executorId, executorEntry.executor); + } + + /** + * @dev Get the script executor that can execute a particular script based on its first 4 bytes + * @param _script EVMScript being inspected + */ + function getScriptExecutor(bytes _script) public view returns (IEVMScriptExecutor) { + uint256 id = _script.getSpecId(); + + // Note that we don't need to check for an executor's existence in this case, as only + // existing executors can be enabled + ExecutorEntry storage entry = executors[id]; + return entry.enabled ? entry.executor : IEVMScriptExecutor(0); + } +} diff --git a/contracts/mutants/EVMScriptRegistry/1/ILR/EVMScriptRegistry.sol b/contracts/mutants/EVMScriptRegistry/1/ILR/EVMScriptRegistry.sol new file mode 100644 index 00000000000..2f97cfec5fa --- /dev/null +++ b/contracts/mutants/EVMScriptRegistry/1/ILR/EVMScriptRegistry.sol @@ -0,0 +1,104 @@ +pragma solidity 0.4.24; + +import "../apps/AragonApp.sol"; +import "./ScriptHelpers.sol"; +import "./IEVMScriptExecutor.sol"; +import "./IEVMScriptRegistry.sol"; + + +/* solium-disable function-order */ +// Allow public initialize() to be first +contract EVMScriptRegistry is IEVMScriptRegistry, EVMScriptRegistryConstants, AragonApp { + using ScriptHelpers for bytes; + + // bytes32 public constant REGISTRY_ADD_EXECUTOR_ROLE = keccak256("REGISTRY_ADD_EXECUTOR_ROLE"); + bytes32 public constant REGISTRY_ADD_EXECUTOR_ROLE = 0xc4e90f38eea8c4212a009ca7b8947943ba4d4a58d19b683417f65291d1cd9ed2; + // WARN: Manager can censor all votes and the like happening in an org + // bytes32 public constant REGISTRY_MANAGER_ROLE = keccak256("REGISTRY_MANAGER_ROLE"); + bytes32 public constant REGISTRY_MANAGER_ROLE = 0xf7a450ef335e1892cb42c8ca72e7242359d7711924b75db5717410da3f614aa3; + + string private constant ERROR_INEXISTENT_EXECUTOR = "EVMREG_INEXISTENT_EXECUTOR"; + string private constant ERROR_EXECUTOR_ENABLED = "EVMREG_EXECUTOR_ENABLED"; + string private constant ERROR_EXECUTOR_DISABLED = "EVMREG_EXECUTOR_DISABLED"; + + struct ExecutorEntry { + IEVMScriptExecutor executor; + bool enabled; + } + + uint256 private executorsNextIndex; + mapping (uint256 => ExecutorEntry) public executors; + + event EnableExecutor(uint256 indexed executorId, address indexed executorAddress); + event DisableExecutor(uint256 indexed executorId, address indexed executorAddress); + + modifier executorExists(uint256 _executorId) { + require(_executorId > 1 && _executorId < executorsNextIndex, ERROR_INEXISTENT_EXECUTOR); + _; + } + + /** + * @notice Initialize the registry + */ + function initialize() public onlyInit { + initialized(); + // Create empty record to begin executor IDs at 1 + executorsNextIndex = 1; + } + + /** + * @notice Add a new script executor with address `_executor` to the registry + * @param _executor Address of the IEVMScriptExecutor that will be added to the registry + * @return id Identifier of the executor in the registry + */ + function addScriptExecutor(IEVMScriptExecutor _executor) external auth(REGISTRY_ADD_EXECUTOR_ROLE) returns (uint256 id) { + uint256 executorId = executorsNextIndex++; + executors[executorId] = ExecutorEntry(_executor, true); + emit EnableExecutor(executorId, _executor); + return executorId; + } + + /** + * @notice Disable script executor with ID `_executorId` + * @param _executorId Identifier of the executor in the registry + */ + function disableScriptExecutor(uint256 _executorId) + external + authP(REGISTRY_MANAGER_ROLE, arr(_executorId)) + { + // Note that we don't need to check for an executor's existence in this case, as only + // existing executors can be enabled + ExecutorEntry storage executorEntry = executors[_executorId]; + require(executorEntry.enabled, ERROR_EXECUTOR_DISABLED); + executorEntry.enabled = false; + emit DisableExecutor(_executorId, executorEntry.executor); + } + + /** + * @notice Enable script executor with ID `_executorId` + * @param _executorId Identifier of the executor in the registry + */ + function enableScriptExecutor(uint256 _executorId) + external + authP(REGISTRY_MANAGER_ROLE, arr(_executorId)) + executorExists(_executorId) + { + ExecutorEntry storage executorEntry = executors[_executorId]; + require(!executorEntry.enabled, ERROR_EXECUTOR_ENABLED); + executorEntry.enabled = true; + emit EnableExecutor(_executorId, executorEntry.executor); + } + + /** + * @dev Get the script executor that can execute a particular script based on its first 4 bytes + * @param _script EVMScript being inspected + */ + function getScriptExecutor(bytes _script) public view returns (IEVMScriptExecutor) { + uint256 id = _script.getSpecId(); + + // Note that we don't need to check for an executor's existence in this case, as only + // existing executors can be enabled + ExecutorEntry storage entry = executors[id]; + return entry.enabled ? entry.executor : IEVMScriptExecutor(0); + } +} diff --git a/contracts/mutants/EVMScriptRegistry/1/MOC/EVMScriptRegistry.sol b/contracts/mutants/EVMScriptRegistry/1/MOC/EVMScriptRegistry.sol new file mode 100644 index 00000000000..bc8e406771d --- /dev/null +++ b/contracts/mutants/EVMScriptRegistry/1/MOC/EVMScriptRegistry.sol @@ -0,0 +1,104 @@ +pragma solidity 0.4.24; + +import "../apps/AragonApp.sol"; +import "./ScriptHelpers.sol"; +import "./IEVMScriptExecutor.sol"; +import "./IEVMScriptRegistry.sol"; + + +/* solium-disable function-order */ +// Allow public initialize() to be first +contract EVMScriptRegistry is IEVMScriptRegistry, EVMScriptRegistryConstants, AragonApp { + using ScriptHelpers for bytes; + + // bytes32 public constant REGISTRY_ADD_EXECUTOR_ROLE = keccak256("REGISTRY_ADD_EXECUTOR_ROLE"); + bytes32 public constant REGISTRY_ADD_EXECUTOR_ROLE = 0xc4e90f38eea8c4212a009ca7b8947943ba4d4a58d19b683417f65291d1cd9ed2; + // WARN: Manager can censor all votes and the like happening in an org + // bytes32 public constant REGISTRY_MANAGER_ROLE = keccak256("REGISTRY_MANAGER_ROLE"); + bytes32 public constant REGISTRY_MANAGER_ROLE = 0xf7a450ef335e1892cb42c8ca72e7242359d7711924b75db5717410da3f614aa3; + + string private constant ERROR_INEXISTENT_EXECUTOR = "EVMREG_INEXISTENT_EXECUTOR"; + string private constant ERROR_EXECUTOR_ENABLED = "EVMREG_EXECUTOR_ENABLED"; + string private constant ERROR_EXECUTOR_DISABLED = "EVMREG_EXECUTOR_DISABLED"; + + struct ExecutorEntry { + IEVMScriptExecutor executor; + bool enabled; + } + + uint256 private executorsNextIndex; + mapping (uint256 => ExecutorEntry) public executors; + + event EnableExecutor(uint256 indexed executorId, address indexed executorAddress); + event DisableExecutor(uint256 indexed executorId, address indexed executorAddress); + + modifier executorExists(uint256 _executorId) { + require(_executorId > 0 && _executorId < executorsNextIndex, ERROR_INEXISTENT_EXECUTOR); + _; + } + + /** + * @notice Initialize the registry + */ + function initialize() public onlyInit { + initialized(); + // Create empty record to begin executor IDs at 1 + executorsNextIndex = 1; + } + + /** + * @notice Add a new script executor with address `_executor` to the registry + * @param _executor Address of the IEVMScriptExecutor that will be added to the registry + * @return id Identifier of the executor in the registry + */ + function addScriptExecutor(IEVMScriptExecutor _executor) external auth(REGISTRY_ADD_EXECUTOR_ROLE) returns (uint256 id) { + uint256 executorId = executorsNextIndex++; + executors[executorId] = ExecutorEntry(_executor, true); + emit EnableExecutor(executorId, _executor); + return executorId; + } + + /** + * @notice Disable script executor with ID `_executorId` + * @param _executorId Identifier of the executor in the registry + */ + function disableScriptExecutor(uint256 _executorId) + external + authP(REGISTRY_MANAGER_ROLE, arr(_executorId)) + { + // Note that we don't need to check for an executor's existence in this case, as only + // existing executors can be enabled + ExecutorEntry storage executorEntry = executors[_executorId]; + require(executorEntry.enabled, ERROR_EXECUTOR_DISABLED); + executorEntry.enabled = false; + emit DisableExecutor(_executorId, executorEntry.executor); + } + + /** + * @notice Enable script executor with ID `_executorId` + * @param _executorId Identifier of the executor in the registry + */ + function enableScriptExecutor(uint256 _executorId) + external + executorExists(_executorId) + authP(REGISTRY_MANAGER_ROLE, arr(_executorId)) + { + ExecutorEntry storage executorEntry = executors[_executorId]; + require(!executorEntry.enabled, ERROR_EXECUTOR_ENABLED); + executorEntry.enabled = true; + emit EnableExecutor(_executorId, executorEntry.executor); + } + + /** + * @dev Get the script executor that can execute a particular script based on its first 4 bytes + * @param _script EVMScript being inspected + */ + function getScriptExecutor(bytes _script) public view returns (IEVMScriptExecutor) { + uint256 id = _script.getSpecId(); + + // Note that we don't need to check for an executor's existence in this case, as only + // existing executors can be enabled + ExecutorEntry storage entry = executors[id]; + return entry.enabled ? entry.executor : IEVMScriptExecutor(0); + } +} diff --git a/contracts/mutants/EVMScriptRegistry/1/MOD/EVMScriptRegistry.sol b/contracts/mutants/EVMScriptRegistry/1/MOD/EVMScriptRegistry.sol new file mode 100644 index 00000000000..ee443fed237 --- /dev/null +++ b/contracts/mutants/EVMScriptRegistry/1/MOD/EVMScriptRegistry.sol @@ -0,0 +1,104 @@ +pragma solidity 0.4.24; + +import "../apps/AragonApp.sol"; +import "./ScriptHelpers.sol"; +import "./IEVMScriptExecutor.sol"; +import "./IEVMScriptRegistry.sol"; + + +/* solium-disable function-order */ +// Allow public initialize() to be first +contract EVMScriptRegistry is IEVMScriptRegistry, EVMScriptRegistryConstants, AragonApp { + using ScriptHelpers for bytes; + + // bytes32 public constant REGISTRY_ADD_EXECUTOR_ROLE = keccak256("REGISTRY_ADD_EXECUTOR_ROLE"); + bytes32 public constant REGISTRY_ADD_EXECUTOR_ROLE = 0xc4e90f38eea8c4212a009ca7b8947943ba4d4a58d19b683417f65291d1cd9ed2; + // WARN: Manager can censor all votes and the like happening in an org + // bytes32 public constant REGISTRY_MANAGER_ROLE = keccak256("REGISTRY_MANAGER_ROLE"); + bytes32 public constant REGISTRY_MANAGER_ROLE = 0xf7a450ef335e1892cb42c8ca72e7242359d7711924b75db5717410da3f614aa3; + + string private constant ERROR_INEXISTENT_EXECUTOR = "EVMREG_INEXISTENT_EXECUTOR"; + string private constant ERROR_EXECUTOR_ENABLED = "EVMREG_EXECUTOR_ENABLED"; + string private constant ERROR_EXECUTOR_DISABLED = "EVMREG_EXECUTOR_DISABLED"; + + struct ExecutorEntry { + IEVMScriptExecutor executor; + bool enabled; + } + + uint256 private executorsNextIndex; + mapping (uint256 => ExecutorEntry) public executors; + + event EnableExecutor(uint256 indexed executorId, address indexed executorAddress); + event DisableExecutor(uint256 indexed executorId, address indexed executorAddress); + + modifier executorExists(uint256 _executorId) { + require(_executorId > 0 && _executorId < executorsNextIndex, ERROR_INEXISTENT_EXECUTOR); + _; + } + + /** + * @notice Initialize the registry + */ + function initialize() public { + initialized(); + // Create empty record to begin executor IDs at 1 + executorsNextIndex = 1; + } + + /** + * @notice Add a new script executor with address `_executor` to the registry + * @param _executor Address of the IEVMScriptExecutor that will be added to the registry + * @return id Identifier of the executor in the registry + */ + function addScriptExecutor(IEVMScriptExecutor _executor) external auth(REGISTRY_ADD_EXECUTOR_ROLE) returns (uint256 id) { + uint256 executorId = executorsNextIndex++; + executors[executorId] = ExecutorEntry(_executor, true); + emit EnableExecutor(executorId, _executor); + return executorId; + } + + /** + * @notice Disable script executor with ID `_executorId` + * @param _executorId Identifier of the executor in the registry + */ + function disableScriptExecutor(uint256 _executorId) + external + authP(REGISTRY_MANAGER_ROLE, arr(_executorId)) + { + // Note that we don't need to check for an executor's existence in this case, as only + // existing executors can be enabled + ExecutorEntry storage executorEntry = executors[_executorId]; + require(executorEntry.enabled, ERROR_EXECUTOR_DISABLED); + executorEntry.enabled = false; + emit DisableExecutor(_executorId, executorEntry.executor); + } + + /** + * @notice Enable script executor with ID `_executorId` + * @param _executorId Identifier of the executor in the registry + */ + function enableScriptExecutor(uint256 _executorId) + external + authP(REGISTRY_MANAGER_ROLE, arr(_executorId)) + executorExists(_executorId) + { + ExecutorEntry storage executorEntry = executors[_executorId]; + require(!executorEntry.enabled, ERROR_EXECUTOR_ENABLED); + executorEntry.enabled = true; + emit EnableExecutor(_executorId, executorEntry.executor); + } + + /** + * @dev Get the script executor that can execute a particular script based on its first 4 bytes + * @param _script EVMScript being inspected + */ + function getScriptExecutor(bytes _script) public view returns (IEVMScriptExecutor) { + uint256 id = _script.getSpecId(); + + // Note that we don't need to check for an executor's existence in this case, as only + // existing executors can be enabled + ExecutorEntry storage entry = executors[id]; + return entry.enabled ? entry.executor : IEVMScriptExecutor(0); + } +} diff --git a/contracts/mutants/EVMScriptRegistry/1/MOR/EVMScriptRegistry.sol b/contracts/mutants/EVMScriptRegistry/1/MOR/EVMScriptRegistry.sol new file mode 100644 index 00000000000..d634307fcdc --- /dev/null +++ b/contracts/mutants/EVMScriptRegistry/1/MOR/EVMScriptRegistry.sol @@ -0,0 +1,104 @@ +pragma solidity 0.4.24; + +import "../apps/AragonApp.sol"; +import "./ScriptHelpers.sol"; +import "./IEVMScriptExecutor.sol"; +import "./IEVMScriptRegistry.sol"; + + +/* solium-disable function-order */ +// Allow public initialize() to be first +contract EVMScriptRegistry is IEVMScriptRegistry, EVMScriptRegistryConstants, AragonApp { + using ScriptHelpers for bytes; + + // bytes32 public constant REGISTRY_ADD_EXECUTOR_ROLE = keccak256("REGISTRY_ADD_EXECUTOR_ROLE"); + bytes32 public constant REGISTRY_ADD_EXECUTOR_ROLE = 0xc4e90f38eea8c4212a009ca7b8947943ba4d4a58d19b683417f65291d1cd9ed2; + // WARN: Manager can censor all votes and the like happening in an org + // bytes32 public constant REGISTRY_MANAGER_ROLE = keccak256("REGISTRY_MANAGER_ROLE"); + bytes32 public constant REGISTRY_MANAGER_ROLE = 0xf7a450ef335e1892cb42c8ca72e7242359d7711924b75db5717410da3f614aa3; + + string private constant ERROR_INEXISTENT_EXECUTOR = "EVMREG_INEXISTENT_EXECUTOR"; + string private constant ERROR_EXECUTOR_ENABLED = "EVMREG_EXECUTOR_ENABLED"; + string private constant ERROR_EXECUTOR_DISABLED = "EVMREG_EXECUTOR_DISABLED"; + + struct ExecutorEntry { + IEVMScriptExecutor executor; + bool enabled; + } + + uint256 private executorsNextIndex; + mapping (uint256 => ExecutorEntry) public executors; + + event EnableExecutor(uint256 indexed executorId, address indexed executorAddress); + event DisableExecutor(uint256 indexed executorId, address indexed executorAddress); + + modifier executorExists(uint256 _executorId) { + require(_executorId > 0 && _executorId < executorsNextIndex, ERROR_INEXISTENT_EXECUTOR); + _; + } + + /** + * @notice Initialize the registry + */ + function initialize() public onlyInit { + initialized(); + // Create empty record to begin executor IDs at 1 + executorsNextIndex = 1; + } + + /** + * @notice Add a new script executor with address `_executor` to the registry + * @param _executor Address of the IEVMScriptExecutor that will be added to the registry + * @return id Identifier of the executor in the registry + */ + function addScriptExecutor(IEVMScriptExecutor _executor) external onlyInit returns (uint256 id) { + uint256 executorId = executorsNextIndex++; + executors[executorId] = ExecutorEntry(_executor, true); + emit EnableExecutor(executorId, _executor); + return executorId; + } + + /** + * @notice Disable script executor with ID `_executorId` + * @param _executorId Identifier of the executor in the registry + */ + function disableScriptExecutor(uint256 _executorId) + external + authP(REGISTRY_MANAGER_ROLE, arr(_executorId)) + { + // Note that we don't need to check for an executor's existence in this case, as only + // existing executors can be enabled + ExecutorEntry storage executorEntry = executors[_executorId]; + require(executorEntry.enabled, ERROR_EXECUTOR_DISABLED); + executorEntry.enabled = false; + emit DisableExecutor(_executorId, executorEntry.executor); + } + + /** + * @notice Enable script executor with ID `_executorId` + * @param _executorId Identifier of the executor in the registry + */ + function enableScriptExecutor(uint256 _executorId) + external + authP(REGISTRY_MANAGER_ROLE, arr(_executorId)) + executorExists(_executorId) + { + ExecutorEntry storage executorEntry = executors[_executorId]; + require(!executorEntry.enabled, ERROR_EXECUTOR_ENABLED); + executorEntry.enabled = true; + emit EnableExecutor(_executorId, executorEntry.executor); + } + + /** + * @dev Get the script executor that can execute a particular script based on its first 4 bytes + * @param _script EVMScript being inspected + */ + function getScriptExecutor(bytes _script) public view returns (IEVMScriptExecutor) { + uint256 id = _script.getSpecId(); + + // Note that we don't need to check for an executor's existence in this case, as only + // existing executors can be enabled + ExecutorEntry storage entry = executors[id]; + return entry.enabled ? entry.executor : IEVMScriptExecutor(0); + } +} diff --git a/contracts/mutants/EVMScriptRegistry/1/RSD/EVMScriptRegistry.sol b/contracts/mutants/EVMScriptRegistry/1/RSD/EVMScriptRegistry.sol new file mode 100644 index 00000000000..d516cf7cd97 --- /dev/null +++ b/contracts/mutants/EVMScriptRegistry/1/RSD/EVMScriptRegistry.sol @@ -0,0 +1,104 @@ +pragma solidity 0.4.24; + +import "../apps/AragonApp.sol"; +import "./ScriptHelpers.sol"; +import "./IEVMScriptExecutor.sol"; +import "./IEVMScriptRegistry.sol"; + + +/* solium-disable function-order */ +// Allow public initialize() to be first +contract EVMScriptRegistry is IEVMScriptRegistry, EVMScriptRegistryConstants, AragonApp { + using ScriptHelpers for bytes; + + // bytes32 public constant REGISTRY_ADD_EXECUTOR_ROLE = keccak256("REGISTRY_ADD_EXECUTOR_ROLE"); + bytes32 public constant REGISTRY_ADD_EXECUTOR_ROLE = 0xc4e90f38eea8c4212a009ca7b8947943ba4d4a58d19b683417f65291d1cd9ed2; + // WARN: Manager can censor all votes and the like happening in an org + // bytes32 public constant REGISTRY_MANAGER_ROLE = keccak256("REGISTRY_MANAGER_ROLE"); + bytes32 public constant REGISTRY_MANAGER_ROLE = 0xf7a450ef335e1892cb42c8ca72e7242359d7711924b75db5717410da3f614aa3; + + string private constant ERROR_INEXISTENT_EXECUTOR = "EVMREG_INEXISTENT_EXECUTOR"; + string private constant ERROR_EXECUTOR_ENABLED = "EVMREG_EXECUTOR_ENABLED"; + string private constant ERROR_EXECUTOR_DISABLED = "EVMREG_EXECUTOR_DISABLED"; + + struct ExecutorEntry { + IEVMScriptExecutor executor; + bool enabled; + } + + uint256 private executorsNextIndex; + mapping (uint256 => ExecutorEntry) public executors; + + event EnableExecutor(uint256 indexed executorId, address indexed executorAddress); + event DisableExecutor(uint256 indexed executorId, address indexed executorAddress); + + modifier executorExists(uint256 _executorId) { + require(_executorId > 0 && _executorId < executorsNextIndex, ERROR_INEXISTENT_EXECUTOR); + _; + } + + /** + * @notice Initialize the registry + */ + function initialize() public onlyInit { + initialized(); + // Create empty record to begin executor IDs at 1 + executorsNextIndex = 1; + } + + /** + * @notice Add a new script executor with address `_executor` to the registry + * @param _executor Address of the IEVMScriptExecutor that will be added to the registry + * @return id Identifier of the executor in the registry + */ + function addScriptExecutor(IEVMScriptExecutor _executor) external auth(REGISTRY_ADD_EXECUTOR_ROLE) returns (uint256 id) { + uint256 executorId = executorsNextIndex++; + executors[executorId] = ExecutorEntry(_executor, true); + emit EnableExecutor(executorId, _executor); + /* return executorId; */ + } + + /** + * @notice Disable script executor with ID `_executorId` + * @param _executorId Identifier of the executor in the registry + */ + function disableScriptExecutor(uint256 _executorId) + external + authP(REGISTRY_MANAGER_ROLE, arr(_executorId)) + { + // Note that we don't need to check for an executor's existence in this case, as only + // existing executors can be enabled + ExecutorEntry storage executorEntry = executors[_executorId]; + require(executorEntry.enabled, ERROR_EXECUTOR_DISABLED); + executorEntry.enabled = false; + emit DisableExecutor(_executorId, executorEntry.executor); + } + + /** + * @notice Enable script executor with ID `_executorId` + * @param _executorId Identifier of the executor in the registry + */ + function enableScriptExecutor(uint256 _executorId) + external + authP(REGISTRY_MANAGER_ROLE, arr(_executorId)) + executorExists(_executorId) + { + ExecutorEntry storage executorEntry = executors[_executorId]; + require(!executorEntry.enabled, ERROR_EXECUTOR_ENABLED); + executorEntry.enabled = true; + emit EnableExecutor(_executorId, executorEntry.executor); + } + + /** + * @dev Get the script executor that can execute a particular script based on its first 4 bytes + * @param _script EVMScript being inspected + */ + function getScriptExecutor(bytes _script) public view returns (IEVMScriptExecutor) { + uint256 id = _script.getSpecId(); + + // Note that we don't need to check for an executor's existence in this case, as only + // existing executors can be enabled + ExecutorEntry storage entry = executors[id]; + return entry.enabled ? entry.executor : IEVMScriptExecutor(0); + } +} diff --git a/contracts/mutants/EVMScriptRegistry/1/SLR/EVMScriptRegistry.sol b/contracts/mutants/EVMScriptRegistry/1/SLR/EVMScriptRegistry.sol new file mode 100644 index 00000000000..80d48ee5064 --- /dev/null +++ b/contracts/mutants/EVMScriptRegistry/1/SLR/EVMScriptRegistry.sol @@ -0,0 +1,104 @@ +pragma solidity 0.4.24; + +import "../apps/AragonApp.sol"; +import "./ScriptHelpers.sol"; +import "./IEVMScriptExecutor.sol"; +import "./IEVMScriptRegistry.sol"; + + +/* solium-disable function-order */ +// Allow public initialize() to be first +contract EVMScriptRegistry is IEVMScriptRegistry, EVMScriptRegistryConstants, AragonApp { + using ScriptHelpers for bytes; + + // bytes32 public constant REGISTRY_ADD_EXECUTOR_ROLE = keccak256("REGISTRY_ADD_EXECUTOR_ROLE"); + bytes32 public constant REGISTRY_ADD_EXECUTOR_ROLE = 0xc4e90f38eea8c4212a009ca7b8947943ba4d4a58d19b683417f65291d1cd9ed2; + // WARN: Manager can censor all votes and the like happening in an org + // bytes32 public constant REGISTRY_MANAGER_ROLE = keccak256("REGISTRY_MANAGER_ROLE"); + bytes32 public constant REGISTRY_MANAGER_ROLE = 0xf7a450ef335e1892cb42c8ca72e7242359d7711924b75db5717410da3f614aa3; + + string private constant ERROR_INEXISTENT_EXECUTOR = ""; + string private constant ERROR_EXECUTOR_ENABLED = "EVMREG_EXECUTOR_ENABLED"; + string private constant ERROR_EXECUTOR_DISABLED = "EVMREG_EXECUTOR_DISABLED"; + + struct ExecutorEntry { + IEVMScriptExecutor executor; + bool enabled; + } + + uint256 private executorsNextIndex; + mapping (uint256 => ExecutorEntry) public executors; + + event EnableExecutor(uint256 indexed executorId, address indexed executorAddress); + event DisableExecutor(uint256 indexed executorId, address indexed executorAddress); + + modifier executorExists(uint256 _executorId) { + require(_executorId > 0 && _executorId < executorsNextIndex, ERROR_INEXISTENT_EXECUTOR); + _; + } + + /** + * @notice Initialize the registry + */ + function initialize() public onlyInit { + initialized(); + // Create empty record to begin executor IDs at 1 + executorsNextIndex = 1; + } + + /** + * @notice Add a new script executor with address `_executor` to the registry + * @param _executor Address of the IEVMScriptExecutor that will be added to the registry + * @return id Identifier of the executor in the registry + */ + function addScriptExecutor(IEVMScriptExecutor _executor) external auth(REGISTRY_ADD_EXECUTOR_ROLE) returns (uint256 id) { + uint256 executorId = executorsNextIndex++; + executors[executorId] = ExecutorEntry(_executor, true); + emit EnableExecutor(executorId, _executor); + return executorId; + } + + /** + * @notice Disable script executor with ID `_executorId` + * @param _executorId Identifier of the executor in the registry + */ + function disableScriptExecutor(uint256 _executorId) + external + authP(REGISTRY_MANAGER_ROLE, arr(_executorId)) + { + // Note that we don't need to check for an executor's existence in this case, as only + // existing executors can be enabled + ExecutorEntry storage executorEntry = executors[_executorId]; + require(executorEntry.enabled, ERROR_EXECUTOR_DISABLED); + executorEntry.enabled = false; + emit DisableExecutor(_executorId, executorEntry.executor); + } + + /** + * @notice Enable script executor with ID `_executorId` + * @param _executorId Identifier of the executor in the registry + */ + function enableScriptExecutor(uint256 _executorId) + external + authP(REGISTRY_MANAGER_ROLE, arr(_executorId)) + executorExists(_executorId) + { + ExecutorEntry storage executorEntry = executors[_executorId]; + require(!executorEntry.enabled, ERROR_EXECUTOR_ENABLED); + executorEntry.enabled = true; + emit EnableExecutor(_executorId, executorEntry.executor); + } + + /** + * @dev Get the script executor that can execute a particular script based on its first 4 bytes + * @param _script EVMScript being inspected + */ + function getScriptExecutor(bytes _script) public view returns (IEVMScriptExecutor) { + uint256 id = _script.getSpecId(); + + // Note that we don't need to check for an executor's existence in this case, as only + // existing executors can be enabled + ExecutorEntry storage entry = executors[id]; + return entry.enabled ? entry.executor : IEVMScriptExecutor(0); + } +} diff --git a/contracts/mutants/EVMScriptRegistry/1/UORD/EVMScriptRegistry.sol b/contracts/mutants/EVMScriptRegistry/1/UORD/EVMScriptRegistry.sol new file mode 100644 index 00000000000..1310b781a4e --- /dev/null +++ b/contracts/mutants/EVMScriptRegistry/1/UORD/EVMScriptRegistry.sol @@ -0,0 +1,104 @@ +pragma solidity 0.4.24; + +import "../apps/AragonApp.sol"; +import "./ScriptHelpers.sol"; +import "./IEVMScriptExecutor.sol"; +import "./IEVMScriptRegistry.sol"; + + +/* solium-disable function-order */ +// Allow public initialize() to be first +contract EVMScriptRegistry is IEVMScriptRegistry, EVMScriptRegistryConstants, AragonApp { + using ScriptHelpers for bytes; + + // bytes32 public constant REGISTRY_ADD_EXECUTOR_ROLE = keccak256("REGISTRY_ADD_EXECUTOR_ROLE"); + bytes32 public constant REGISTRY_ADD_EXECUTOR_ROLE = 0xc4e90f38eea8c4212a009ca7b8947943ba4d4a58d19b683417f65291d1cd9ed2; + // WARN: Manager can censor all votes and the like happening in an org + // bytes32 public constant REGISTRY_MANAGER_ROLE = keccak256("REGISTRY_MANAGER_ROLE"); + bytes32 public constant REGISTRY_MANAGER_ROLE = 0xf7a450ef335e1892cb42c8ca72e7242359d7711924b75db5717410da3f614aa3; + + string private constant ERROR_INEXISTENT_EXECUTOR = "EVMREG_INEXISTENT_EXECUTOR"; + string private constant ERROR_EXECUTOR_ENABLED = "EVMREG_EXECUTOR_ENABLED"; + string private constant ERROR_EXECUTOR_DISABLED = "EVMREG_EXECUTOR_DISABLED"; + + struct ExecutorEntry { + IEVMScriptExecutor executor; + bool enabled; + } + + uint256 private executorsNextIndex; + mapping (uint256 => ExecutorEntry) public executors; + + event EnableExecutor(uint256 indexed executorId, address indexed executorAddress); + event DisableExecutor(uint256 indexed executorId, address indexed executorAddress); + + modifier executorExists(uint256 _executorId) { + require(_executorId > 0 && _executorId < executorsNextIndex, ERROR_INEXISTENT_EXECUTOR); + _; + } + + /** + * @notice Initialize the registry + */ + function initialize() public onlyInit { + initialized(); + // Create empty record to begin executor IDs at 1 + executorsNextIndex = 1; + } + + /** + * @notice Add a new script executor with address `_executor` to the registry + * @param _executor Address of the IEVMScriptExecutor that will be added to the registry + * @return id Identifier of the executor in the registry + */ + function addScriptExecutor(IEVMScriptExecutor _executor) external auth(REGISTRY_ADD_EXECUTOR_ROLE) returns (uint256 id) { + uint256 executorId = executorsNextIndex--; + executors[executorId] = ExecutorEntry(_executor, true); + emit EnableExecutor(executorId, _executor); + return executorId; + } + + /** + * @notice Disable script executor with ID `_executorId` + * @param _executorId Identifier of the executor in the registry + */ + function disableScriptExecutor(uint256 _executorId) + external + authP(REGISTRY_MANAGER_ROLE, arr(_executorId)) + { + // Note that we don't need to check for an executor's existence in this case, as only + // existing executors can be enabled + ExecutorEntry storage executorEntry = executors[_executorId]; + require(executorEntry.enabled, ERROR_EXECUTOR_DISABLED); + executorEntry.enabled = false; + emit DisableExecutor(_executorId, executorEntry.executor); + } + + /** + * @notice Enable script executor with ID `_executorId` + * @param _executorId Identifier of the executor in the registry + */ + function enableScriptExecutor(uint256 _executorId) + external + authP(REGISTRY_MANAGER_ROLE, arr(_executorId)) + executorExists(_executorId) + { + ExecutorEntry storage executorEntry = executors[_executorId]; + require(!executorEntry.enabled, ERROR_EXECUTOR_ENABLED); + executorEntry.enabled = true; + emit EnableExecutor(_executorId, executorEntry.executor); + } + + /** + * @dev Get the script executor that can execute a particular script based on its first 4 bytes + * @param _script EVMScript being inspected + */ + function getScriptExecutor(bytes _script) public view returns (IEVMScriptExecutor) { + uint256 id = _script.getSpecId(); + + // Note that we don't need to check for an executor's existence in this case, as only + // existing executors can be enabled + ExecutorEntry storage entry = executors[id]; + return entry.enabled ? entry.executor : IEVMScriptExecutor(0); + } +} diff --git a/contracts/mutants/EVMScriptRegistry/1/VVR/EVMScriptRegistry.sol b/contracts/mutants/EVMScriptRegistry/1/VVR/EVMScriptRegistry.sol new file mode 100644 index 00000000000..4bcad1fe28d --- /dev/null +++ b/contracts/mutants/EVMScriptRegistry/1/VVR/EVMScriptRegistry.sol @@ -0,0 +1,104 @@ +pragma solidity 0.4.24; + +import "../apps/AragonApp.sol"; +import "./ScriptHelpers.sol"; +import "./IEVMScriptExecutor.sol"; +import "./IEVMScriptRegistry.sol"; + + +/* solium-disable function-order */ +// Allow public initialize() to be first +contract EVMScriptRegistry is IEVMScriptRegistry, EVMScriptRegistryConstants, AragonApp { + using ScriptHelpers for bytes; + + // bytes32 public constant REGISTRY_ADD_EXECUTOR_ROLE = keccak256("REGISTRY_ADD_EXECUTOR_ROLE"); + bytes32 internal constant REGISTRY_ADD_EXECUTOR_ROLE = 0xc4e90f38eea8c4212a009ca7b8947943ba4d4a58d19b683417f65291d1cd9ed2; + // WARN: Manager can censor all votes and the like happening in an org + // bytes32 public constant REGISTRY_MANAGER_ROLE = keccak256("REGISTRY_MANAGER_ROLE"); + bytes32 public constant REGISTRY_MANAGER_ROLE = 0xf7a450ef335e1892cb42c8ca72e7242359d7711924b75db5717410da3f614aa3; + + string private constant ERROR_INEXISTENT_EXECUTOR = "EVMREG_INEXISTENT_EXECUTOR"; + string private constant ERROR_EXECUTOR_ENABLED = "EVMREG_EXECUTOR_ENABLED"; + string private constant ERROR_EXECUTOR_DISABLED = "EVMREG_EXECUTOR_DISABLED"; + + struct ExecutorEntry { + IEVMScriptExecutor executor; + bool enabled; + } + + uint256 private executorsNextIndex; + mapping (uint256 => ExecutorEntry) public executors; + + event EnableExecutor(uint256 indexed executorId, address indexed executorAddress); + event DisableExecutor(uint256 indexed executorId, address indexed executorAddress); + + modifier executorExists(uint256 _executorId) { + require(_executorId > 0 && _executorId < executorsNextIndex, ERROR_INEXISTENT_EXECUTOR); + _; + } + + /** + * @notice Initialize the registry + */ + function initialize() public onlyInit { + initialized(); + // Create empty record to begin executor IDs at 1 + executorsNextIndex = 1; + } + + /** + * @notice Add a new script executor with address `_executor` to the registry + * @param _executor Address of the IEVMScriptExecutor that will be added to the registry + * @return id Identifier of the executor in the registry + */ + function addScriptExecutor(IEVMScriptExecutor _executor) external auth(REGISTRY_ADD_EXECUTOR_ROLE) returns (uint256 id) { + uint256 executorId = executorsNextIndex++; + executors[executorId] = ExecutorEntry(_executor, true); + emit EnableExecutor(executorId, _executor); + return executorId; + } + + /** + * @notice Disable script executor with ID `_executorId` + * @param _executorId Identifier of the executor in the registry + */ + function disableScriptExecutor(uint256 _executorId) + external + authP(REGISTRY_MANAGER_ROLE, arr(_executorId)) + { + // Note that we don't need to check for an executor's existence in this case, as only + // existing executors can be enabled + ExecutorEntry storage executorEntry = executors[_executorId]; + require(executorEntry.enabled, ERROR_EXECUTOR_DISABLED); + executorEntry.enabled = false; + emit DisableExecutor(_executorId, executorEntry.executor); + } + + /** + * @notice Enable script executor with ID `_executorId` + * @param _executorId Identifier of the executor in the registry + */ + function enableScriptExecutor(uint256 _executorId) + external + authP(REGISTRY_MANAGER_ROLE, arr(_executorId)) + executorExists(_executorId) + { + ExecutorEntry storage executorEntry = executors[_executorId]; + require(!executorEntry.enabled, ERROR_EXECUTOR_ENABLED); + executorEntry.enabled = true; + emit EnableExecutor(_executorId, executorEntry.executor); + } + + /** + * @dev Get the script executor that can execute a particular script based on its first 4 bytes + * @param _script EVMScript being inspected + */ + function getScriptExecutor(bytes _script) public view returns (IEVMScriptExecutor) { + uint256 id = _script.getSpecId(); + + // Note that we don't need to check for an executor's existence in this case, as only + // existing executors can be enabled + ExecutorEntry storage entry = executors[id]; + return entry.enabled ? entry.executor : IEVMScriptExecutor(0); + } +} diff --git a/contracts/mutants/EVMScriptRegistry/2/BLR/EVMScriptRegistry.sol b/contracts/mutants/EVMScriptRegistry/2/BLR/EVMScriptRegistry.sol new file mode 100644 index 00000000000..29c90c6401e --- /dev/null +++ b/contracts/mutants/EVMScriptRegistry/2/BLR/EVMScriptRegistry.sol @@ -0,0 +1,104 @@ +pragma solidity 0.4.24; + +import "../apps/AragonApp.sol"; +import "./ScriptHelpers.sol"; +import "./IEVMScriptExecutor.sol"; +import "./IEVMScriptRegistry.sol"; + + +/* solium-disable function-order */ +// Allow public initialize() to be first +contract EVMScriptRegistry is IEVMScriptRegistry, EVMScriptRegistryConstants, AragonApp { + using ScriptHelpers for bytes; + + // bytes32 public constant REGISTRY_ADD_EXECUTOR_ROLE = keccak256("REGISTRY_ADD_EXECUTOR_ROLE"); + bytes32 public constant REGISTRY_ADD_EXECUTOR_ROLE = 0xc4e90f38eea8c4212a009ca7b8947943ba4d4a58d19b683417f65291d1cd9ed2; + // WARN: Manager can censor all votes and the like happening in an org + // bytes32 public constant REGISTRY_MANAGER_ROLE = keccak256("REGISTRY_MANAGER_ROLE"); + bytes32 public constant REGISTRY_MANAGER_ROLE = 0xf7a450ef335e1892cb42c8ca72e7242359d7711924b75db5717410da3f614aa3; + + string private constant ERROR_INEXISTENT_EXECUTOR = "EVMREG_INEXISTENT_EXECUTOR"; + string private constant ERROR_EXECUTOR_ENABLED = "EVMREG_EXECUTOR_ENABLED"; + string private constant ERROR_EXECUTOR_DISABLED = "EVMREG_EXECUTOR_DISABLED"; + + struct ExecutorEntry { + IEVMScriptExecutor executor; + bool enabled; + } + + uint256 private executorsNextIndex; + mapping (uint256 => ExecutorEntry) public executors; + + event EnableExecutor(uint256 indexed executorId, address indexed executorAddress); + event DisableExecutor(uint256 indexed executorId, address indexed executorAddress); + + modifier executorExists(uint256 _executorId) { + require(_executorId > 0 && _executorId < executorsNextIndex, ERROR_INEXISTENT_EXECUTOR); + _; + } + + /** + * @notice Initialize the registry + */ + function initialize() public onlyInit { + initialized(); + // Create empty record to begin executor IDs at 1 + executorsNextIndex = 1; + } + + /** + * @notice Add a new script executor with address `_executor` to the registry + * @param _executor Address of the IEVMScriptExecutor that will be added to the registry + * @return id Identifier of the executor in the registry + */ + function addScriptExecutor(IEVMScriptExecutor _executor) external auth(REGISTRY_ADD_EXECUTOR_ROLE) returns (uint256 id) { + uint256 executorId = executorsNextIndex++; + executors[executorId] = ExecutorEntry(_executor, false); + emit EnableExecutor(executorId, _executor); + return executorId; + } + + /** + * @notice Disable script executor with ID `_executorId` + * @param _executorId Identifier of the executor in the registry + */ + function disableScriptExecutor(uint256 _executorId) + external + authP(REGISTRY_MANAGER_ROLE, arr(_executorId)) + { + // Note that we don't need to check for an executor's existence in this case, as only + // existing executors can be enabled + ExecutorEntry storage executorEntry = executors[_executorId]; + require(executorEntry.enabled, ERROR_EXECUTOR_DISABLED); + executorEntry.enabled = true; + emit DisableExecutor(_executorId, executorEntry.executor); + } + + /** + * @notice Enable script executor with ID `_executorId` + * @param _executorId Identifier of the executor in the registry + */ + function enableScriptExecutor(uint256 _executorId) + external + authP(REGISTRY_MANAGER_ROLE, arr(_executorId)) + executorExists(_executorId) + { + ExecutorEntry storage executorEntry = executors[_executorId]; + require(!executorEntry.enabled, ERROR_EXECUTOR_ENABLED); + executorEntry.enabled = true; + emit EnableExecutor(_executorId, executorEntry.executor); + } + + /** + * @dev Get the script executor that can execute a particular script based on its first 4 bytes + * @param _script EVMScript being inspected + */ + function getScriptExecutor(bytes _script) public view returns (IEVMScriptExecutor) { + uint256 id = _script.getSpecId(); + + // Note that we don't need to check for an executor's existence in this case, as only + // existing executors can be enabled + ExecutorEntry storage entry = executors[id]; + return entry.enabled ? entry.executor : IEVMScriptExecutor(0); + } +} diff --git a/contracts/mutants/EVMScriptRegistry/2/BOR/EVMScriptRegistry.sol b/contracts/mutants/EVMScriptRegistry/2/BOR/EVMScriptRegistry.sol new file mode 100644 index 00000000000..77aca6adec6 --- /dev/null +++ b/contracts/mutants/EVMScriptRegistry/2/BOR/EVMScriptRegistry.sol @@ -0,0 +1,104 @@ +pragma solidity 0.4.24; + +import "../apps/AragonApp.sol"; +import "./ScriptHelpers.sol"; +import "./IEVMScriptExecutor.sol"; +import "./IEVMScriptRegistry.sol"; + + +/* solium-disable function-order */ +// Allow public initialize() to be first +contract EVMScriptRegistry is IEVMScriptRegistry, EVMScriptRegistryConstants, AragonApp { + using ScriptHelpers for bytes; + + // bytes32 public constant REGISTRY_ADD_EXECUTOR_ROLE = keccak256("REGISTRY_ADD_EXECUTOR_ROLE"); + bytes32 public constant REGISTRY_ADD_EXECUTOR_ROLE = 0xc4e90f38eea8c4212a009ca7b8947943ba4d4a58d19b683417f65291d1cd9ed2; + // WARN: Manager can censor all votes and the like happening in an org + // bytes32 public constant REGISTRY_MANAGER_ROLE = keccak256("REGISTRY_MANAGER_ROLE"); + bytes32 public constant REGISTRY_MANAGER_ROLE = 0xf7a450ef335e1892cb42c8ca72e7242359d7711924b75db5717410da3f614aa3; + + string private constant ERROR_INEXISTENT_EXECUTOR = "EVMREG_INEXISTENT_EXECUTOR"; + string private constant ERROR_EXECUTOR_ENABLED = "EVMREG_EXECUTOR_ENABLED"; + string private constant ERROR_EXECUTOR_DISABLED = "EVMREG_EXECUTOR_DISABLED"; + + struct ExecutorEntry { + IEVMScriptExecutor executor; + bool enabled; + } + + uint256 private executorsNextIndex; + mapping (uint256 => ExecutorEntry) public executors; + + event EnableExecutor(uint256 indexed executorId, address indexed executorAddress); + event DisableExecutor(uint256 indexed executorId, address indexed executorAddress); + + modifier executorExists(uint256 _executorId) { + require(_executorId >= 0 || _executorId < executorsNextIndex, ERROR_INEXISTENT_EXECUTOR); + _; + } + + /** + * @notice Initialize the registry + */ + function initialize() public onlyInit { + initialized(); + // Create empty record to begin executor IDs at 1 + executorsNextIndex = 1; + } + + /** + * @notice Add a new script executor with address `_executor` to the registry + * @param _executor Address of the IEVMScriptExecutor that will be added to the registry + * @return id Identifier of the executor in the registry + */ + function addScriptExecutor(IEVMScriptExecutor _executor) external auth(REGISTRY_ADD_EXECUTOR_ROLE) returns (uint256 id) { + uint256 executorId = executorsNextIndex++; + executors[executorId] = ExecutorEntry(_executor, true); + emit EnableExecutor(executorId, _executor); + return executorId; + } + + /** + * @notice Disable script executor with ID `_executorId` + * @param _executorId Identifier of the executor in the registry + */ + function disableScriptExecutor(uint256 _executorId) + external + authP(REGISTRY_MANAGER_ROLE, arr(_executorId)) + { + // Note that we don't need to check for an executor's existence in this case, as only + // existing executors can be enabled + ExecutorEntry storage executorEntry = executors[_executorId]; + require(executorEntry.enabled, ERROR_EXECUTOR_DISABLED); + executorEntry.enabled = false; + emit DisableExecutor(_executorId, executorEntry.executor); + } + + /** + * @notice Enable script executor with ID `_executorId` + * @param _executorId Identifier of the executor in the registry + */ + function enableScriptExecutor(uint256 _executorId) + external + authP(REGISTRY_MANAGER_ROLE, arr(_executorId)) + executorExists(_executorId) + { + ExecutorEntry storage executorEntry = executors[_executorId]; + require(!executorEntry.enabled, ERROR_EXECUTOR_ENABLED); + executorEntry.enabled = true; + emit EnableExecutor(_executorId, executorEntry.executor); + } + + /** + * @dev Get the script executor that can execute a particular script based on its first 4 bytes + * @param _script EVMScript being inspected + */ + function getScriptExecutor(bytes _script) public view returns (IEVMScriptExecutor) { + uint256 id = _script.getSpecId(); + + // Note that we don't need to check for an executor's existence in this case, as only + // existing executors can be enabled + ExecutorEntry storage entry = executors[id]; + return entry.enabled ? entry.executor : IEVMScriptExecutor(0); + } +} diff --git a/contracts/mutants/EVMScriptRegistry/2/DLR/EVMScriptRegistry.sol b/contracts/mutants/EVMScriptRegistry/2/DLR/EVMScriptRegistry.sol new file mode 100644 index 00000000000..9f16ca93a1b --- /dev/null +++ b/contracts/mutants/EVMScriptRegistry/2/DLR/EVMScriptRegistry.sol @@ -0,0 +1,104 @@ +pragma solidity 0.4.24; + +import "../apps/AragonApp.sol"; +import "./ScriptHelpers.sol"; +import "./IEVMScriptExecutor.sol"; +import "./IEVMScriptRegistry.sol"; + + +/* solium-disable function-order */ +// Allow public initialize() to be first +contract EVMScriptRegistry is IEVMScriptRegistry, EVMScriptRegistryConstants, AragonApp { + using ScriptHelpers for bytes; + + // bytes32 public constant REGISTRY_ADD_EXECUTOR_ROLE = keccak256("REGISTRY_ADD_EXECUTOR_ROLE"); + bytes32 public constant REGISTRY_ADD_EXECUTOR_ROLE = 0xc4e90f38eea8c4212a009ca7b8947943ba4d4a58d19b683417f65291d1cd9ed2; + // WARN: Manager can censor all votes and the like happening in an org + // bytes32 public constant REGISTRY_MANAGER_ROLE = keccak256("REGISTRY_MANAGER_ROLE"); + bytes32 public constant REGISTRY_MANAGER_ROLE = 0xf7a450ef335e1892cb42c8ca72e7242359d7711924b75db5717410da3f614aa3; + + string private constant ERROR_INEXISTENT_EXECUTOR = "EVMREG_INEXISTENT_EXECUTOR"; + string private constant ERROR_EXECUTOR_ENABLED = "EVMREG_EXECUTOR_ENABLED"; + string private constant ERROR_EXECUTOR_DISABLED = "EVMREG_EXECUTOR_DISABLED"; + + struct ExecutorEntry { + IEVMScriptExecutor executor; + bool enabled; + } + + uint256 private executorsNextIndex; + mapping (uint256 => ExecutorEntry) public executors; + + event EnableExecutor(uint256 indexed executorId, address indexed executorAddress); + event DisableExecutor(uint256 indexed executorId, address indexed executorAddress); + + modifier executorExists(uint256 _executorId) { + require(_executorId > 0 && _executorId < executorsNextIndex, ERROR_INEXISTENT_EXECUTOR); + _; + } + + /** + * @notice Initialize the registry + */ + function initialize() public onlyInit { + initialized(); + // Create empty record to begin executor IDs at 1 + executorsNextIndex = 1; + } + + /** + * @notice Add a new script executor with address `_executor` to the registry + * @param _executor Address of the IEVMScriptExecutor that will be added to the registry + * @return id Identifier of the executor in the registry + */ + function addScriptExecutor(IEVMScriptExecutor _executor) external auth(REGISTRY_ADD_EXECUTOR_ROLE) returns (uint256 id) { + uint256 executorId = executorsNextIndex++; + executors[executorId] = ExecutorEntry(_executor, true); + emit EnableExecutor(executorId, _executor); + return executorId; + } + + /** + * @notice Disable script executor with ID `_executorId` + * @param _executorId Identifier of the executor in the registry + */ + function disableScriptExecutor(uint256 _executorId) + external + authP(REGISTRY_MANAGER_ROLE, arr(_executorId)) + { + // Note that we don't need to check for an executor's existence in this case, as only + // existing executors can be enabled + ExecutorEntry memory executorEntry = executors[_executorId]; + require(executorEntry.enabled, ERROR_EXECUTOR_DISABLED); + executorEntry.enabled = false; + emit DisableExecutor(_executorId, executorEntry.executor); + } + + /** + * @notice Enable script executor with ID `_executorId` + * @param _executorId Identifier of the executor in the registry + */ + function enableScriptExecutor(uint256 _executorId) + external + authP(REGISTRY_MANAGER_ROLE, arr(_executorId)) + executorExists(_executorId) + { + ExecutorEntry memory executorEntry = executors[_executorId]; + require(!executorEntry.enabled, ERROR_EXECUTOR_ENABLED); + executorEntry.enabled = true; + emit EnableExecutor(_executorId, executorEntry.executor); + } + + /** + * @dev Get the script executor that can execute a particular script based on its first 4 bytes + * @param _script EVMScript being inspected + */ + function getScriptExecutor(bytes _script) public view returns (IEVMScriptExecutor) { + uint256 id = _script.getSpecId(); + + // Note that we don't need to check for an executor's existence in this case, as only + // existing executors can be enabled + ExecutorEntry storage entry = executors[id]; + return entry.enabled ? entry.executor : IEVMScriptExecutor(0); + } +} diff --git a/contracts/mutants/EVMScriptRegistry/2/EED/EVMScriptRegistry.sol b/contracts/mutants/EVMScriptRegistry/2/EED/EVMScriptRegistry.sol new file mode 100644 index 00000000000..8b6f731c494 --- /dev/null +++ b/contracts/mutants/EVMScriptRegistry/2/EED/EVMScriptRegistry.sol @@ -0,0 +1,104 @@ +pragma solidity 0.4.24; + +import "../apps/AragonApp.sol"; +import "./ScriptHelpers.sol"; +import "./IEVMScriptExecutor.sol"; +import "./IEVMScriptRegistry.sol"; + + +/* solium-disable function-order */ +// Allow public initialize() to be first +contract EVMScriptRegistry is IEVMScriptRegistry, EVMScriptRegistryConstants, AragonApp { + using ScriptHelpers for bytes; + + // bytes32 public constant REGISTRY_ADD_EXECUTOR_ROLE = keccak256("REGISTRY_ADD_EXECUTOR_ROLE"); + bytes32 public constant REGISTRY_ADD_EXECUTOR_ROLE = 0xc4e90f38eea8c4212a009ca7b8947943ba4d4a58d19b683417f65291d1cd9ed2; + // WARN: Manager can censor all votes and the like happening in an org + // bytes32 public constant REGISTRY_MANAGER_ROLE = keccak256("REGISTRY_MANAGER_ROLE"); + bytes32 public constant REGISTRY_MANAGER_ROLE = 0xf7a450ef335e1892cb42c8ca72e7242359d7711924b75db5717410da3f614aa3; + + string private constant ERROR_INEXISTENT_EXECUTOR = "EVMREG_INEXISTENT_EXECUTOR"; + string private constant ERROR_EXECUTOR_ENABLED = "EVMREG_EXECUTOR_ENABLED"; + string private constant ERROR_EXECUTOR_DISABLED = "EVMREG_EXECUTOR_DISABLED"; + + struct ExecutorEntry { + IEVMScriptExecutor executor; + bool enabled; + } + + uint256 private executorsNextIndex; + mapping (uint256 => ExecutorEntry) public executors; + + event EnableExecutor(uint256 indexed executorId, address indexed executorAddress); + event DisableExecutor(uint256 indexed executorId, address indexed executorAddress); + + modifier executorExists(uint256 _executorId) { + require(_executorId > 0 && _executorId < executorsNextIndex, ERROR_INEXISTENT_EXECUTOR); + _; + } + + /** + * @notice Initialize the registry + */ + function initialize() public onlyInit { + initialized(); + // Create empty record to begin executor IDs at 1 + executorsNextIndex = 1; + } + + /** + * @notice Add a new script executor with address `_executor` to the registry + * @param _executor Address of the IEVMScriptExecutor that will be added to the registry + * @return id Identifier of the executor in the registry + */ + function addScriptExecutor(IEVMScriptExecutor _executor) external auth(REGISTRY_ADD_EXECUTOR_ROLE) returns (uint256 id) { + uint256 executorId = executorsNextIndex++; + executors[executorId] = ExecutorEntry(_executor, true); + /* emit EnableExecutor(executorId, _executor); */ + return executorId; + } + + /** + * @notice Disable script executor with ID `_executorId` + * @param _executorId Identifier of the executor in the registry + */ + function disableScriptExecutor(uint256 _executorId) + external + authP(REGISTRY_MANAGER_ROLE, arr(_executorId)) + { + // Note that we don't need to check for an executor's existence in this case, as only + // existing executors can be enabled + ExecutorEntry storage executorEntry = executors[_executorId]; + require(executorEntry.enabled, ERROR_EXECUTOR_DISABLED); + executorEntry.enabled = false; + /* emit DisableExecutor(_executorId, executorEntry.executor); */ + } + + /** + * @notice Enable script executor with ID `_executorId` + * @param _executorId Identifier of the executor in the registry + */ + function enableScriptExecutor(uint256 _executorId) + external + authP(REGISTRY_MANAGER_ROLE, arr(_executorId)) + executorExists(_executorId) + { + ExecutorEntry storage executorEntry = executors[_executorId]; + require(!executorEntry.enabled, ERROR_EXECUTOR_ENABLED); + executorEntry.enabled = true; + emit EnableExecutor(_executorId, executorEntry.executor); + } + + /** + * @dev Get the script executor that can execute a particular script based on its first 4 bytes + * @param _script EVMScript being inspected + */ + function getScriptExecutor(bytes _script) public view returns (IEVMScriptExecutor) { + uint256 id = _script.getSpecId(); + + // Note that we don't need to check for an executor's existence in this case, as only + // existing executors can be enabled + ExecutorEntry storage entry = executors[id]; + return entry.enabled ? entry.executor : IEVMScriptExecutor(0); + } +} diff --git a/contracts/mutants/EVMScriptRegistry/2/EHC/EVMScriptRegistry.sol b/contracts/mutants/EVMScriptRegistry/2/EHC/EVMScriptRegistry.sol new file mode 100644 index 00000000000..37238e640a7 --- /dev/null +++ b/contracts/mutants/EVMScriptRegistry/2/EHC/EVMScriptRegistry.sol @@ -0,0 +1,104 @@ +pragma solidity 0.4.24; + +import "../apps/AragonApp.sol"; +import "./ScriptHelpers.sol"; +import "./IEVMScriptExecutor.sol"; +import "./IEVMScriptRegistry.sol"; + + +/* solium-disable function-order */ +// Allow public initialize() to be first +contract EVMScriptRegistry is IEVMScriptRegistry, EVMScriptRegistryConstants, AragonApp { + using ScriptHelpers for bytes; + + // bytes32 public constant REGISTRY_ADD_EXECUTOR_ROLE = keccak256("REGISTRY_ADD_EXECUTOR_ROLE"); + bytes32 public constant REGISTRY_ADD_EXECUTOR_ROLE = 0xc4e90f38eea8c4212a009ca7b8947943ba4d4a58d19b683417f65291d1cd9ed2; + // WARN: Manager can censor all votes and the like happening in an org + // bytes32 public constant REGISTRY_MANAGER_ROLE = keccak256("REGISTRY_MANAGER_ROLE"); + bytes32 public constant REGISTRY_MANAGER_ROLE = 0xf7a450ef335e1892cb42c8ca72e7242359d7711924b75db5717410da3f614aa3; + + string private constant ERROR_INEXISTENT_EXECUTOR = "EVMREG_INEXISTENT_EXECUTOR"; + string private constant ERROR_EXECUTOR_ENABLED = "EVMREG_EXECUTOR_ENABLED"; + string private constant ERROR_EXECUTOR_DISABLED = "EVMREG_EXECUTOR_DISABLED"; + + struct ExecutorEntry { + IEVMScriptExecutor executor; + bool enabled; + } + + uint256 private executorsNextIndex; + mapping (uint256 => ExecutorEntry) public executors; + + event EnableExecutor(uint256 indexed executorId, address indexed executorAddress); + event DisableExecutor(uint256 indexed executorId, address indexed executorAddress); + + modifier executorExists(uint256 _executorId) { + /* require(_executorId > 0 && _executorId < executorsNextIndex, ERROR_INEXISTENT_EXECUTOR); */ + _; + } + + /** + * @notice Initialize the registry + */ + function initialize() public onlyInit { + initialized(); + // Create empty record to begin executor IDs at 1 + executorsNextIndex = 1; + } + + /** + * @notice Add a new script executor with address `_executor` to the registry + * @param _executor Address of the IEVMScriptExecutor that will be added to the registry + * @return id Identifier of the executor in the registry + */ + function addScriptExecutor(IEVMScriptExecutor _executor) external auth(REGISTRY_ADD_EXECUTOR_ROLE) returns (uint256 id) { + uint256 executorId = executorsNextIndex++; + executors[executorId] = ExecutorEntry(_executor, true); + emit EnableExecutor(executorId, _executor); + return executorId; + } + + /** + * @notice Disable script executor with ID `_executorId` + * @param _executorId Identifier of the executor in the registry + */ + function disableScriptExecutor(uint256 _executorId) + external + authP(REGISTRY_MANAGER_ROLE, arr(_executorId)) + { + // Note that we don't need to check for an executor's existence in this case, as only + // existing executors can be enabled + ExecutorEntry storage executorEntry = executors[_executorId]; + /* require(executorEntry.enabled, ERROR_EXECUTOR_DISABLED); */ + executorEntry.enabled = false; + emit DisableExecutor(_executorId, executorEntry.executor); + } + + /** + * @notice Enable script executor with ID `_executorId` + * @param _executorId Identifier of the executor in the registry + */ + function enableScriptExecutor(uint256 _executorId) + external + authP(REGISTRY_MANAGER_ROLE, arr(_executorId)) + executorExists(_executorId) + { + ExecutorEntry storage executorEntry = executors[_executorId]; + require(!executorEntry.enabled, ERROR_EXECUTOR_ENABLED); + executorEntry.enabled = true; + emit EnableExecutor(_executorId, executorEntry.executor); + } + + /** + * @dev Get the script executor that can execute a particular script based on its first 4 bytes + * @param _script EVMScript being inspected + */ + function getScriptExecutor(bytes _script) public view returns (IEVMScriptExecutor) { + uint256 id = _script.getSpecId(); + + // Note that we don't need to check for an executor's existence in this case, as only + // existing executors can be enabled + ExecutorEntry storage entry = executors[id]; + return entry.enabled ? entry.executor : IEVMScriptExecutor(0); + } +} diff --git a/contracts/mutants/EVMScriptRegistry/2/FVR/EVMScriptRegistry.sol b/contracts/mutants/EVMScriptRegistry/2/FVR/EVMScriptRegistry.sol new file mode 100644 index 00000000000..774043e3f6f --- /dev/null +++ b/contracts/mutants/EVMScriptRegistry/2/FVR/EVMScriptRegistry.sol @@ -0,0 +1,104 @@ +pragma solidity 0.4.24; + +import "../apps/AragonApp.sol"; +import "./ScriptHelpers.sol"; +import "./IEVMScriptExecutor.sol"; +import "./IEVMScriptRegistry.sol"; + + +/* solium-disable function-order */ +// Allow public initialize() to be first +contract EVMScriptRegistry is IEVMScriptRegistry, EVMScriptRegistryConstants, AragonApp { + using ScriptHelpers for bytes; + + // bytes32 public constant REGISTRY_ADD_EXECUTOR_ROLE = keccak256("REGISTRY_ADD_EXECUTOR_ROLE"); + bytes32 public constant REGISTRY_ADD_EXECUTOR_ROLE = 0xc4e90f38eea8c4212a009ca7b8947943ba4d4a58d19b683417f65291d1cd9ed2; + // WARN: Manager can censor all votes and the like happening in an org + // bytes32 public constant REGISTRY_MANAGER_ROLE = keccak256("REGISTRY_MANAGER_ROLE"); + bytes32 public constant REGISTRY_MANAGER_ROLE = 0xf7a450ef335e1892cb42c8ca72e7242359d7711924b75db5717410da3f614aa3; + + string private constant ERROR_INEXISTENT_EXECUTOR = "EVMREG_INEXISTENT_EXECUTOR"; + string private constant ERROR_EXECUTOR_ENABLED = "EVMREG_EXECUTOR_ENABLED"; + string private constant ERROR_EXECUTOR_DISABLED = "EVMREG_EXECUTOR_DISABLED"; + + struct ExecutorEntry { + IEVMScriptExecutor executor; + bool enabled; + } + + uint256 private executorsNextIndex; + mapping (uint256 => ExecutorEntry) public executors; + + event EnableExecutor(uint256 indexed executorId, address indexed executorAddress); + event DisableExecutor(uint256 indexed executorId, address indexed executorAddress); + + modifier executorExists(uint256 _executorId) { + require(_executorId > 0 && _executorId < executorsNextIndex, ERROR_INEXISTENT_EXECUTOR); + _; + } + + /** + * @notice Initialize the registry + */ + function initialize() external onlyInit { + initialized(); + // Create empty record to begin executor IDs at 1 + executorsNextIndex = 1; + } + + /** + * @notice Add a new script executor with address `_executor` to the registry + * @param _executor Address of the IEVMScriptExecutor that will be added to the registry + * @return id Identifier of the executor in the registry + */ + function addScriptExecutor(IEVMScriptExecutor _executor) public auth(REGISTRY_ADD_EXECUTOR_ROLE) returns (uint256 id) { + uint256 executorId = executorsNextIndex++; + executors[executorId] = ExecutorEntry(_executor, true); + emit EnableExecutor(executorId, _executor); + return executorId; + } + + /** + * @notice Disable script executor with ID `_executorId` + * @param _executorId Identifier of the executor in the registry + */ + function disableScriptExecutor(uint256 _executorId) + external + authP(REGISTRY_MANAGER_ROLE, arr(_executorId)) + { + // Note that we don't need to check for an executor's existence in this case, as only + // existing executors can be enabled + ExecutorEntry storage executorEntry = executors[_executorId]; + require(executorEntry.enabled, ERROR_EXECUTOR_DISABLED); + executorEntry.enabled = false; + emit DisableExecutor(_executorId, executorEntry.executor); + } + + /** + * @notice Enable script executor with ID `_executorId` + * @param _executorId Identifier of the executor in the registry + */ + function enableScriptExecutor(uint256 _executorId) + external + authP(REGISTRY_MANAGER_ROLE, arr(_executorId)) + executorExists(_executorId) + { + ExecutorEntry storage executorEntry = executors[_executorId]; + require(!executorEntry.enabled, ERROR_EXECUTOR_ENABLED); + executorEntry.enabled = true; + emit EnableExecutor(_executorId, executorEntry.executor); + } + + /** + * @dev Get the script executor that can execute a particular script based on its first 4 bytes + * @param _script EVMScript being inspected + */ + function getScriptExecutor(bytes _script) public view returns (IEVMScriptExecutor) { + uint256 id = _script.getSpecId(); + + // Note that we don't need to check for an executor's existence in this case, as only + // existing executors can be enabled + ExecutorEntry storage entry = executors[id]; + return entry.enabled ? entry.executor : IEVMScriptExecutor(0); + } +} diff --git a/contracts/mutants/EVMScriptRegistry/2/ILR/EVMScriptRegistry.sol b/contracts/mutants/EVMScriptRegistry/2/ILR/EVMScriptRegistry.sol new file mode 100644 index 00000000000..a8b4ce6986d --- /dev/null +++ b/contracts/mutants/EVMScriptRegistry/2/ILR/EVMScriptRegistry.sol @@ -0,0 +1,104 @@ +pragma solidity 0.4.24; + +import "../apps/AragonApp.sol"; +import "./ScriptHelpers.sol"; +import "./IEVMScriptExecutor.sol"; +import "./IEVMScriptRegistry.sol"; + + +/* solium-disable function-order */ +// Allow public initialize() to be first +contract EVMScriptRegistry is IEVMScriptRegistry, EVMScriptRegistryConstants, AragonApp { + using ScriptHelpers for bytes; + + // bytes32 public constant REGISTRY_ADD_EXECUTOR_ROLE = keccak256("REGISTRY_ADD_EXECUTOR_ROLE"); + bytes32 public constant REGISTRY_ADD_EXECUTOR_ROLE = 0xc4e90f38eea8c4212a009ca7b8947943ba4d4a58d19b683417f65291d1cd9ed2; + // WARN: Manager can censor all votes and the like happening in an org + // bytes32 public constant REGISTRY_MANAGER_ROLE = keccak256("REGISTRY_MANAGER_ROLE"); + bytes32 public constant REGISTRY_MANAGER_ROLE = 0xf7a450ef335e1892cb42c8ca72e7242359d7711924b75db5717410da3f614aa3; + + string private constant ERROR_INEXISTENT_EXECUTOR = "EVMREG_INEXISTENT_EXECUTOR"; + string private constant ERROR_EXECUTOR_ENABLED = "EVMREG_EXECUTOR_ENABLED"; + string private constant ERROR_EXECUTOR_DISABLED = "EVMREG_EXECUTOR_DISABLED"; + + struct ExecutorEntry { + IEVMScriptExecutor executor; + bool enabled; + } + + uint256 private executorsNextIndex; + mapping (uint256 => ExecutorEntry) public executors; + + event EnableExecutor(uint256 indexed executorId, address indexed executorAddress); + event DisableExecutor(uint256 indexed executorId, address indexed executorAddress); + + modifier executorExists(uint256 _executorId) { + require(_executorId > 1 && _executorId < executorsNextIndex, ERROR_INEXISTENT_EXECUTOR); + _; + } + + /** + * @notice Initialize the registry + */ + function initialize() public onlyInit { + initialized(); + // Create empty record to begin executor IDs at 1 + executorsNextIndex = 0; + } + + /** + * @notice Add a new script executor with address `_executor` to the registry + * @param _executor Address of the IEVMScriptExecutor that will be added to the registry + * @return id Identifier of the executor in the registry + */ + function addScriptExecutor(IEVMScriptExecutor _executor) external auth(REGISTRY_ADD_EXECUTOR_ROLE) returns (uint256 id) { + uint256 executorId = executorsNextIndex++; + executors[executorId] = ExecutorEntry(_executor, true); + emit EnableExecutor(executorId, _executor); + return executorId; + } + + /** + * @notice Disable script executor with ID `_executorId` + * @param _executorId Identifier of the executor in the registry + */ + function disableScriptExecutor(uint256 _executorId) + external + authP(REGISTRY_MANAGER_ROLE, arr(_executorId)) + { + // Note that we don't need to check for an executor's existence in this case, as only + // existing executors can be enabled + ExecutorEntry storage executorEntry = executors[_executorId]; + require(executorEntry.enabled, ERROR_EXECUTOR_DISABLED); + executorEntry.enabled = false; + emit DisableExecutor(_executorId, executorEntry.executor); + } + + /** + * @notice Enable script executor with ID `_executorId` + * @param _executorId Identifier of the executor in the registry + */ + function enableScriptExecutor(uint256 _executorId) + external + authP(REGISTRY_MANAGER_ROLE, arr(_executorId)) + executorExists(_executorId) + { + ExecutorEntry storage executorEntry = executors[_executorId]; + require(!executorEntry.enabled, ERROR_EXECUTOR_ENABLED); + executorEntry.enabled = true; + emit EnableExecutor(_executorId, executorEntry.executor); + } + + /** + * @dev Get the script executor that can execute a particular script based on its first 4 bytes + * @param _script EVMScript being inspected + */ + function getScriptExecutor(bytes _script) public view returns (IEVMScriptExecutor) { + uint256 id = _script.getSpecId(); + + // Note that we don't need to check for an executor's existence in this case, as only + // existing executors can be enabled + ExecutorEntry storage entry = executors[id]; + return entry.enabled ? entry.executor : IEVMScriptExecutor(0); + } +} diff --git a/contracts/mutants/EVMScriptRegistry/2/MOD/EVMScriptRegistry.sol b/contracts/mutants/EVMScriptRegistry/2/MOD/EVMScriptRegistry.sol new file mode 100644 index 00000000000..797766983d6 --- /dev/null +++ b/contracts/mutants/EVMScriptRegistry/2/MOD/EVMScriptRegistry.sol @@ -0,0 +1,104 @@ +pragma solidity 0.4.24; + +import "../apps/AragonApp.sol"; +import "./ScriptHelpers.sol"; +import "./IEVMScriptExecutor.sol"; +import "./IEVMScriptRegistry.sol"; + + +/* solium-disable function-order */ +// Allow public initialize() to be first +contract EVMScriptRegistry is IEVMScriptRegistry, EVMScriptRegistryConstants, AragonApp { + using ScriptHelpers for bytes; + + // bytes32 public constant REGISTRY_ADD_EXECUTOR_ROLE = keccak256("REGISTRY_ADD_EXECUTOR_ROLE"); + bytes32 public constant REGISTRY_ADD_EXECUTOR_ROLE = 0xc4e90f38eea8c4212a009ca7b8947943ba4d4a58d19b683417f65291d1cd9ed2; + // WARN: Manager can censor all votes and the like happening in an org + // bytes32 public constant REGISTRY_MANAGER_ROLE = keccak256("REGISTRY_MANAGER_ROLE"); + bytes32 public constant REGISTRY_MANAGER_ROLE = 0xf7a450ef335e1892cb42c8ca72e7242359d7711924b75db5717410da3f614aa3; + + string private constant ERROR_INEXISTENT_EXECUTOR = "EVMREG_INEXISTENT_EXECUTOR"; + string private constant ERROR_EXECUTOR_ENABLED = "EVMREG_EXECUTOR_ENABLED"; + string private constant ERROR_EXECUTOR_DISABLED = "EVMREG_EXECUTOR_DISABLED"; + + struct ExecutorEntry { + IEVMScriptExecutor executor; + bool enabled; + } + + uint256 private executorsNextIndex; + mapping (uint256 => ExecutorEntry) public executors; + + event EnableExecutor(uint256 indexed executorId, address indexed executorAddress); + event DisableExecutor(uint256 indexed executorId, address indexed executorAddress); + + modifier executorExists(uint256 _executorId) { + require(_executorId > 0 && _executorId < executorsNextIndex, ERROR_INEXISTENT_EXECUTOR); + _; + } + + /** + * @notice Initialize the registry + */ + function initialize() public { + initialized(); + // Create empty record to begin executor IDs at 1 + executorsNextIndex = 1; + } + + /** + * @notice Add a new script executor with address `_executor` to the registry + * @param _executor Address of the IEVMScriptExecutor that will be added to the registry + * @return id Identifier of the executor in the registry + */ + function addScriptExecutor(IEVMScriptExecutor _executor) external returns (uint256 id) { + uint256 executorId = executorsNextIndex++; + executors[executorId] = ExecutorEntry(_executor, true); + emit EnableExecutor(executorId, _executor); + return executorId; + } + + /** + * @notice Disable script executor with ID `_executorId` + * @param _executorId Identifier of the executor in the registry + */ + function disableScriptExecutor(uint256 _executorId) + external + authP(REGISTRY_MANAGER_ROLE, arr(_executorId)) + { + // Note that we don't need to check for an executor's existence in this case, as only + // existing executors can be enabled + ExecutorEntry storage executorEntry = executors[_executorId]; + require(executorEntry.enabled, ERROR_EXECUTOR_DISABLED); + executorEntry.enabled = false; + emit DisableExecutor(_executorId, executorEntry.executor); + } + + /** + * @notice Enable script executor with ID `_executorId` + * @param _executorId Identifier of the executor in the registry + */ + function enableScriptExecutor(uint256 _executorId) + external + authP(REGISTRY_MANAGER_ROLE, arr(_executorId)) + executorExists(_executorId) + { + ExecutorEntry storage executorEntry = executors[_executorId]; + require(!executorEntry.enabled, ERROR_EXECUTOR_ENABLED); + executorEntry.enabled = true; + emit EnableExecutor(_executorId, executorEntry.executor); + } + + /** + * @dev Get the script executor that can execute a particular script based on its first 4 bytes + * @param _script EVMScript being inspected + */ + function getScriptExecutor(bytes _script) public view returns (IEVMScriptExecutor) { + uint256 id = _script.getSpecId(); + + // Note that we don't need to check for an executor's existence in this case, as only + // existing executors can be enabled + ExecutorEntry storage entry = executors[id]; + return entry.enabled ? entry.executor : IEVMScriptExecutor(0); + } +} diff --git a/contracts/mutants/EVMScriptRegistry/2/MOR/EVMScriptRegistry.sol b/contracts/mutants/EVMScriptRegistry/2/MOR/EVMScriptRegistry.sol new file mode 100644 index 00000000000..05503570266 --- /dev/null +++ b/contracts/mutants/EVMScriptRegistry/2/MOR/EVMScriptRegistry.sol @@ -0,0 +1,104 @@ +pragma solidity 0.4.24; + +import "../apps/AragonApp.sol"; +import "./ScriptHelpers.sol"; +import "./IEVMScriptExecutor.sol"; +import "./IEVMScriptRegistry.sol"; + + +/* solium-disable function-order */ +// Allow public initialize() to be first +contract EVMScriptRegistry is IEVMScriptRegistry, EVMScriptRegistryConstants, AragonApp { + using ScriptHelpers for bytes; + + // bytes32 public constant REGISTRY_ADD_EXECUTOR_ROLE = keccak256("REGISTRY_ADD_EXECUTOR_ROLE"); + bytes32 public constant REGISTRY_ADD_EXECUTOR_ROLE = 0xc4e90f38eea8c4212a009ca7b8947943ba4d4a58d19b683417f65291d1cd9ed2; + // WARN: Manager can censor all votes and the like happening in an org + // bytes32 public constant REGISTRY_MANAGER_ROLE = keccak256("REGISTRY_MANAGER_ROLE"); + bytes32 public constant REGISTRY_MANAGER_ROLE = 0xf7a450ef335e1892cb42c8ca72e7242359d7711924b75db5717410da3f614aa3; + + string private constant ERROR_INEXISTENT_EXECUTOR = "EVMREG_INEXISTENT_EXECUTOR"; + string private constant ERROR_EXECUTOR_ENABLED = "EVMREG_EXECUTOR_ENABLED"; + string private constant ERROR_EXECUTOR_DISABLED = "EVMREG_EXECUTOR_DISABLED"; + + struct ExecutorEntry { + IEVMScriptExecutor executor; + bool enabled; + } + + uint256 private executorsNextIndex; + mapping (uint256 => ExecutorEntry) public executors; + + event EnableExecutor(uint256 indexed executorId, address indexed executorAddress); + event DisableExecutor(uint256 indexed executorId, address indexed executorAddress); + + modifier executorExists(uint256 _executorId) { + require(_executorId > 0 && _executorId < executorsNextIndex, ERROR_INEXISTENT_EXECUTOR); + _; + } + + /** + * @notice Initialize the registry + */ + function initialize() public onlyInit { + initialized(); + // Create empty record to begin executor IDs at 1 + executorsNextIndex = 1; + } + + /** + * @notice Add a new script executor with address `_executor` to the registry + * @param _executor Address of the IEVMScriptExecutor that will be added to the registry + * @return id Identifier of the executor in the registry + */ + function addScriptExecutor(IEVMScriptExecutor _executor) external onlyInit returns (uint256 id) { + uint256 executorId = executorsNextIndex++; + executors[executorId] = ExecutorEntry(_executor, true); + emit EnableExecutor(executorId, _executor); + return executorId; + } + + /** + * @notice Disable script executor with ID `_executorId` + * @param _executorId Identifier of the executor in the registry + */ + function disableScriptExecutor(uint256 _executorId) + external + onlyInit + { + // Note that we don't need to check for an executor's existence in this case, as only + // existing executors can be enabled + ExecutorEntry storage executorEntry = executors[_executorId]; + require(executorEntry.enabled, ERROR_EXECUTOR_DISABLED); + executorEntry.enabled = false; + emit DisableExecutor(_executorId, executorEntry.executor); + } + + /** + * @notice Enable script executor with ID `_executorId` + * @param _executorId Identifier of the executor in the registry + */ + function enableScriptExecutor(uint256 _executorId) + external + authP(REGISTRY_MANAGER_ROLE, arr(_executorId)) + executorExists(_executorId) + { + ExecutorEntry storage executorEntry = executors[_executorId]; + require(!executorEntry.enabled, ERROR_EXECUTOR_ENABLED); + executorEntry.enabled = true; + emit EnableExecutor(_executorId, executorEntry.executor); + } + + /** + * @dev Get the script executor that can execute a particular script based on its first 4 bytes + * @param _script EVMScript being inspected + */ + function getScriptExecutor(bytes _script) public view returns (IEVMScriptExecutor) { + uint256 id = _script.getSpecId(); + + // Note that we don't need to check for an executor's existence in this case, as only + // existing executors can be enabled + ExecutorEntry storage entry = executors[id]; + return entry.enabled ? entry.executor : IEVMScriptExecutor(0); + } +} diff --git a/contracts/mutants/EVMScriptRegistry/2/RSD/EVMScriptRegistry.sol b/contracts/mutants/EVMScriptRegistry/2/RSD/EVMScriptRegistry.sol new file mode 100644 index 00000000000..9190391f615 --- /dev/null +++ b/contracts/mutants/EVMScriptRegistry/2/RSD/EVMScriptRegistry.sol @@ -0,0 +1,104 @@ +pragma solidity 0.4.24; + +import "../apps/AragonApp.sol"; +import "./ScriptHelpers.sol"; +import "./IEVMScriptExecutor.sol"; +import "./IEVMScriptRegistry.sol"; + + +/* solium-disable function-order */ +// Allow public initialize() to be first +contract EVMScriptRegistry is IEVMScriptRegistry, EVMScriptRegistryConstants, AragonApp { + using ScriptHelpers for bytes; + + // bytes32 public constant REGISTRY_ADD_EXECUTOR_ROLE = keccak256("REGISTRY_ADD_EXECUTOR_ROLE"); + bytes32 public constant REGISTRY_ADD_EXECUTOR_ROLE = 0xc4e90f38eea8c4212a009ca7b8947943ba4d4a58d19b683417f65291d1cd9ed2; + // WARN: Manager can censor all votes and the like happening in an org + // bytes32 public constant REGISTRY_MANAGER_ROLE = keccak256("REGISTRY_MANAGER_ROLE"); + bytes32 public constant REGISTRY_MANAGER_ROLE = 0xf7a450ef335e1892cb42c8ca72e7242359d7711924b75db5717410da3f614aa3; + + string private constant ERROR_INEXISTENT_EXECUTOR = "EVMREG_INEXISTENT_EXECUTOR"; + string private constant ERROR_EXECUTOR_ENABLED = "EVMREG_EXECUTOR_ENABLED"; + string private constant ERROR_EXECUTOR_DISABLED = "EVMREG_EXECUTOR_DISABLED"; + + struct ExecutorEntry { + IEVMScriptExecutor executor; + bool enabled; + } + + uint256 private executorsNextIndex; + mapping (uint256 => ExecutorEntry) public executors; + + event EnableExecutor(uint256 indexed executorId, address indexed executorAddress); + event DisableExecutor(uint256 indexed executorId, address indexed executorAddress); + + modifier executorExists(uint256 _executorId) { + require(_executorId > 0 && _executorId < executorsNextIndex, ERROR_INEXISTENT_EXECUTOR); + _; + } + + /** + * @notice Initialize the registry + */ + function initialize() public onlyInit { + initialized(); + // Create empty record to begin executor IDs at 1 + executorsNextIndex = 1; + } + + /** + * @notice Add a new script executor with address `_executor` to the registry + * @param _executor Address of the IEVMScriptExecutor that will be added to the registry + * @return id Identifier of the executor in the registry + */ + function addScriptExecutor(IEVMScriptExecutor _executor) external auth(REGISTRY_ADD_EXECUTOR_ROLE) returns (uint256 id) { + uint256 executorId = executorsNextIndex++; + executors[executorId] = ExecutorEntry(_executor, true); + emit EnableExecutor(executorId, _executor); + /* return executorId; */ + } + + /** + * @notice Disable script executor with ID `_executorId` + * @param _executorId Identifier of the executor in the registry + */ + function disableScriptExecutor(uint256 _executorId) + external + authP(REGISTRY_MANAGER_ROLE, arr(_executorId)) + { + // Note that we don't need to check for an executor's existence in this case, as only + // existing executors can be enabled + ExecutorEntry storage executorEntry = executors[_executorId]; + require(executorEntry.enabled, ERROR_EXECUTOR_DISABLED); + executorEntry.enabled = false; + emit DisableExecutor(_executorId, executorEntry.executor); + } + + /** + * @notice Enable script executor with ID `_executorId` + * @param _executorId Identifier of the executor in the registry + */ + function enableScriptExecutor(uint256 _executorId) + external + authP(REGISTRY_MANAGER_ROLE, arr(_executorId)) + executorExists(_executorId) + { + ExecutorEntry storage executorEntry = executors[_executorId]; + require(!executorEntry.enabled, ERROR_EXECUTOR_ENABLED); + executorEntry.enabled = true; + emit EnableExecutor(_executorId, executorEntry.executor); + } + + /** + * @dev Get the script executor that can execute a particular script based on its first 4 bytes + * @param _script EVMScript being inspected + */ + function getScriptExecutor(bytes _script) public view returns (IEVMScriptExecutor) { + uint256 id = _script.getSpecId(); + + // Note that we don't need to check for an executor's existence in this case, as only + // existing executors can be enabled + ExecutorEntry storage entry = executors[id]; + /* return entry.enabled ? entry.executor : IEVMScriptExecutor(0); */ + } +} diff --git a/contracts/mutants/EVMScriptRegistry/2/SLR/EVMScriptRegistry.sol b/contracts/mutants/EVMScriptRegistry/2/SLR/EVMScriptRegistry.sol new file mode 100644 index 00000000000..55a2aa8fa19 --- /dev/null +++ b/contracts/mutants/EVMScriptRegistry/2/SLR/EVMScriptRegistry.sol @@ -0,0 +1,104 @@ +pragma solidity 0.4.24; + +import "../apps/AragonApp.sol"; +import "./ScriptHelpers.sol"; +import "./IEVMScriptExecutor.sol"; +import "./IEVMScriptRegistry.sol"; + + +/* solium-disable function-order */ +// Allow public initialize() to be first +contract EVMScriptRegistry is IEVMScriptRegistry, EVMScriptRegistryConstants, AragonApp { + using ScriptHelpers for bytes; + + // bytes32 public constant REGISTRY_ADD_EXECUTOR_ROLE = keccak256("REGISTRY_ADD_EXECUTOR_ROLE"); + bytes32 public constant REGISTRY_ADD_EXECUTOR_ROLE = 0xc4e90f38eea8c4212a009ca7b8947943ba4d4a58d19b683417f65291d1cd9ed2; + // WARN: Manager can censor all votes and the like happening in an org + // bytes32 public constant REGISTRY_MANAGER_ROLE = keccak256("REGISTRY_MANAGER_ROLE"); + bytes32 public constant REGISTRY_MANAGER_ROLE = 0xf7a450ef335e1892cb42c8ca72e7242359d7711924b75db5717410da3f614aa3; + + string private constant ERROR_INEXISTENT_EXECUTOR = ""; + string private constant ERROR_EXECUTOR_ENABLED = ""; + string private constant ERROR_EXECUTOR_DISABLED = "EVMREG_EXECUTOR_DISABLED"; + + struct ExecutorEntry { + IEVMScriptExecutor executor; + bool enabled; + } + + uint256 private executorsNextIndex; + mapping (uint256 => ExecutorEntry) public executors; + + event EnableExecutor(uint256 indexed executorId, address indexed executorAddress); + event DisableExecutor(uint256 indexed executorId, address indexed executorAddress); + + modifier executorExists(uint256 _executorId) { + require(_executorId > 0 && _executorId < executorsNextIndex, ERROR_INEXISTENT_EXECUTOR); + _; + } + + /** + * @notice Initialize the registry + */ + function initialize() public onlyInit { + initialized(); + // Create empty record to begin executor IDs at 1 + executorsNextIndex = 1; + } + + /** + * @notice Add a new script executor with address `_executor` to the registry + * @param _executor Address of the IEVMScriptExecutor that will be added to the registry + * @return id Identifier of the executor in the registry + */ + function addScriptExecutor(IEVMScriptExecutor _executor) external auth(REGISTRY_ADD_EXECUTOR_ROLE) returns (uint256 id) { + uint256 executorId = executorsNextIndex++; + executors[executorId] = ExecutorEntry(_executor, true); + emit EnableExecutor(executorId, _executor); + return executorId; + } + + /** + * @notice Disable script executor with ID `_executorId` + * @param _executorId Identifier of the executor in the registry + */ + function disableScriptExecutor(uint256 _executorId) + external + authP(REGISTRY_MANAGER_ROLE, arr(_executorId)) + { + // Note that we don't need to check for an executor's existence in this case, as only + // existing executors can be enabled + ExecutorEntry storage executorEntry = executors[_executorId]; + require(executorEntry.enabled, ERROR_EXECUTOR_DISABLED); + executorEntry.enabled = false; + emit DisableExecutor(_executorId, executorEntry.executor); + } + + /** + * @notice Enable script executor with ID `_executorId` + * @param _executorId Identifier of the executor in the registry + */ + function enableScriptExecutor(uint256 _executorId) + external + authP(REGISTRY_MANAGER_ROLE, arr(_executorId)) + executorExists(_executorId) + { + ExecutorEntry storage executorEntry = executors[_executorId]; + require(!executorEntry.enabled, ERROR_EXECUTOR_ENABLED); + executorEntry.enabled = true; + emit EnableExecutor(_executorId, executorEntry.executor); + } + + /** + * @dev Get the script executor that can execute a particular script based on its first 4 bytes + * @param _script EVMScript being inspected + */ + function getScriptExecutor(bytes _script) public view returns (IEVMScriptExecutor) { + uint256 id = _script.getSpecId(); + + // Note that we don't need to check for an executor's existence in this case, as only + // existing executors can be enabled + ExecutorEntry storage entry = executors[id]; + return entry.enabled ? entry.executor : IEVMScriptExecutor(0); + } +} diff --git a/contracts/mutants/EVMScriptRegistry/2/UORD/EVMScriptRegistry.sol b/contracts/mutants/EVMScriptRegistry/2/UORD/EVMScriptRegistry.sol new file mode 100644 index 00000000000..ad7188c7b8a --- /dev/null +++ b/contracts/mutants/EVMScriptRegistry/2/UORD/EVMScriptRegistry.sol @@ -0,0 +1,104 @@ +pragma solidity 0.4.24; + +import "../apps/AragonApp.sol"; +import "./ScriptHelpers.sol"; +import "./IEVMScriptExecutor.sol"; +import "./IEVMScriptRegistry.sol"; + + +/* solium-disable function-order */ +// Allow public initialize() to be first +contract EVMScriptRegistry is IEVMScriptRegistry, EVMScriptRegistryConstants, AragonApp { + using ScriptHelpers for bytes; + + // bytes32 public constant REGISTRY_ADD_EXECUTOR_ROLE = keccak256("REGISTRY_ADD_EXECUTOR_ROLE"); + bytes32 public constant REGISTRY_ADD_EXECUTOR_ROLE = 0xc4e90f38eea8c4212a009ca7b8947943ba4d4a58d19b683417f65291d1cd9ed2; + // WARN: Manager can censor all votes and the like happening in an org + // bytes32 public constant REGISTRY_MANAGER_ROLE = keccak256("REGISTRY_MANAGER_ROLE"); + bytes32 public constant REGISTRY_MANAGER_ROLE = 0xf7a450ef335e1892cb42c8ca72e7242359d7711924b75db5717410da3f614aa3; + + string private constant ERROR_INEXISTENT_EXECUTOR = "EVMREG_INEXISTENT_EXECUTOR"; + string private constant ERROR_EXECUTOR_ENABLED = "EVMREG_EXECUTOR_ENABLED"; + string private constant ERROR_EXECUTOR_DISABLED = "EVMREG_EXECUTOR_DISABLED"; + + struct ExecutorEntry { + IEVMScriptExecutor executor; + bool enabled; + } + + uint256 private executorsNextIndex; + mapping (uint256 => ExecutorEntry) public executors; + + event EnableExecutor(uint256 indexed executorId, address indexed executorAddress); + event DisableExecutor(uint256 indexed executorId, address indexed executorAddress); + + modifier executorExists(uint256 _executorId) { + require(_executorId > 0 && _executorId < executorsNextIndex, ERROR_INEXISTENT_EXECUTOR); + _; + } + + /** + * @notice Initialize the registry + */ + function initialize() public onlyInit { + initialized(); + // Create empty record to begin executor IDs at 1 + executorsNextIndex = 1; + } + + /** + * @notice Add a new script executor with address `_executor` to the registry + * @param _executor Address of the IEVMScriptExecutor that will be added to the registry + * @return id Identifier of the executor in the registry + */ + function addScriptExecutor(IEVMScriptExecutor _executor) external auth(REGISTRY_ADD_EXECUTOR_ROLE) returns (uint256 id) { + uint256 executorId = executorsNextIndex--; + executors[executorId] = ExecutorEntry(_executor, true); + emit EnableExecutor(executorId, _executor); + return executorId; + } + + /** + * @notice Disable script executor with ID `_executorId` + * @param _executorId Identifier of the executor in the registry + */ + function disableScriptExecutor(uint256 _executorId) + external + authP(REGISTRY_MANAGER_ROLE, arr(_executorId)) + { + // Note that we don't need to check for an executor's existence in this case, as only + // existing executors can be enabled + ExecutorEntry storage executorEntry = executors[_executorId]; + require(executorEntry.enabled, ERROR_EXECUTOR_DISABLED); + executorEntry.enabled = false; + emit DisableExecutor(_executorId, executorEntry.executor); + } + + /** + * @notice Enable script executor with ID `_executorId` + * @param _executorId Identifier of the executor in the registry + */ + function enableScriptExecutor(uint256 _executorId) + external + authP(REGISTRY_MANAGER_ROLE, arr(_executorId)) + executorExists(_executorId) + { + ExecutorEntry storage executorEntry = executors[_executorId]; + require( executorEntry.enabled, ERROR_EXECUTOR_ENABLED); + executorEntry.enabled = true; + emit EnableExecutor(_executorId, executorEntry.executor); + } + + /** + * @dev Get the script executor that can execute a particular script based on its first 4 bytes + * @param _script EVMScript being inspected + */ + function getScriptExecutor(bytes _script) public view returns (IEVMScriptExecutor) { + uint256 id = _script.getSpecId(); + + // Note that we don't need to check for an executor's existence in this case, as only + // existing executors can be enabled + ExecutorEntry storage entry = executors[id]; + return entry.enabled ? entry.executor : IEVMScriptExecutor(0); + } +} diff --git a/contracts/mutants/EVMScriptRegistry/2/VVR/EVMScriptRegistry.sol b/contracts/mutants/EVMScriptRegistry/2/VVR/EVMScriptRegistry.sol new file mode 100644 index 00000000000..8f177639e8f --- /dev/null +++ b/contracts/mutants/EVMScriptRegistry/2/VVR/EVMScriptRegistry.sol @@ -0,0 +1,104 @@ +pragma solidity 0.4.24; + +import "../apps/AragonApp.sol"; +import "./ScriptHelpers.sol"; +import "./IEVMScriptExecutor.sol"; +import "./IEVMScriptRegistry.sol"; + + +/* solium-disable function-order */ +// Allow public initialize() to be first +contract EVMScriptRegistry is IEVMScriptRegistry, EVMScriptRegistryConstants, AragonApp { + using ScriptHelpers for bytes; + + // bytes32 public constant REGISTRY_ADD_EXECUTOR_ROLE = keccak256("REGISTRY_ADD_EXECUTOR_ROLE"); + bytes32 internal constant REGISTRY_ADD_EXECUTOR_ROLE = 0xc4e90f38eea8c4212a009ca7b8947943ba4d4a58d19b683417f65291d1cd9ed2; + // WARN: Manager can censor all votes and the like happening in an org + // bytes32 public constant REGISTRY_MANAGER_ROLE = keccak256("REGISTRY_MANAGER_ROLE"); + bytes32 internal constant REGISTRY_MANAGER_ROLE = 0xf7a450ef335e1892cb42c8ca72e7242359d7711924b75db5717410da3f614aa3; + + string private constant ERROR_INEXISTENT_EXECUTOR = "EVMREG_INEXISTENT_EXECUTOR"; + string private constant ERROR_EXECUTOR_ENABLED = "EVMREG_EXECUTOR_ENABLED"; + string private constant ERROR_EXECUTOR_DISABLED = "EVMREG_EXECUTOR_DISABLED"; + + struct ExecutorEntry { + IEVMScriptExecutor executor; + bool enabled; + } + + uint256 private executorsNextIndex; + mapping (uint256 => ExecutorEntry) public executors; + + event EnableExecutor(uint256 indexed executorId, address indexed executorAddress); + event DisableExecutor(uint256 indexed executorId, address indexed executorAddress); + + modifier executorExists(uint256 _executorId) { + require(_executorId > 0 && _executorId < executorsNextIndex, ERROR_INEXISTENT_EXECUTOR); + _; + } + + /** + * @notice Initialize the registry + */ + function initialize() public onlyInit { + initialized(); + // Create empty record to begin executor IDs at 1 + executorsNextIndex = 1; + } + + /** + * @notice Add a new script executor with address `_executor` to the registry + * @param _executor Address of the IEVMScriptExecutor that will be added to the registry + * @return id Identifier of the executor in the registry + */ + function addScriptExecutor(IEVMScriptExecutor _executor) external auth(REGISTRY_ADD_EXECUTOR_ROLE) returns (uint256 id) { + uint256 executorId = executorsNextIndex++; + executors[executorId] = ExecutorEntry(_executor, true); + emit EnableExecutor(executorId, _executor); + return executorId; + } + + /** + * @notice Disable script executor with ID `_executorId` + * @param _executorId Identifier of the executor in the registry + */ + function disableScriptExecutor(uint256 _executorId) + external + authP(REGISTRY_MANAGER_ROLE, arr(_executorId)) + { + // Note that we don't need to check for an executor's existence in this case, as only + // existing executors can be enabled + ExecutorEntry storage executorEntry = executors[_executorId]; + require(executorEntry.enabled, ERROR_EXECUTOR_DISABLED); + executorEntry.enabled = false; + emit DisableExecutor(_executorId, executorEntry.executor); + } + + /** + * @notice Enable script executor with ID `_executorId` + * @param _executorId Identifier of the executor in the registry + */ + function enableScriptExecutor(uint256 _executorId) + external + authP(REGISTRY_MANAGER_ROLE, arr(_executorId)) + executorExists(_executorId) + { + ExecutorEntry storage executorEntry = executors[_executorId]; + require(!executorEntry.enabled, ERROR_EXECUTOR_ENABLED); + executorEntry.enabled = true; + emit EnableExecutor(_executorId, executorEntry.executor); + } + + /** + * @dev Get the script executor that can execute a particular script based on its first 4 bytes + * @param _script EVMScript being inspected + */ + function getScriptExecutor(bytes _script) public view returns (IEVMScriptExecutor) { + uint256 id = _script.getSpecId(); + + // Note that we don't need to check for an executor's existence in this case, as only + // existing executors can be enabled + ExecutorEntry storage entry = executors[id]; + return entry.enabled ? entry.executor : IEVMScriptExecutor(0); + } +} diff --git a/contracts/mutants/EVMScriptRegistry/3/BLR/EVMScriptRegistry.sol b/contracts/mutants/EVMScriptRegistry/3/BLR/EVMScriptRegistry.sol new file mode 100644 index 00000000000..772302ab8da --- /dev/null +++ b/contracts/mutants/EVMScriptRegistry/3/BLR/EVMScriptRegistry.sol @@ -0,0 +1,104 @@ +pragma solidity 0.4.24; + +import "../apps/AragonApp.sol"; +import "./ScriptHelpers.sol"; +import "./IEVMScriptExecutor.sol"; +import "./IEVMScriptRegistry.sol"; + + +/* solium-disable function-order */ +// Allow public initialize() to be first +contract EVMScriptRegistry is IEVMScriptRegistry, EVMScriptRegistryConstants, AragonApp { + using ScriptHelpers for bytes; + + // bytes32 public constant REGISTRY_ADD_EXECUTOR_ROLE = keccak256("REGISTRY_ADD_EXECUTOR_ROLE"); + bytes32 public constant REGISTRY_ADD_EXECUTOR_ROLE = 0xc4e90f38eea8c4212a009ca7b8947943ba4d4a58d19b683417f65291d1cd9ed2; + // WARN: Manager can censor all votes and the like happening in an org + // bytes32 public constant REGISTRY_MANAGER_ROLE = keccak256("REGISTRY_MANAGER_ROLE"); + bytes32 public constant REGISTRY_MANAGER_ROLE = 0xf7a450ef335e1892cb42c8ca72e7242359d7711924b75db5717410da3f614aa3; + + string private constant ERROR_INEXISTENT_EXECUTOR = "EVMREG_INEXISTENT_EXECUTOR"; + string private constant ERROR_EXECUTOR_ENABLED = "EVMREG_EXECUTOR_ENABLED"; + string private constant ERROR_EXECUTOR_DISABLED = "EVMREG_EXECUTOR_DISABLED"; + + struct ExecutorEntry { + IEVMScriptExecutor executor; + bool enabled; + } + + uint256 private executorsNextIndex; + mapping (uint256 => ExecutorEntry) public executors; + + event EnableExecutor(uint256 indexed executorId, address indexed executorAddress); + event DisableExecutor(uint256 indexed executorId, address indexed executorAddress); + + modifier executorExists(uint256 _executorId) { + require(_executorId > 0 && _executorId < executorsNextIndex, ERROR_INEXISTENT_EXECUTOR); + _; + } + + /** + * @notice Initialize the registry + */ + function initialize() public onlyInit { + initialized(); + // Create empty record to begin executor IDs at 1 + executorsNextIndex = 1; + } + + /** + * @notice Add a new script executor with address `_executor` to the registry + * @param _executor Address of the IEVMScriptExecutor that will be added to the registry + * @return id Identifier of the executor in the registry + */ + function addScriptExecutor(IEVMScriptExecutor _executor) external auth(REGISTRY_ADD_EXECUTOR_ROLE) returns (uint256 id) { + uint256 executorId = executorsNextIndex++; + executors[executorId] = ExecutorEntry(_executor, false); + emit EnableExecutor(executorId, _executor); + return executorId; + } + + /** + * @notice Disable script executor with ID `_executorId` + * @param _executorId Identifier of the executor in the registry + */ + function disableScriptExecutor(uint256 _executorId) + external + authP(REGISTRY_MANAGER_ROLE, arr(_executorId)) + { + // Note that we don't need to check for an executor's existence in this case, as only + // existing executors can be enabled + ExecutorEntry storage executorEntry = executors[_executorId]; + require(executorEntry.enabled, ERROR_EXECUTOR_DISABLED); + executorEntry.enabled = true; + emit DisableExecutor(_executorId, executorEntry.executor); + } + + /** + * @notice Enable script executor with ID `_executorId` + * @param _executorId Identifier of the executor in the registry + */ + function enableScriptExecutor(uint256 _executorId) + external + authP(REGISTRY_MANAGER_ROLE, arr(_executorId)) + executorExists(_executorId) + { + ExecutorEntry storage executorEntry = executors[_executorId]; + require(!executorEntry.enabled, ERROR_EXECUTOR_ENABLED); + executorEntry.enabled = false; + emit EnableExecutor(_executorId, executorEntry.executor); + } + + /** + * @dev Get the script executor that can execute a particular script based on its first 4 bytes + * @param _script EVMScript being inspected + */ + function getScriptExecutor(bytes _script) public view returns (IEVMScriptExecutor) { + uint256 id = _script.getSpecId(); + + // Note that we don't need to check for an executor's existence in this case, as only + // existing executors can be enabled + ExecutorEntry storage entry = executors[id]; + return entry.enabled ? entry.executor : IEVMScriptExecutor(0); + } +} diff --git a/contracts/mutants/EVMScriptRegistry/3/BOR/EVMScriptRegistry.sol b/contracts/mutants/EVMScriptRegistry/3/BOR/EVMScriptRegistry.sol new file mode 100644 index 00000000000..7926e0fa708 --- /dev/null +++ b/contracts/mutants/EVMScriptRegistry/3/BOR/EVMScriptRegistry.sol @@ -0,0 +1,104 @@ +pragma solidity 0.4.24; + +import "../apps/AragonApp.sol"; +import "./ScriptHelpers.sol"; +import "./IEVMScriptExecutor.sol"; +import "./IEVMScriptRegistry.sol"; + + +/* solium-disable function-order */ +// Allow public initialize() to be first +contract EVMScriptRegistry is IEVMScriptRegistry, EVMScriptRegistryConstants, AragonApp { + using ScriptHelpers for bytes; + + // bytes32 public constant REGISTRY_ADD_EXECUTOR_ROLE = keccak256("REGISTRY_ADD_EXECUTOR_ROLE"); + bytes32 public constant REGISTRY_ADD_EXECUTOR_ROLE = 0xc4e90f38eea8c4212a009ca7b8947943ba4d4a58d19b683417f65291d1cd9ed2; + // WARN: Manager can censor all votes and the like happening in an org + // bytes32 public constant REGISTRY_MANAGER_ROLE = keccak256("REGISTRY_MANAGER_ROLE"); + bytes32 public constant REGISTRY_MANAGER_ROLE = 0xf7a450ef335e1892cb42c8ca72e7242359d7711924b75db5717410da3f614aa3; + + string private constant ERROR_INEXISTENT_EXECUTOR = "EVMREG_INEXISTENT_EXECUTOR"; + string private constant ERROR_EXECUTOR_ENABLED = "EVMREG_EXECUTOR_ENABLED"; + string private constant ERROR_EXECUTOR_DISABLED = "EVMREG_EXECUTOR_DISABLED"; + + struct ExecutorEntry { + IEVMScriptExecutor executor; + bool enabled; + } + + uint256 private executorsNextIndex; + mapping (uint256 => ExecutorEntry) public executors; + + event EnableExecutor(uint256 indexed executorId, address indexed executorAddress); + event DisableExecutor(uint256 indexed executorId, address indexed executorAddress); + + modifier executorExists(uint256 _executorId) { + require(_executorId >= 0 || _executorId <= executorsNextIndex, ERROR_INEXISTENT_EXECUTOR); + _; + } + + /** + * @notice Initialize the registry + */ + function initialize() public onlyInit { + initialized(); + // Create empty record to begin executor IDs at 1 + executorsNextIndex = 1; + } + + /** + * @notice Add a new script executor with address `_executor` to the registry + * @param _executor Address of the IEVMScriptExecutor that will be added to the registry + * @return id Identifier of the executor in the registry + */ + function addScriptExecutor(IEVMScriptExecutor _executor) external auth(REGISTRY_ADD_EXECUTOR_ROLE) returns (uint256 id) { + uint256 executorId = executorsNextIndex++; + executors[executorId] = ExecutorEntry(_executor, true); + emit EnableExecutor(executorId, _executor); + return executorId; + } + + /** + * @notice Disable script executor with ID `_executorId` + * @param _executorId Identifier of the executor in the registry + */ + function disableScriptExecutor(uint256 _executorId) + external + authP(REGISTRY_MANAGER_ROLE, arr(_executorId)) + { + // Note that we don't need to check for an executor's existence in this case, as only + // existing executors can be enabled + ExecutorEntry storage executorEntry = executors[_executorId]; + require(executorEntry.enabled, ERROR_EXECUTOR_DISABLED); + executorEntry.enabled = false; + emit DisableExecutor(_executorId, executorEntry.executor); + } + + /** + * @notice Enable script executor with ID `_executorId` + * @param _executorId Identifier of the executor in the registry + */ + function enableScriptExecutor(uint256 _executorId) + external + authP(REGISTRY_MANAGER_ROLE, arr(_executorId)) + executorExists(_executorId) + { + ExecutorEntry storage executorEntry = executors[_executorId]; + require(!executorEntry.enabled, ERROR_EXECUTOR_ENABLED); + executorEntry.enabled = true; + emit EnableExecutor(_executorId, executorEntry.executor); + } + + /** + * @dev Get the script executor that can execute a particular script based on its first 4 bytes + * @param _script EVMScript being inspected + */ + function getScriptExecutor(bytes _script) public view returns (IEVMScriptExecutor) { + uint256 id = _script.getSpecId(); + + // Note that we don't need to check for an executor's existence in this case, as only + // existing executors can be enabled + ExecutorEntry storage entry = executors[id]; + return entry.enabled ? entry.executor : IEVMScriptExecutor(0); + } +} diff --git a/contracts/mutants/EVMScriptRegistry/3/DLR/EVMScriptRegistry.sol b/contracts/mutants/EVMScriptRegistry/3/DLR/EVMScriptRegistry.sol new file mode 100644 index 00000000000..ef5c2672989 --- /dev/null +++ b/contracts/mutants/EVMScriptRegistry/3/DLR/EVMScriptRegistry.sol @@ -0,0 +1,104 @@ +pragma solidity 0.4.24; + +import "../apps/AragonApp.sol"; +import "./ScriptHelpers.sol"; +import "./IEVMScriptExecutor.sol"; +import "./IEVMScriptRegistry.sol"; + + +/* solium-disable function-order */ +// Allow public initialize() to be first +contract EVMScriptRegistry is IEVMScriptRegistry, EVMScriptRegistryConstants, AragonApp { + using ScriptHelpers for bytes; + + // bytes32 public constant REGISTRY_ADD_EXECUTOR_ROLE = keccak256("REGISTRY_ADD_EXECUTOR_ROLE"); + bytes32 public constant REGISTRY_ADD_EXECUTOR_ROLE = 0xc4e90f38eea8c4212a009ca7b8947943ba4d4a58d19b683417f65291d1cd9ed2; + // WARN: Manager can censor all votes and the like happening in an org + // bytes32 public constant REGISTRY_MANAGER_ROLE = keccak256("REGISTRY_MANAGER_ROLE"); + bytes32 public constant REGISTRY_MANAGER_ROLE = 0xf7a450ef335e1892cb42c8ca72e7242359d7711924b75db5717410da3f614aa3; + + string private constant ERROR_INEXISTENT_EXECUTOR = "EVMREG_INEXISTENT_EXECUTOR"; + string private constant ERROR_EXECUTOR_ENABLED = "EVMREG_EXECUTOR_ENABLED"; + string private constant ERROR_EXECUTOR_DISABLED = "EVMREG_EXECUTOR_DISABLED"; + + struct ExecutorEntry { + IEVMScriptExecutor executor; + bool enabled; + } + + uint256 private executorsNextIndex; + mapping (uint256 => ExecutorEntry) public executors; + + event EnableExecutor(uint256 indexed executorId, address indexed executorAddress); + event DisableExecutor(uint256 indexed executorId, address indexed executorAddress); + + modifier executorExists(uint256 _executorId) { + require(_executorId > 0 && _executorId < executorsNextIndex, ERROR_INEXISTENT_EXECUTOR); + _; + } + + /** + * @notice Initialize the registry + */ + function initialize() public onlyInit { + initialized(); + // Create empty record to begin executor IDs at 1 + executorsNextIndex = 1; + } + + /** + * @notice Add a new script executor with address `_executor` to the registry + * @param _executor Address of the IEVMScriptExecutor that will be added to the registry + * @return id Identifier of the executor in the registry + */ + function addScriptExecutor(IEVMScriptExecutor _executor) external auth(REGISTRY_ADD_EXECUTOR_ROLE) returns (uint256 id) { + uint256 executorId = executorsNextIndex++; + executors[executorId] = ExecutorEntry(_executor, true); + emit EnableExecutor(executorId, _executor); + return executorId; + } + + /** + * @notice Disable script executor with ID `_executorId` + * @param _executorId Identifier of the executor in the registry + */ + function disableScriptExecutor(uint256 _executorId) + external + authP(REGISTRY_MANAGER_ROLE, arr(_executorId)) + { + // Note that we don't need to check for an executor's existence in this case, as only + // existing executors can be enabled + ExecutorEntry memory executorEntry = executors[_executorId]; + require(executorEntry.enabled, ERROR_EXECUTOR_DISABLED); + executorEntry.enabled = false; + emit DisableExecutor(_executorId, executorEntry.executor); + } + + /** + * @notice Enable script executor with ID `_executorId` + * @param _executorId Identifier of the executor in the registry + */ + function enableScriptExecutor(uint256 _executorId) + external + authP(REGISTRY_MANAGER_ROLE, arr(_executorId)) + executorExists(_executorId) + { + ExecutorEntry memory executorEntry = executors[_executorId]; + require(!executorEntry.enabled, ERROR_EXECUTOR_ENABLED); + executorEntry.enabled = true; + emit EnableExecutor(_executorId, executorEntry.executor); + } + + /** + * @dev Get the script executor that can execute a particular script based on its first 4 bytes + * @param _script EVMScript being inspected + */ + function getScriptExecutor(bytes _script) public view returns (IEVMScriptExecutor) { + uint256 id = _script.getSpecId(); + + // Note that we don't need to check for an executor's existence in this case, as only + // existing executors can be enabled + ExecutorEntry memory entry = executors[id]; + return entry.enabled ? entry.executor : IEVMScriptExecutor(0); + } +} diff --git a/contracts/mutants/EVMScriptRegistry/3/EED/EVMScriptRegistry.sol b/contracts/mutants/EVMScriptRegistry/3/EED/EVMScriptRegistry.sol new file mode 100644 index 00000000000..6e0f15222e9 --- /dev/null +++ b/contracts/mutants/EVMScriptRegistry/3/EED/EVMScriptRegistry.sol @@ -0,0 +1,104 @@ +pragma solidity 0.4.24; + +import "../apps/AragonApp.sol"; +import "./ScriptHelpers.sol"; +import "./IEVMScriptExecutor.sol"; +import "./IEVMScriptRegistry.sol"; + + +/* solium-disable function-order */ +// Allow public initialize() to be first +contract EVMScriptRegistry is IEVMScriptRegistry, EVMScriptRegistryConstants, AragonApp { + using ScriptHelpers for bytes; + + // bytes32 public constant REGISTRY_ADD_EXECUTOR_ROLE = keccak256("REGISTRY_ADD_EXECUTOR_ROLE"); + bytes32 public constant REGISTRY_ADD_EXECUTOR_ROLE = 0xc4e90f38eea8c4212a009ca7b8947943ba4d4a58d19b683417f65291d1cd9ed2; + // WARN: Manager can censor all votes and the like happening in an org + // bytes32 public constant REGISTRY_MANAGER_ROLE = keccak256("REGISTRY_MANAGER_ROLE"); + bytes32 public constant REGISTRY_MANAGER_ROLE = 0xf7a450ef335e1892cb42c8ca72e7242359d7711924b75db5717410da3f614aa3; + + string private constant ERROR_INEXISTENT_EXECUTOR = "EVMREG_INEXISTENT_EXECUTOR"; + string private constant ERROR_EXECUTOR_ENABLED = "EVMREG_EXECUTOR_ENABLED"; + string private constant ERROR_EXECUTOR_DISABLED = "EVMREG_EXECUTOR_DISABLED"; + + struct ExecutorEntry { + IEVMScriptExecutor executor; + bool enabled; + } + + uint256 private executorsNextIndex; + mapping (uint256 => ExecutorEntry) public executors; + + event EnableExecutor(uint256 indexed executorId, address indexed executorAddress); + event DisableExecutor(uint256 indexed executorId, address indexed executorAddress); + + modifier executorExists(uint256 _executorId) { + require(_executorId > 0 && _executorId < executorsNextIndex, ERROR_INEXISTENT_EXECUTOR); + _; + } + + /** + * @notice Initialize the registry + */ + function initialize() public onlyInit { + initialized(); + // Create empty record to begin executor IDs at 1 + executorsNextIndex = 1; + } + + /** + * @notice Add a new script executor with address `_executor` to the registry + * @param _executor Address of the IEVMScriptExecutor that will be added to the registry + * @return id Identifier of the executor in the registry + */ + function addScriptExecutor(IEVMScriptExecutor _executor) external auth(REGISTRY_ADD_EXECUTOR_ROLE) returns (uint256 id) { + uint256 executorId = executorsNextIndex++; + executors[executorId] = ExecutorEntry(_executor, true); + /* emit EnableExecutor(executorId, _executor); */ + return executorId; + } + + /** + * @notice Disable script executor with ID `_executorId` + * @param _executorId Identifier of the executor in the registry + */ + function disableScriptExecutor(uint256 _executorId) + external + authP(REGISTRY_MANAGER_ROLE, arr(_executorId)) + { + // Note that we don't need to check for an executor's existence in this case, as only + // existing executors can be enabled + ExecutorEntry storage executorEntry = executors[_executorId]; + require(executorEntry.enabled, ERROR_EXECUTOR_DISABLED); + executorEntry.enabled = false; + /* emit DisableExecutor(_executorId, executorEntry.executor); */ + } + + /** + * @notice Enable script executor with ID `_executorId` + * @param _executorId Identifier of the executor in the registry + */ + function enableScriptExecutor(uint256 _executorId) + external + authP(REGISTRY_MANAGER_ROLE, arr(_executorId)) + executorExists(_executorId) + { + ExecutorEntry storage executorEntry = executors[_executorId]; + require(!executorEntry.enabled, ERROR_EXECUTOR_ENABLED); + executorEntry.enabled = true; + /* emit EnableExecutor(_executorId, executorEntry.executor); */ + } + + /** + * @dev Get the script executor that can execute a particular script based on its first 4 bytes + * @param _script EVMScript being inspected + */ + function getScriptExecutor(bytes _script) public view returns (IEVMScriptExecutor) { + uint256 id = _script.getSpecId(); + + // Note that we don't need to check for an executor's existence in this case, as only + // existing executors can be enabled + ExecutorEntry storage entry = executors[id]; + return entry.enabled ? entry.executor : IEVMScriptExecutor(0); + } +} diff --git a/contracts/mutants/EVMScriptRegistry/3/EHC/EVMScriptRegistry.sol b/contracts/mutants/EVMScriptRegistry/3/EHC/EVMScriptRegistry.sol new file mode 100644 index 00000000000..ef87ee2801d --- /dev/null +++ b/contracts/mutants/EVMScriptRegistry/3/EHC/EVMScriptRegistry.sol @@ -0,0 +1,104 @@ +pragma solidity 0.4.24; + +import "../apps/AragonApp.sol"; +import "./ScriptHelpers.sol"; +import "./IEVMScriptExecutor.sol"; +import "./IEVMScriptRegistry.sol"; + + +/* solium-disable function-order */ +// Allow public initialize() to be first +contract EVMScriptRegistry is IEVMScriptRegistry, EVMScriptRegistryConstants, AragonApp { + using ScriptHelpers for bytes; + + // bytes32 public constant REGISTRY_ADD_EXECUTOR_ROLE = keccak256("REGISTRY_ADD_EXECUTOR_ROLE"); + bytes32 public constant REGISTRY_ADD_EXECUTOR_ROLE = 0xc4e90f38eea8c4212a009ca7b8947943ba4d4a58d19b683417f65291d1cd9ed2; + // WARN: Manager can censor all votes and the like happening in an org + // bytes32 public constant REGISTRY_MANAGER_ROLE = keccak256("REGISTRY_MANAGER_ROLE"); + bytes32 public constant REGISTRY_MANAGER_ROLE = 0xf7a450ef335e1892cb42c8ca72e7242359d7711924b75db5717410da3f614aa3; + + string private constant ERROR_INEXISTENT_EXECUTOR = "EVMREG_INEXISTENT_EXECUTOR"; + string private constant ERROR_EXECUTOR_ENABLED = "EVMREG_EXECUTOR_ENABLED"; + string private constant ERROR_EXECUTOR_DISABLED = "EVMREG_EXECUTOR_DISABLED"; + + struct ExecutorEntry { + IEVMScriptExecutor executor; + bool enabled; + } + + uint256 private executorsNextIndex; + mapping (uint256 => ExecutorEntry) public executors; + + event EnableExecutor(uint256 indexed executorId, address indexed executorAddress); + event DisableExecutor(uint256 indexed executorId, address indexed executorAddress); + + modifier executorExists(uint256 _executorId) { + /* require(_executorId > 0 && _executorId < executorsNextIndex, ERROR_INEXISTENT_EXECUTOR); */ + _; + } + + /** + * @notice Initialize the registry + */ + function initialize() public onlyInit { + initialized(); + // Create empty record to begin executor IDs at 1 + executorsNextIndex = 1; + } + + /** + * @notice Add a new script executor with address `_executor` to the registry + * @param _executor Address of the IEVMScriptExecutor that will be added to the registry + * @return id Identifier of the executor in the registry + */ + function addScriptExecutor(IEVMScriptExecutor _executor) external auth(REGISTRY_ADD_EXECUTOR_ROLE) returns (uint256 id) { + uint256 executorId = executorsNextIndex++; + executors[executorId] = ExecutorEntry(_executor, true); + emit EnableExecutor(executorId, _executor); + return executorId; + } + + /** + * @notice Disable script executor with ID `_executorId` + * @param _executorId Identifier of the executor in the registry + */ + function disableScriptExecutor(uint256 _executorId) + external + authP(REGISTRY_MANAGER_ROLE, arr(_executorId)) + { + // Note that we don't need to check for an executor's existence in this case, as only + // existing executors can be enabled + ExecutorEntry storage executorEntry = executors[_executorId]; + /* require(executorEntry.enabled, ERROR_EXECUTOR_DISABLED); */ + executorEntry.enabled = false; + emit DisableExecutor(_executorId, executorEntry.executor); + } + + /** + * @notice Enable script executor with ID `_executorId` + * @param _executorId Identifier of the executor in the registry + */ + function enableScriptExecutor(uint256 _executorId) + external + authP(REGISTRY_MANAGER_ROLE, arr(_executorId)) + executorExists(_executorId) + { + ExecutorEntry storage executorEntry = executors[_executorId]; + /* require(!executorEntry.enabled, ERROR_EXECUTOR_ENABLED); */ + executorEntry.enabled = true; + emit EnableExecutor(_executorId, executorEntry.executor); + } + + /** + * @dev Get the script executor that can execute a particular script based on its first 4 bytes + * @param _script EVMScript being inspected + */ + function getScriptExecutor(bytes _script) public view returns (IEVMScriptExecutor) { + uint256 id = _script.getSpecId(); + + // Note that we don't need to check for an executor's existence in this case, as only + // existing executors can be enabled + ExecutorEntry storage entry = executors[id]; + return entry.enabled ? entry.executor : IEVMScriptExecutor(0); + } +} diff --git a/contracts/mutants/EVMScriptRegistry/3/FVR/EVMScriptRegistry.sol b/contracts/mutants/EVMScriptRegistry/3/FVR/EVMScriptRegistry.sol new file mode 100644 index 00000000000..202372a5936 --- /dev/null +++ b/contracts/mutants/EVMScriptRegistry/3/FVR/EVMScriptRegistry.sol @@ -0,0 +1,104 @@ +pragma solidity 0.4.24; + +import "../apps/AragonApp.sol"; +import "./ScriptHelpers.sol"; +import "./IEVMScriptExecutor.sol"; +import "./IEVMScriptRegistry.sol"; + + +/* solium-disable function-order */ +// Allow public initialize() to be first +contract EVMScriptRegistry is IEVMScriptRegistry, EVMScriptRegistryConstants, AragonApp { + using ScriptHelpers for bytes; + + // bytes32 public constant REGISTRY_ADD_EXECUTOR_ROLE = keccak256("REGISTRY_ADD_EXECUTOR_ROLE"); + bytes32 public constant REGISTRY_ADD_EXECUTOR_ROLE = 0xc4e90f38eea8c4212a009ca7b8947943ba4d4a58d19b683417f65291d1cd9ed2; + // WARN: Manager can censor all votes and the like happening in an org + // bytes32 public constant REGISTRY_MANAGER_ROLE = keccak256("REGISTRY_MANAGER_ROLE"); + bytes32 public constant REGISTRY_MANAGER_ROLE = 0xf7a450ef335e1892cb42c8ca72e7242359d7711924b75db5717410da3f614aa3; + + string private constant ERROR_INEXISTENT_EXECUTOR = "EVMREG_INEXISTENT_EXECUTOR"; + string private constant ERROR_EXECUTOR_ENABLED = "EVMREG_EXECUTOR_ENABLED"; + string private constant ERROR_EXECUTOR_DISABLED = "EVMREG_EXECUTOR_DISABLED"; + + struct ExecutorEntry { + IEVMScriptExecutor executor; + bool enabled; + } + + uint256 private executorsNextIndex; + mapping (uint256 => ExecutorEntry) public executors; + + event EnableExecutor(uint256 indexed executorId, address indexed executorAddress); + event DisableExecutor(uint256 indexed executorId, address indexed executorAddress); + + modifier executorExists(uint256 _executorId) { + require(_executorId > 0 && _executorId < executorsNextIndex, ERROR_INEXISTENT_EXECUTOR); + _; + } + + /** + * @notice Initialize the registry + */ + function initialize() external onlyInit { + initialized(); + // Create empty record to begin executor IDs at 1 + executorsNextIndex = 1; + } + + /** + * @notice Add a new script executor with address `_executor` to the registry + * @param _executor Address of the IEVMScriptExecutor that will be added to the registry + * @return id Identifier of the executor in the registry + */ + function addScriptExecutor(IEVMScriptExecutor _executor) public auth(REGISTRY_ADD_EXECUTOR_ROLE) returns (uint256 id) { + uint256 executorId = executorsNextIndex++; + executors[executorId] = ExecutorEntry(_executor, true); + emit EnableExecutor(executorId, _executor); + return executorId; + } + + /** + * @notice Disable script executor with ID `_executorId` + * @param _executorId Identifier of the executor in the registry + */ + function disableScriptExecutor(uint256 _executorId) + public + authP(REGISTRY_MANAGER_ROLE, arr(_executorId)) + { + // Note that we don't need to check for an executor's existence in this case, as only + // existing executors can be enabled + ExecutorEntry storage executorEntry = executors[_executorId]; + require(executorEntry.enabled, ERROR_EXECUTOR_DISABLED); + executorEntry.enabled = false; + emit DisableExecutor(_executorId, executorEntry.executor); + } + + /** + * @notice Enable script executor with ID `_executorId` + * @param _executorId Identifier of the executor in the registry + */ + function enableScriptExecutor(uint256 _executorId) + external + authP(REGISTRY_MANAGER_ROLE, arr(_executorId)) + executorExists(_executorId) + { + ExecutorEntry storage executorEntry = executors[_executorId]; + require(!executorEntry.enabled, ERROR_EXECUTOR_ENABLED); + executorEntry.enabled = true; + emit EnableExecutor(_executorId, executorEntry.executor); + } + + /** + * @dev Get the script executor that can execute a particular script based on its first 4 bytes + * @param _script EVMScript being inspected + */ + function getScriptExecutor(bytes _script) public view returns (IEVMScriptExecutor) { + uint256 id = _script.getSpecId(); + + // Note that we don't need to check for an executor's existence in this case, as only + // existing executors can be enabled + ExecutorEntry storage entry = executors[id]; + return entry.enabled ? entry.executor : IEVMScriptExecutor(0); + } +} diff --git a/contracts/mutants/EVMScriptRegistry/3/ILR/EVMScriptRegistry.sol b/contracts/mutants/EVMScriptRegistry/3/ILR/EVMScriptRegistry.sol new file mode 100644 index 00000000000..b723526d93d --- /dev/null +++ b/contracts/mutants/EVMScriptRegistry/3/ILR/EVMScriptRegistry.sol @@ -0,0 +1,104 @@ +pragma solidity 0.4.24; + +import "../apps/AragonApp.sol"; +import "./ScriptHelpers.sol"; +import "./IEVMScriptExecutor.sol"; +import "./IEVMScriptRegistry.sol"; + + +/* solium-disable function-order */ +// Allow public initialize() to be first +contract EVMScriptRegistry is IEVMScriptRegistry, EVMScriptRegistryConstants, AragonApp { + using ScriptHelpers for bytes; + + // bytes32 public constant REGISTRY_ADD_EXECUTOR_ROLE = keccak256("REGISTRY_ADD_EXECUTOR_ROLE"); + bytes32 public constant REGISTRY_ADD_EXECUTOR_ROLE = 0xc4e90f38eea8c4212a009ca7b8947943ba4d4a58d19b683417f65291d1cd9ed2; + // WARN: Manager can censor all votes and the like happening in an org + // bytes32 public constant REGISTRY_MANAGER_ROLE = keccak256("REGISTRY_MANAGER_ROLE"); + bytes32 public constant REGISTRY_MANAGER_ROLE = 0xf7a450ef335e1892cb42c8ca72e7242359d7711924b75db5717410da3f614aa3; + + string private constant ERROR_INEXISTENT_EXECUTOR = "EVMREG_INEXISTENT_EXECUTOR"; + string private constant ERROR_EXECUTOR_ENABLED = "EVMREG_EXECUTOR_ENABLED"; + string private constant ERROR_EXECUTOR_DISABLED = "EVMREG_EXECUTOR_DISABLED"; + + struct ExecutorEntry { + IEVMScriptExecutor executor; + bool enabled; + } + + uint256 private executorsNextIndex; + mapping (uint256 => ExecutorEntry) public executors; + + event EnableExecutor(uint256 indexed executorId, address indexed executorAddress); + event DisableExecutor(uint256 indexed executorId, address indexed executorAddress); + + modifier executorExists(uint256 _executorId) { + require(_executorId > 1 && _executorId < executorsNextIndex, ERROR_INEXISTENT_EXECUTOR); + _; + } + + /** + * @notice Initialize the registry + */ + function initialize() public onlyInit { + initialized(); + // Create empty record to begin executor IDs at 1 + executorsNextIndex = 0; + } + + /** + * @notice Add a new script executor with address `_executor` to the registry + * @param _executor Address of the IEVMScriptExecutor that will be added to the registry + * @return id Identifier of the executor in the registry + */ + function addScriptExecutor(IEVMScriptExecutor _executor) external auth(REGISTRY_ADD_EXECUTOR_ROLE) returns (uint256 id) { + uint256 executorId = executorsNextIndex++; + executors[executorId] = ExecutorEntry(_executor, true); + emit EnableExecutor(executorId, _executor); + return executorId; + } + + /** + * @notice Disable script executor with ID `_executorId` + * @param _executorId Identifier of the executor in the registry + */ + function disableScriptExecutor(uint256 _executorId) + external + authP(REGISTRY_MANAGER_ROLE, arr(_executorId)) + { + // Note that we don't need to check for an executor's existence in this case, as only + // existing executors can be enabled + ExecutorEntry storage executorEntry = executors[_executorId]; + require(executorEntry.enabled, ERROR_EXECUTOR_DISABLED); + executorEntry.enabled = false; + emit DisableExecutor(_executorId, executorEntry.executor); + } + + /** + * @notice Enable script executor with ID `_executorId` + * @param _executorId Identifier of the executor in the registry + */ + function enableScriptExecutor(uint256 _executorId) + external + authP(REGISTRY_MANAGER_ROLE, arr(_executorId)) + executorExists(_executorId) + { + ExecutorEntry storage executorEntry = executors[_executorId]; + require(!executorEntry.enabled, ERROR_EXECUTOR_ENABLED); + executorEntry.enabled = true; + emit EnableExecutor(_executorId, executorEntry.executor); + } + + /** + * @dev Get the script executor that can execute a particular script based on its first 4 bytes + * @param _script EVMScript being inspected + */ + function getScriptExecutor(bytes _script) public view returns (IEVMScriptExecutor) { + uint256 id = _script.getSpecId(); + + // Note that we don't need to check for an executor's existence in this case, as only + // existing executors can be enabled + ExecutorEntry storage entry = executors[id]; + return entry.enabled ? entry.executor : IEVMScriptExecutor(1); + } +} diff --git a/contracts/mutants/EVMScriptRegistry/3/MOD/EVMScriptRegistry.sol b/contracts/mutants/EVMScriptRegistry/3/MOD/EVMScriptRegistry.sol new file mode 100644 index 00000000000..ef6e2278086 --- /dev/null +++ b/contracts/mutants/EVMScriptRegistry/3/MOD/EVMScriptRegistry.sol @@ -0,0 +1,104 @@ +pragma solidity 0.4.24; + +import "../apps/AragonApp.sol"; +import "./ScriptHelpers.sol"; +import "./IEVMScriptExecutor.sol"; +import "./IEVMScriptRegistry.sol"; + + +/* solium-disable function-order */ +// Allow public initialize() to be first +contract EVMScriptRegistry is IEVMScriptRegistry, EVMScriptRegistryConstants, AragonApp { + using ScriptHelpers for bytes; + + // bytes32 public constant REGISTRY_ADD_EXECUTOR_ROLE = keccak256("REGISTRY_ADD_EXECUTOR_ROLE"); + bytes32 public constant REGISTRY_ADD_EXECUTOR_ROLE = 0xc4e90f38eea8c4212a009ca7b8947943ba4d4a58d19b683417f65291d1cd9ed2; + // WARN: Manager can censor all votes and the like happening in an org + // bytes32 public constant REGISTRY_MANAGER_ROLE = keccak256("REGISTRY_MANAGER_ROLE"); + bytes32 public constant REGISTRY_MANAGER_ROLE = 0xf7a450ef335e1892cb42c8ca72e7242359d7711924b75db5717410da3f614aa3; + + string private constant ERROR_INEXISTENT_EXECUTOR = "EVMREG_INEXISTENT_EXECUTOR"; + string private constant ERROR_EXECUTOR_ENABLED = "EVMREG_EXECUTOR_ENABLED"; + string private constant ERROR_EXECUTOR_DISABLED = "EVMREG_EXECUTOR_DISABLED"; + + struct ExecutorEntry { + IEVMScriptExecutor executor; + bool enabled; + } + + uint256 private executorsNextIndex; + mapping (uint256 => ExecutorEntry) public executors; + + event EnableExecutor(uint256 indexed executorId, address indexed executorAddress); + event DisableExecutor(uint256 indexed executorId, address indexed executorAddress); + + modifier executorExists(uint256 _executorId) { + require(_executorId > 0 && _executorId < executorsNextIndex, ERROR_INEXISTENT_EXECUTOR); + _; + } + + /** + * @notice Initialize the registry + */ + function initialize() public { + initialized(); + // Create empty record to begin executor IDs at 1 + executorsNextIndex = 1; + } + + /** + * @notice Add a new script executor with address `_executor` to the registry + * @param _executor Address of the IEVMScriptExecutor that will be added to the registry + * @return id Identifier of the executor in the registry + */ + function addScriptExecutor(IEVMScriptExecutor _executor) external returns (uint256 id) { + uint256 executorId = executorsNextIndex++; + executors[executorId] = ExecutorEntry(_executor, true); + emit EnableExecutor(executorId, _executor); + return executorId; + } + + /** + * @notice Disable script executor with ID `_executorId` + * @param _executorId Identifier of the executor in the registry + */ + function disableScriptExecutor(uint256 _executorId) + external + + { + // Note that we don't need to check for an executor's existence in this case, as only + // existing executors can be enabled + ExecutorEntry storage executorEntry = executors[_executorId]; + require(executorEntry.enabled, ERROR_EXECUTOR_DISABLED); + executorEntry.enabled = false; + emit DisableExecutor(_executorId, executorEntry.executor); + } + + /** + * @notice Enable script executor with ID `_executorId` + * @param _executorId Identifier of the executor in the registry + */ + function enableScriptExecutor(uint256 _executorId) + external + authP(REGISTRY_MANAGER_ROLE, arr(_executorId)) + executorExists(_executorId) + { + ExecutorEntry storage executorEntry = executors[_executorId]; + require(!executorEntry.enabled, ERROR_EXECUTOR_ENABLED); + executorEntry.enabled = true; + emit EnableExecutor(_executorId, executorEntry.executor); + } + + /** + * @dev Get the script executor that can execute a particular script based on its first 4 bytes + * @param _script EVMScript being inspected + */ + function getScriptExecutor(bytes _script) public view returns (IEVMScriptExecutor) { + uint256 id = _script.getSpecId(); + + // Note that we don't need to check for an executor's existence in this case, as only + // existing executors can be enabled + ExecutorEntry storage entry = executors[id]; + return entry.enabled ? entry.executor : IEVMScriptExecutor(0); + } +} diff --git a/contracts/mutants/EVMScriptRegistry/3/MOR/EVMScriptRegistry.sol b/contracts/mutants/EVMScriptRegistry/3/MOR/EVMScriptRegistry.sol new file mode 100644 index 00000000000..c174fba4086 --- /dev/null +++ b/contracts/mutants/EVMScriptRegistry/3/MOR/EVMScriptRegistry.sol @@ -0,0 +1,104 @@ +pragma solidity 0.4.24; + +import "../apps/AragonApp.sol"; +import "./ScriptHelpers.sol"; +import "./IEVMScriptExecutor.sol"; +import "./IEVMScriptRegistry.sol"; + + +/* solium-disable function-order */ +// Allow public initialize() to be first +contract EVMScriptRegistry is IEVMScriptRegistry, EVMScriptRegistryConstants, AragonApp { + using ScriptHelpers for bytes; + + // bytes32 public constant REGISTRY_ADD_EXECUTOR_ROLE = keccak256("REGISTRY_ADD_EXECUTOR_ROLE"); + bytes32 public constant REGISTRY_ADD_EXECUTOR_ROLE = 0xc4e90f38eea8c4212a009ca7b8947943ba4d4a58d19b683417f65291d1cd9ed2; + // WARN: Manager can censor all votes and the like happening in an org + // bytes32 public constant REGISTRY_MANAGER_ROLE = keccak256("REGISTRY_MANAGER_ROLE"); + bytes32 public constant REGISTRY_MANAGER_ROLE = 0xf7a450ef335e1892cb42c8ca72e7242359d7711924b75db5717410da3f614aa3; + + string private constant ERROR_INEXISTENT_EXECUTOR = "EVMREG_INEXISTENT_EXECUTOR"; + string private constant ERROR_EXECUTOR_ENABLED = "EVMREG_EXECUTOR_ENABLED"; + string private constant ERROR_EXECUTOR_DISABLED = "EVMREG_EXECUTOR_DISABLED"; + + struct ExecutorEntry { + IEVMScriptExecutor executor; + bool enabled; + } + + uint256 private executorsNextIndex; + mapping (uint256 => ExecutorEntry) public executors; + + event EnableExecutor(uint256 indexed executorId, address indexed executorAddress); + event DisableExecutor(uint256 indexed executorId, address indexed executorAddress); + + modifier executorExists(uint256 _executorId) { + require(_executorId > 0 && _executorId < executorsNextIndex, ERROR_INEXISTENT_EXECUTOR); + _; + } + + /** + * @notice Initialize the registry + */ + function initialize() public onlyInit { + initialized(); + // Create empty record to begin executor IDs at 1 + executorsNextIndex = 1; + } + + /** + * @notice Add a new script executor with address `_executor` to the registry + * @param _executor Address of the IEVMScriptExecutor that will be added to the registry + * @return id Identifier of the executor in the registry + */ + function addScriptExecutor(IEVMScriptExecutor _executor) external onlyInit returns (uint256 id) { + uint256 executorId = executorsNextIndex++; + executors[executorId] = ExecutorEntry(_executor, true); + emit EnableExecutor(executorId, _executor); + return executorId; + } + + /** + * @notice Disable script executor with ID `_executorId` + * @param _executorId Identifier of the executor in the registry + */ + function disableScriptExecutor(uint256 _executorId) + external + onlyInit + { + // Note that we don't need to check for an executor's existence in this case, as only + // existing executors can be enabled + ExecutorEntry storage executorEntry = executors[_executorId]; + require(executorEntry.enabled, ERROR_EXECUTOR_DISABLED); + executorEntry.enabled = false; + emit DisableExecutor(_executorId, executorEntry.executor); + } + + /** + * @notice Enable script executor with ID `_executorId` + * @param _executorId Identifier of the executor in the registry + */ + function enableScriptExecutor(uint256 _executorId) + external + onlyInit + executorExists(_executorId) + { + ExecutorEntry storage executorEntry = executors[_executorId]; + require(!executorEntry.enabled, ERROR_EXECUTOR_ENABLED); + executorEntry.enabled = true; + emit EnableExecutor(_executorId, executorEntry.executor); + } + + /** + * @dev Get the script executor that can execute a particular script based on its first 4 bytes + * @param _script EVMScript being inspected + */ + function getScriptExecutor(bytes _script) public view returns (IEVMScriptExecutor) { + uint256 id = _script.getSpecId(); + + // Note that we don't need to check for an executor's existence in this case, as only + // existing executors can be enabled + ExecutorEntry storage entry = executors[id]; + return entry.enabled ? entry.executor : IEVMScriptExecutor(0); + } +} diff --git a/contracts/mutants/EVMScriptRegistry/3/SLR/EVMScriptRegistry.sol b/contracts/mutants/EVMScriptRegistry/3/SLR/EVMScriptRegistry.sol new file mode 100644 index 00000000000..6dcda08e736 --- /dev/null +++ b/contracts/mutants/EVMScriptRegistry/3/SLR/EVMScriptRegistry.sol @@ -0,0 +1,104 @@ +pragma solidity 0.4.24; + +import "../apps/AragonApp.sol"; +import "./ScriptHelpers.sol"; +import "./IEVMScriptExecutor.sol"; +import "./IEVMScriptRegistry.sol"; + + +/* solium-disable function-order */ +// Allow public initialize() to be first +contract EVMScriptRegistry is IEVMScriptRegistry, EVMScriptRegistryConstants, AragonApp { + using ScriptHelpers for bytes; + + // bytes32 public constant REGISTRY_ADD_EXECUTOR_ROLE = keccak256("REGISTRY_ADD_EXECUTOR_ROLE"); + bytes32 public constant REGISTRY_ADD_EXECUTOR_ROLE = 0xc4e90f38eea8c4212a009ca7b8947943ba4d4a58d19b683417f65291d1cd9ed2; + // WARN: Manager can censor all votes and the like happening in an org + // bytes32 public constant REGISTRY_MANAGER_ROLE = keccak256("REGISTRY_MANAGER_ROLE"); + bytes32 public constant REGISTRY_MANAGER_ROLE = 0xf7a450ef335e1892cb42c8ca72e7242359d7711924b75db5717410da3f614aa3; + + string private constant ERROR_INEXISTENT_EXECUTOR = ""; + string private constant ERROR_EXECUTOR_ENABLED = ""; + string private constant ERROR_EXECUTOR_DISABLED = ""; + + struct ExecutorEntry { + IEVMScriptExecutor executor; + bool enabled; + } + + uint256 private executorsNextIndex; + mapping (uint256 => ExecutorEntry) public executors; + + event EnableExecutor(uint256 indexed executorId, address indexed executorAddress); + event DisableExecutor(uint256 indexed executorId, address indexed executorAddress); + + modifier executorExists(uint256 _executorId) { + require(_executorId > 0 && _executorId < executorsNextIndex, ERROR_INEXISTENT_EXECUTOR); + _; + } + + /** + * @notice Initialize the registry + */ + function initialize() public onlyInit { + initialized(); + // Create empty record to begin executor IDs at 1 + executorsNextIndex = 1; + } + + /** + * @notice Add a new script executor with address `_executor` to the registry + * @param _executor Address of the IEVMScriptExecutor that will be added to the registry + * @return id Identifier of the executor in the registry + */ + function addScriptExecutor(IEVMScriptExecutor _executor) external auth(REGISTRY_ADD_EXECUTOR_ROLE) returns (uint256 id) { + uint256 executorId = executorsNextIndex++; + executors[executorId] = ExecutorEntry(_executor, true); + emit EnableExecutor(executorId, _executor); + return executorId; + } + + /** + * @notice Disable script executor with ID `_executorId` + * @param _executorId Identifier of the executor in the registry + */ + function disableScriptExecutor(uint256 _executorId) + external + authP(REGISTRY_MANAGER_ROLE, arr(_executorId)) + { + // Note that we don't need to check for an executor's existence in this case, as only + // existing executors can be enabled + ExecutorEntry storage executorEntry = executors[_executorId]; + require(executorEntry.enabled, ERROR_EXECUTOR_DISABLED); + executorEntry.enabled = false; + emit DisableExecutor(_executorId, executorEntry.executor); + } + + /** + * @notice Enable script executor with ID `_executorId` + * @param _executorId Identifier of the executor in the registry + */ + function enableScriptExecutor(uint256 _executorId) + external + authP(REGISTRY_MANAGER_ROLE, arr(_executorId)) + executorExists(_executorId) + { + ExecutorEntry storage executorEntry = executors[_executorId]; + require(!executorEntry.enabled, ERROR_EXECUTOR_ENABLED); + executorEntry.enabled = true; + emit EnableExecutor(_executorId, executorEntry.executor); + } + + /** + * @dev Get the script executor that can execute a particular script based on its first 4 bytes + * @param _script EVMScript being inspected + */ + function getScriptExecutor(bytes _script) public view returns (IEVMScriptExecutor) { + uint256 id = _script.getSpecId(); + + // Note that we don't need to check for an executor's existence in this case, as only + // existing executors can be enabled + ExecutorEntry storage entry = executors[id]; + return entry.enabled ? entry.executor : IEVMScriptExecutor(0); + } +} diff --git a/contracts/mutants/EVMScriptRegistry/3/VVR/EVMScriptRegistry.sol b/contracts/mutants/EVMScriptRegistry/3/VVR/EVMScriptRegistry.sol new file mode 100644 index 00000000000..0c1bef05fd5 --- /dev/null +++ b/contracts/mutants/EVMScriptRegistry/3/VVR/EVMScriptRegistry.sol @@ -0,0 +1,104 @@ +pragma solidity 0.4.24; + +import "../apps/AragonApp.sol"; +import "./ScriptHelpers.sol"; +import "./IEVMScriptExecutor.sol"; +import "./IEVMScriptRegistry.sol"; + + +/* solium-disable function-order */ +// Allow public initialize() to be first +contract EVMScriptRegistry is IEVMScriptRegistry, EVMScriptRegistryConstants, AragonApp { + using ScriptHelpers for bytes; + + // bytes32 public constant REGISTRY_ADD_EXECUTOR_ROLE = keccak256("REGISTRY_ADD_EXECUTOR_ROLE"); + bytes32 internal constant REGISTRY_ADD_EXECUTOR_ROLE = 0xc4e90f38eea8c4212a009ca7b8947943ba4d4a58d19b683417f65291d1cd9ed2; + // WARN: Manager can censor all votes and the like happening in an org + // bytes32 public constant REGISTRY_MANAGER_ROLE = keccak256("REGISTRY_MANAGER_ROLE"); + bytes32 internal constant REGISTRY_MANAGER_ROLE = 0xf7a450ef335e1892cb42c8ca72e7242359d7711924b75db5717410da3f614aa3; + + string public constant ERROR_INEXISTENT_EXECUTOR = "EVMREG_INEXISTENT_EXECUTOR"; + string private constant ERROR_EXECUTOR_ENABLED = "EVMREG_EXECUTOR_ENABLED"; + string private constant ERROR_EXECUTOR_DISABLED = "EVMREG_EXECUTOR_DISABLED"; + + struct ExecutorEntry { + IEVMScriptExecutor executor; + bool enabled; + } + + uint256 private executorsNextIndex; + mapping (uint256 => ExecutorEntry) public executors; + + event EnableExecutor(uint256 indexed executorId, address indexed executorAddress); + event DisableExecutor(uint256 indexed executorId, address indexed executorAddress); + + modifier executorExists(uint256 _executorId) { + require(_executorId > 0 && _executorId < executorsNextIndex, ERROR_INEXISTENT_EXECUTOR); + _; + } + + /** + * @notice Initialize the registry + */ + function initialize() public onlyInit { + initialized(); + // Create empty record to begin executor IDs at 1 + executorsNextIndex = 1; + } + + /** + * @notice Add a new script executor with address `_executor` to the registry + * @param _executor Address of the IEVMScriptExecutor that will be added to the registry + * @return id Identifier of the executor in the registry + */ + function addScriptExecutor(IEVMScriptExecutor _executor) external auth(REGISTRY_ADD_EXECUTOR_ROLE) returns (uint256 id) { + uint256 executorId = executorsNextIndex++; + executors[executorId] = ExecutorEntry(_executor, true); + emit EnableExecutor(executorId, _executor); + return executorId; + } + + /** + * @notice Disable script executor with ID `_executorId` + * @param _executorId Identifier of the executor in the registry + */ + function disableScriptExecutor(uint256 _executorId) + external + authP(REGISTRY_MANAGER_ROLE, arr(_executorId)) + { + // Note that we don't need to check for an executor's existence in this case, as only + // existing executors can be enabled + ExecutorEntry storage executorEntry = executors[_executorId]; + require(executorEntry.enabled, ERROR_EXECUTOR_DISABLED); + executorEntry.enabled = false; + emit DisableExecutor(_executorId, executorEntry.executor); + } + + /** + * @notice Enable script executor with ID `_executorId` + * @param _executorId Identifier of the executor in the registry + */ + function enableScriptExecutor(uint256 _executorId) + external + authP(REGISTRY_MANAGER_ROLE, arr(_executorId)) + executorExists(_executorId) + { + ExecutorEntry storage executorEntry = executors[_executorId]; + require(!executorEntry.enabled, ERROR_EXECUTOR_ENABLED); + executorEntry.enabled = true; + emit EnableExecutor(_executorId, executorEntry.executor); + } + + /** + * @dev Get the script executor that can execute a particular script based on its first 4 bytes + * @param _script EVMScript being inspected + */ + function getScriptExecutor(bytes _script) public view returns (IEVMScriptExecutor) { + uint256 id = _script.getSpecId(); + + // Note that we don't need to check for an executor's existence in this case, as only + // existing executors can be enabled + ExecutorEntry storage entry = executors[id]; + return entry.enabled ? entry.executor : IEVMScriptExecutor(0); + } +} diff --git a/contracts/mutants/EVMScriptRegistry/4/FVR/EVMScriptRegistry.sol b/contracts/mutants/EVMScriptRegistry/4/FVR/EVMScriptRegistry.sol new file mode 100644 index 00000000000..9460524a3b2 --- /dev/null +++ b/contracts/mutants/EVMScriptRegistry/4/FVR/EVMScriptRegistry.sol @@ -0,0 +1,104 @@ +pragma solidity 0.4.24; + +import "../apps/AragonApp.sol"; +import "./ScriptHelpers.sol"; +import "./IEVMScriptExecutor.sol"; +import "./IEVMScriptRegistry.sol"; + + +/* solium-disable function-order */ +// Allow public initialize() to be first +contract EVMScriptRegistry is IEVMScriptRegistry, EVMScriptRegistryConstants, AragonApp { + using ScriptHelpers for bytes; + + // bytes32 public constant REGISTRY_ADD_EXECUTOR_ROLE = keccak256("REGISTRY_ADD_EXECUTOR_ROLE"); + bytes32 public constant REGISTRY_ADD_EXECUTOR_ROLE = 0xc4e90f38eea8c4212a009ca7b8947943ba4d4a58d19b683417f65291d1cd9ed2; + // WARN: Manager can censor all votes and the like happening in an org + // bytes32 public constant REGISTRY_MANAGER_ROLE = keccak256("REGISTRY_MANAGER_ROLE"); + bytes32 public constant REGISTRY_MANAGER_ROLE = 0xf7a450ef335e1892cb42c8ca72e7242359d7711924b75db5717410da3f614aa3; + + string private constant ERROR_INEXISTENT_EXECUTOR = "EVMREG_INEXISTENT_EXECUTOR"; + string private constant ERROR_EXECUTOR_ENABLED = "EVMREG_EXECUTOR_ENABLED"; + string private constant ERROR_EXECUTOR_DISABLED = "EVMREG_EXECUTOR_DISABLED"; + + struct ExecutorEntry { + IEVMScriptExecutor executor; + bool enabled; + } + + uint256 private executorsNextIndex; + mapping (uint256 => ExecutorEntry) public executors; + + event EnableExecutor(uint256 indexed executorId, address indexed executorAddress); + event DisableExecutor(uint256 indexed executorId, address indexed executorAddress); + + modifier executorExists(uint256 _executorId) { + require(_executorId > 0 && _executorId < executorsNextIndex, ERROR_INEXISTENT_EXECUTOR); + _; + } + + /** + * @notice Initialize the registry + */ + function initialize() external onlyInit { + initialized(); + // Create empty record to begin executor IDs at 1 + executorsNextIndex = 1; + } + + /** + * @notice Add a new script executor with address `_executor` to the registry + * @param _executor Address of the IEVMScriptExecutor that will be added to the registry + * @return id Identifier of the executor in the registry + */ + function addScriptExecutor(IEVMScriptExecutor _executor) public auth(REGISTRY_ADD_EXECUTOR_ROLE) returns (uint256 id) { + uint256 executorId = executorsNextIndex++; + executors[executorId] = ExecutorEntry(_executor, true); + emit EnableExecutor(executorId, _executor); + return executorId; + } + + /** + * @notice Disable script executor with ID `_executorId` + * @param _executorId Identifier of the executor in the registry + */ + function disableScriptExecutor(uint256 _executorId) + public + authP(REGISTRY_MANAGER_ROLE, arr(_executorId)) + { + // Note that we don't need to check for an executor's existence in this case, as only + // existing executors can be enabled + ExecutorEntry storage executorEntry = executors[_executorId]; + require(executorEntry.enabled, ERROR_EXECUTOR_DISABLED); + executorEntry.enabled = false; + emit DisableExecutor(_executorId, executorEntry.executor); + } + + /** + * @notice Enable script executor with ID `_executorId` + * @param _executorId Identifier of the executor in the registry + */ + function enableScriptExecutor(uint256 _executorId) + public + authP(REGISTRY_MANAGER_ROLE, arr(_executorId)) + executorExists(_executorId) + { + ExecutorEntry storage executorEntry = executors[_executorId]; + require(!executorEntry.enabled, ERROR_EXECUTOR_ENABLED); + executorEntry.enabled = true; + emit EnableExecutor(_executorId, executorEntry.executor); + } + + /** + * @dev Get the script executor that can execute a particular script based on its first 4 bytes + * @param _script EVMScript being inspected + */ + function getScriptExecutor(bytes _script) public view returns (IEVMScriptExecutor) { + uint256 id = _script.getSpecId(); + + // Note that we don't need to check for an executor's existence in this case, as only + // existing executors can be enabled + ExecutorEntry storage entry = executors[id]; + return entry.enabled ? entry.executor : IEVMScriptExecutor(0); + } +} diff --git a/contracts/mutants/EVMScriptRegistry/4/MOD/EVMScriptRegistry.sol b/contracts/mutants/EVMScriptRegistry/4/MOD/EVMScriptRegistry.sol new file mode 100644 index 00000000000..75c1fb8ec0d --- /dev/null +++ b/contracts/mutants/EVMScriptRegistry/4/MOD/EVMScriptRegistry.sol @@ -0,0 +1,104 @@ +pragma solidity 0.4.24; + +import "../apps/AragonApp.sol"; +import "./ScriptHelpers.sol"; +import "./IEVMScriptExecutor.sol"; +import "./IEVMScriptRegistry.sol"; + + +/* solium-disable function-order */ +// Allow public initialize() to be first +contract EVMScriptRegistry is IEVMScriptRegistry, EVMScriptRegistryConstants, AragonApp { + using ScriptHelpers for bytes; + + // bytes32 public constant REGISTRY_ADD_EXECUTOR_ROLE = keccak256("REGISTRY_ADD_EXECUTOR_ROLE"); + bytes32 public constant REGISTRY_ADD_EXECUTOR_ROLE = 0xc4e90f38eea8c4212a009ca7b8947943ba4d4a58d19b683417f65291d1cd9ed2; + // WARN: Manager can censor all votes and the like happening in an org + // bytes32 public constant REGISTRY_MANAGER_ROLE = keccak256("REGISTRY_MANAGER_ROLE"); + bytes32 public constant REGISTRY_MANAGER_ROLE = 0xf7a450ef335e1892cb42c8ca72e7242359d7711924b75db5717410da3f614aa3; + + string private constant ERROR_INEXISTENT_EXECUTOR = "EVMREG_INEXISTENT_EXECUTOR"; + string private constant ERROR_EXECUTOR_ENABLED = "EVMREG_EXECUTOR_ENABLED"; + string private constant ERROR_EXECUTOR_DISABLED = "EVMREG_EXECUTOR_DISABLED"; + + struct ExecutorEntry { + IEVMScriptExecutor executor; + bool enabled; + } + + uint256 private executorsNextIndex; + mapping (uint256 => ExecutorEntry) public executors; + + event EnableExecutor(uint256 indexed executorId, address indexed executorAddress); + event DisableExecutor(uint256 indexed executorId, address indexed executorAddress); + + modifier executorExists(uint256 _executorId) { + require(_executorId > 0 && _executorId < executorsNextIndex, ERROR_INEXISTENT_EXECUTOR); + _; + } + + /** + * @notice Initialize the registry + */ + function initialize() public { + initialized(); + // Create empty record to begin executor IDs at 1 + executorsNextIndex = 1; + } + + /** + * @notice Add a new script executor with address `_executor` to the registry + * @param _executor Address of the IEVMScriptExecutor that will be added to the registry + * @return id Identifier of the executor in the registry + */ + function addScriptExecutor(IEVMScriptExecutor _executor) external returns (uint256 id) { + uint256 executorId = executorsNextIndex++; + executors[executorId] = ExecutorEntry(_executor, true); + emit EnableExecutor(executorId, _executor); + return executorId; + } + + /** + * @notice Disable script executor with ID `_executorId` + * @param _executorId Identifier of the executor in the registry + */ + function disableScriptExecutor(uint256 _executorId) + external + + { + // Note that we don't need to check for an executor's existence in this case, as only + // existing executors can be enabled + ExecutorEntry storage executorEntry = executors[_executorId]; + require(executorEntry.enabled, ERROR_EXECUTOR_DISABLED); + executorEntry.enabled = false; + emit DisableExecutor(_executorId, executorEntry.executor); + } + + /** + * @notice Enable script executor with ID `_executorId` + * @param _executorId Identifier of the executor in the registry + */ + function enableScriptExecutor(uint256 _executorId) + external + + executorExists(_executorId) + { + ExecutorEntry storage executorEntry = executors[_executorId]; + require(!executorEntry.enabled, ERROR_EXECUTOR_ENABLED); + executorEntry.enabled = true; + emit EnableExecutor(_executorId, executorEntry.executor); + } + + /** + * @dev Get the script executor that can execute a particular script based on its first 4 bytes + * @param _script EVMScript being inspected + */ + function getScriptExecutor(bytes _script) public view returns (IEVMScriptExecutor) { + uint256 id = _script.getSpecId(); + + // Note that we don't need to check for an executor's existence in this case, as only + // existing executors can be enabled + ExecutorEntry storage entry = executors[id]; + return entry.enabled ? entry.executor : IEVMScriptExecutor(0); + } +} diff --git a/contracts/mutants/EVMScriptRegistry/4/VVR/EVMScriptRegistry.sol b/contracts/mutants/EVMScriptRegistry/4/VVR/EVMScriptRegistry.sol new file mode 100644 index 00000000000..3f400cd3ee9 --- /dev/null +++ b/contracts/mutants/EVMScriptRegistry/4/VVR/EVMScriptRegistry.sol @@ -0,0 +1,104 @@ +pragma solidity 0.4.24; + +import "../apps/AragonApp.sol"; +import "./ScriptHelpers.sol"; +import "./IEVMScriptExecutor.sol"; +import "./IEVMScriptRegistry.sol"; + + +/* solium-disable function-order */ +// Allow public initialize() to be first +contract EVMScriptRegistry is IEVMScriptRegistry, EVMScriptRegistryConstants, AragonApp { + using ScriptHelpers for bytes; + + // bytes32 public constant REGISTRY_ADD_EXECUTOR_ROLE = keccak256("REGISTRY_ADD_EXECUTOR_ROLE"); + bytes32 internal constant REGISTRY_ADD_EXECUTOR_ROLE = 0xc4e90f38eea8c4212a009ca7b8947943ba4d4a58d19b683417f65291d1cd9ed2; + // WARN: Manager can censor all votes and the like happening in an org + // bytes32 public constant REGISTRY_MANAGER_ROLE = keccak256("REGISTRY_MANAGER_ROLE"); + bytes32 internal constant REGISTRY_MANAGER_ROLE = 0xf7a450ef335e1892cb42c8ca72e7242359d7711924b75db5717410da3f614aa3; + + string public constant ERROR_INEXISTENT_EXECUTOR = "EVMREG_INEXISTENT_EXECUTOR"; + string public constant ERROR_EXECUTOR_ENABLED = "EVMREG_EXECUTOR_ENABLED"; + string private constant ERROR_EXECUTOR_DISABLED = "EVMREG_EXECUTOR_DISABLED"; + + struct ExecutorEntry { + IEVMScriptExecutor executor; + bool enabled; + } + + uint256 private executorsNextIndex; + mapping (uint256 => ExecutorEntry) public executors; + + event EnableExecutor(uint256 indexed executorId, address indexed executorAddress); + event DisableExecutor(uint256 indexed executorId, address indexed executorAddress); + + modifier executorExists(uint256 _executorId) { + require(_executorId > 0 && _executorId < executorsNextIndex, ERROR_INEXISTENT_EXECUTOR); + _; + } + + /** + * @notice Initialize the registry + */ + function initialize() public onlyInit { + initialized(); + // Create empty record to begin executor IDs at 1 + executorsNextIndex = 1; + } + + /** + * @notice Add a new script executor with address `_executor` to the registry + * @param _executor Address of the IEVMScriptExecutor that will be added to the registry + * @return id Identifier of the executor in the registry + */ + function addScriptExecutor(IEVMScriptExecutor _executor) external auth(REGISTRY_ADD_EXECUTOR_ROLE) returns (uint256 id) { + uint256 executorId = executorsNextIndex++; + executors[executorId] = ExecutorEntry(_executor, true); + emit EnableExecutor(executorId, _executor); + return executorId; + } + + /** + * @notice Disable script executor with ID `_executorId` + * @param _executorId Identifier of the executor in the registry + */ + function disableScriptExecutor(uint256 _executorId) + external + authP(REGISTRY_MANAGER_ROLE, arr(_executorId)) + { + // Note that we don't need to check for an executor's existence in this case, as only + // existing executors can be enabled + ExecutorEntry storage executorEntry = executors[_executorId]; + require(executorEntry.enabled, ERROR_EXECUTOR_DISABLED); + executorEntry.enabled = false; + emit DisableExecutor(_executorId, executorEntry.executor); + } + + /** + * @notice Enable script executor with ID `_executorId` + * @param _executorId Identifier of the executor in the registry + */ + function enableScriptExecutor(uint256 _executorId) + external + authP(REGISTRY_MANAGER_ROLE, arr(_executorId)) + executorExists(_executorId) + { + ExecutorEntry storage executorEntry = executors[_executorId]; + require(!executorEntry.enabled, ERROR_EXECUTOR_ENABLED); + executorEntry.enabled = true; + emit EnableExecutor(_executorId, executorEntry.executor); + } + + /** + * @dev Get the script executor that can execute a particular script based on its first 4 bytes + * @param _script EVMScript being inspected + */ + function getScriptExecutor(bytes _script) public view returns (IEVMScriptExecutor) { + uint256 id = _script.getSpecId(); + + // Note that we don't need to check for an executor's existence in this case, as only + // existing executors can be enabled + ExecutorEntry storage entry = executors[id]; + return entry.enabled ? entry.executor : IEVMScriptExecutor(0); + } +} diff --git a/contracts/mutants/EVMScriptRegistry/5/FVR/EVMScriptRegistry.sol b/contracts/mutants/EVMScriptRegistry/5/FVR/EVMScriptRegistry.sol new file mode 100644 index 00000000000..a97a4032d16 --- /dev/null +++ b/contracts/mutants/EVMScriptRegistry/5/FVR/EVMScriptRegistry.sol @@ -0,0 +1,104 @@ +pragma solidity 0.4.24; + +import "../apps/AragonApp.sol"; +import "./ScriptHelpers.sol"; +import "./IEVMScriptExecutor.sol"; +import "./IEVMScriptRegistry.sol"; + + +/* solium-disable function-order */ +// Allow public initialize() to be first +contract EVMScriptRegistry is IEVMScriptRegistry, EVMScriptRegistryConstants, AragonApp { + using ScriptHelpers for bytes; + + // bytes32 public constant REGISTRY_ADD_EXECUTOR_ROLE = keccak256("REGISTRY_ADD_EXECUTOR_ROLE"); + bytes32 public constant REGISTRY_ADD_EXECUTOR_ROLE = 0xc4e90f38eea8c4212a009ca7b8947943ba4d4a58d19b683417f65291d1cd9ed2; + // WARN: Manager can censor all votes and the like happening in an org + // bytes32 public constant REGISTRY_MANAGER_ROLE = keccak256("REGISTRY_MANAGER_ROLE"); + bytes32 public constant REGISTRY_MANAGER_ROLE = 0xf7a450ef335e1892cb42c8ca72e7242359d7711924b75db5717410da3f614aa3; + + string private constant ERROR_INEXISTENT_EXECUTOR = "EVMREG_INEXISTENT_EXECUTOR"; + string private constant ERROR_EXECUTOR_ENABLED = "EVMREG_EXECUTOR_ENABLED"; + string private constant ERROR_EXECUTOR_DISABLED = "EVMREG_EXECUTOR_DISABLED"; + + struct ExecutorEntry { + IEVMScriptExecutor executor; + bool enabled; + } + + uint256 private executorsNextIndex; + mapping (uint256 => ExecutorEntry) public executors; + + event EnableExecutor(uint256 indexed executorId, address indexed executorAddress); + event DisableExecutor(uint256 indexed executorId, address indexed executorAddress); + + modifier executorExists(uint256 _executorId) { + require(_executorId > 0 && _executorId < executorsNextIndex, ERROR_INEXISTENT_EXECUTOR); + _; + } + + /** + * @notice Initialize the registry + */ + function initialize() external onlyInit { + initialized(); + // Create empty record to begin executor IDs at 1 + executorsNextIndex = 1; + } + + /** + * @notice Add a new script executor with address `_executor` to the registry + * @param _executor Address of the IEVMScriptExecutor that will be added to the registry + * @return id Identifier of the executor in the registry + */ + function addScriptExecutor(IEVMScriptExecutor _executor) public auth(REGISTRY_ADD_EXECUTOR_ROLE) returns (uint256 id) { + uint256 executorId = executorsNextIndex++; + executors[executorId] = ExecutorEntry(_executor, true); + emit EnableExecutor(executorId, _executor); + return executorId; + } + + /** + * @notice Disable script executor with ID `_executorId` + * @param _executorId Identifier of the executor in the registry + */ + function disableScriptExecutor(uint256 _executorId) + public + authP(REGISTRY_MANAGER_ROLE, arr(_executorId)) + { + // Note that we don't need to check for an executor's existence in this case, as only + // existing executors can be enabled + ExecutorEntry storage executorEntry = executors[_executorId]; + require(executorEntry.enabled, ERROR_EXECUTOR_DISABLED); + executorEntry.enabled = false; + emit DisableExecutor(_executorId, executorEntry.executor); + } + + /** + * @notice Enable script executor with ID `_executorId` + * @param _executorId Identifier of the executor in the registry + */ + function enableScriptExecutor(uint256 _executorId) + public + authP(REGISTRY_MANAGER_ROLE, arr(_executorId)) + executorExists(_executorId) + { + ExecutorEntry storage executorEntry = executors[_executorId]; + require(!executorEntry.enabled, ERROR_EXECUTOR_ENABLED); + executorEntry.enabled = true; + emit EnableExecutor(_executorId, executorEntry.executor); + } + + /** + * @dev Get the script executor that can execute a particular script based on its first 4 bytes + * @param _script EVMScript being inspected + */ + function getScriptExecutor(bytes _script) external view returns (IEVMScriptExecutor) { + uint256 id = _script.getSpecId(); + + // Note that we don't need to check for an executor's existence in this case, as only + // existing executors can be enabled + ExecutorEntry storage entry = executors[id]; + return entry.enabled ? entry.executor : IEVMScriptExecutor(0); + } +} diff --git a/contracts/mutants/EVMScriptRegistry/5/VVR/EVMScriptRegistry.sol b/contracts/mutants/EVMScriptRegistry/5/VVR/EVMScriptRegistry.sol new file mode 100644 index 00000000000..b0eb220c6ea --- /dev/null +++ b/contracts/mutants/EVMScriptRegistry/5/VVR/EVMScriptRegistry.sol @@ -0,0 +1,104 @@ +pragma solidity 0.4.24; + +import "../apps/AragonApp.sol"; +import "./ScriptHelpers.sol"; +import "./IEVMScriptExecutor.sol"; +import "./IEVMScriptRegistry.sol"; + + +/* solium-disable function-order */ +// Allow public initialize() to be first +contract EVMScriptRegistry is IEVMScriptRegistry, EVMScriptRegistryConstants, AragonApp { + using ScriptHelpers for bytes; + + // bytes32 public constant REGISTRY_ADD_EXECUTOR_ROLE = keccak256("REGISTRY_ADD_EXECUTOR_ROLE"); + bytes32 internal constant REGISTRY_ADD_EXECUTOR_ROLE = 0xc4e90f38eea8c4212a009ca7b8947943ba4d4a58d19b683417f65291d1cd9ed2; + // WARN: Manager can censor all votes and the like happening in an org + // bytes32 public constant REGISTRY_MANAGER_ROLE = keccak256("REGISTRY_MANAGER_ROLE"); + bytes32 internal constant REGISTRY_MANAGER_ROLE = 0xf7a450ef335e1892cb42c8ca72e7242359d7711924b75db5717410da3f614aa3; + + string public constant ERROR_INEXISTENT_EXECUTOR = "EVMREG_INEXISTENT_EXECUTOR"; + string public constant ERROR_EXECUTOR_ENABLED = "EVMREG_EXECUTOR_ENABLED"; + string public constant ERROR_EXECUTOR_DISABLED = "EVMREG_EXECUTOR_DISABLED"; + + struct ExecutorEntry { + IEVMScriptExecutor executor; + bool enabled; + } + + uint256 private executorsNextIndex; + mapping (uint256 => ExecutorEntry) public executors; + + event EnableExecutor(uint256 indexed executorId, address indexed executorAddress); + event DisableExecutor(uint256 indexed executorId, address indexed executorAddress); + + modifier executorExists(uint256 _executorId) { + require(_executorId > 0 && _executorId < executorsNextIndex, ERROR_INEXISTENT_EXECUTOR); + _; + } + + /** + * @notice Initialize the registry + */ + function initialize() public onlyInit { + initialized(); + // Create empty record to begin executor IDs at 1 + executorsNextIndex = 1; + } + + /** + * @notice Add a new script executor with address `_executor` to the registry + * @param _executor Address of the IEVMScriptExecutor that will be added to the registry + * @return id Identifier of the executor in the registry + */ + function addScriptExecutor(IEVMScriptExecutor _executor) external auth(REGISTRY_ADD_EXECUTOR_ROLE) returns (uint256 id) { + uint256 executorId = executorsNextIndex++; + executors[executorId] = ExecutorEntry(_executor, true); + emit EnableExecutor(executorId, _executor); + return executorId; + } + + /** + * @notice Disable script executor with ID `_executorId` + * @param _executorId Identifier of the executor in the registry + */ + function disableScriptExecutor(uint256 _executorId) + external + authP(REGISTRY_MANAGER_ROLE, arr(_executorId)) + { + // Note that we don't need to check for an executor's existence in this case, as only + // existing executors can be enabled + ExecutorEntry storage executorEntry = executors[_executorId]; + require(executorEntry.enabled, ERROR_EXECUTOR_DISABLED); + executorEntry.enabled = false; + emit DisableExecutor(_executorId, executorEntry.executor); + } + + /** + * @notice Enable script executor with ID `_executorId` + * @param _executorId Identifier of the executor in the registry + */ + function enableScriptExecutor(uint256 _executorId) + external + authP(REGISTRY_MANAGER_ROLE, arr(_executorId)) + executorExists(_executorId) + { + ExecutorEntry storage executorEntry = executors[_executorId]; + require(!executorEntry.enabled, ERROR_EXECUTOR_ENABLED); + executorEntry.enabled = true; + emit EnableExecutor(_executorId, executorEntry.executor); + } + + /** + * @dev Get the script executor that can execute a particular script based on its first 4 bytes + * @param _script EVMScript being inspected + */ + function getScriptExecutor(bytes _script) public view returns (IEVMScriptExecutor) { + uint256 id = _script.getSpecId(); + + // Note that we don't need to check for an executor's existence in this case, as only + // existing executors can be enabled + ExecutorEntry storage entry = executors[id]; + return entry.enabled ? entry.executor : IEVMScriptExecutor(0); + } +} diff --git a/contracts/mutants/EVMScriptRegistry/6/VVR/EVMScriptRegistry.sol b/contracts/mutants/EVMScriptRegistry/6/VVR/EVMScriptRegistry.sol new file mode 100644 index 00000000000..99b2d9137a7 --- /dev/null +++ b/contracts/mutants/EVMScriptRegistry/6/VVR/EVMScriptRegistry.sol @@ -0,0 +1,104 @@ +pragma solidity 0.4.24; + +import "../apps/AragonApp.sol"; +import "./ScriptHelpers.sol"; +import "./IEVMScriptExecutor.sol"; +import "./IEVMScriptRegistry.sol"; + + +/* solium-disable function-order */ +// Allow public initialize() to be first +contract EVMScriptRegistry is IEVMScriptRegistry, EVMScriptRegistryConstants, AragonApp { + using ScriptHelpers for bytes; + + // bytes32 public constant REGISTRY_ADD_EXECUTOR_ROLE = keccak256("REGISTRY_ADD_EXECUTOR_ROLE"); + bytes32 internal constant REGISTRY_ADD_EXECUTOR_ROLE = 0xc4e90f38eea8c4212a009ca7b8947943ba4d4a58d19b683417f65291d1cd9ed2; + // WARN: Manager can censor all votes and the like happening in an org + // bytes32 public constant REGISTRY_MANAGER_ROLE = keccak256("REGISTRY_MANAGER_ROLE"); + bytes32 internal constant REGISTRY_MANAGER_ROLE = 0xf7a450ef335e1892cb42c8ca72e7242359d7711924b75db5717410da3f614aa3; + + string public constant ERROR_INEXISTENT_EXECUTOR = "EVMREG_INEXISTENT_EXECUTOR"; + string public constant ERROR_EXECUTOR_ENABLED = "EVMREG_EXECUTOR_ENABLED"; + string public constant ERROR_EXECUTOR_DISABLED = "EVMREG_EXECUTOR_DISABLED"; + + struct ExecutorEntry { + IEVMScriptExecutor executor; + bool enabled; + } + + uint256 public executorsNextIndex; + mapping (uint256 => ExecutorEntry) public executors; + + event EnableExecutor(uint256 indexed executorId, address indexed executorAddress); + event DisableExecutor(uint256 indexed executorId, address indexed executorAddress); + + modifier executorExists(uint256 _executorId) { + require(_executorId > 0 && _executorId < executorsNextIndex, ERROR_INEXISTENT_EXECUTOR); + _; + } + + /** + * @notice Initialize the registry + */ + function initialize() public onlyInit { + initialized(); + // Create empty record to begin executor IDs at 1 + executorsNextIndex = 1; + } + + /** + * @notice Add a new script executor with address `_executor` to the registry + * @param _executor Address of the IEVMScriptExecutor that will be added to the registry + * @return id Identifier of the executor in the registry + */ + function addScriptExecutor(IEVMScriptExecutor _executor) external auth(REGISTRY_ADD_EXECUTOR_ROLE) returns (uint256 id) { + uint256 executorId = executorsNextIndex++; + executors[executorId] = ExecutorEntry(_executor, true); + emit EnableExecutor(executorId, _executor); + return executorId; + } + + /** + * @notice Disable script executor with ID `_executorId` + * @param _executorId Identifier of the executor in the registry + */ + function disableScriptExecutor(uint256 _executorId) + external + authP(REGISTRY_MANAGER_ROLE, arr(_executorId)) + { + // Note that we don't need to check for an executor's existence in this case, as only + // existing executors can be enabled + ExecutorEntry storage executorEntry = executors[_executorId]; + require(executorEntry.enabled, ERROR_EXECUTOR_DISABLED); + executorEntry.enabled = false; + emit DisableExecutor(_executorId, executorEntry.executor); + } + + /** + * @notice Enable script executor with ID `_executorId` + * @param _executorId Identifier of the executor in the registry + */ + function enableScriptExecutor(uint256 _executorId) + external + authP(REGISTRY_MANAGER_ROLE, arr(_executorId)) + executorExists(_executorId) + { + ExecutorEntry storage executorEntry = executors[_executorId]; + require(!executorEntry.enabled, ERROR_EXECUTOR_ENABLED); + executorEntry.enabled = true; + emit EnableExecutor(_executorId, executorEntry.executor); + } + + /** + * @dev Get the script executor that can execute a particular script based on its first 4 bytes + * @param _script EVMScript being inspected + */ + function getScriptExecutor(bytes _script) public view returns (IEVMScriptExecutor) { + uint256 id = _script.getSpecId(); + + // Note that we don't need to check for an executor's existence in this case, as only + // existing executors can be enabled + ExecutorEntry storage entry = executors[id]; + return entry.enabled ? entry.executor : IEVMScriptExecutor(0); + } +} diff --git a/contracts/mutants/EVMScriptRegistry/original/EVMScriptRegistry.sol b/contracts/mutants/EVMScriptRegistry/original/EVMScriptRegistry.sol new file mode 100644 index 00000000000..bc64c4653e6 --- /dev/null +++ b/contracts/mutants/EVMScriptRegistry/original/EVMScriptRegistry.sol @@ -0,0 +1,104 @@ +pragma solidity 0.4.24; + +import "../apps/AragonApp.sol"; +import "./ScriptHelpers.sol"; +import "./IEVMScriptExecutor.sol"; +import "./IEVMScriptRegistry.sol"; + + +/* solium-disable function-order */ +// Allow public initialize() to be first +contract EVMScriptRegistry is IEVMScriptRegistry, EVMScriptRegistryConstants, AragonApp { + using ScriptHelpers for bytes; + + // bytes32 public constant REGISTRY_ADD_EXECUTOR_ROLE = keccak256("REGISTRY_ADD_EXECUTOR_ROLE"); + bytes32 public constant REGISTRY_ADD_EXECUTOR_ROLE = 0xc4e90f38eea8c4212a009ca7b8947943ba4d4a58d19b683417f65291d1cd9ed2; + // WARN: Manager can censor all votes and the like happening in an org + // bytes32 public constant REGISTRY_MANAGER_ROLE = keccak256("REGISTRY_MANAGER_ROLE"); + bytes32 public constant REGISTRY_MANAGER_ROLE = 0xf7a450ef335e1892cb42c8ca72e7242359d7711924b75db5717410da3f614aa3; + + string private constant ERROR_INEXISTENT_EXECUTOR = "EVMREG_INEXISTENT_EXECUTOR"; + string private constant ERROR_EXECUTOR_ENABLED = "EVMREG_EXECUTOR_ENABLED"; + string private constant ERROR_EXECUTOR_DISABLED = "EVMREG_EXECUTOR_DISABLED"; + + struct ExecutorEntry { + IEVMScriptExecutor executor; + bool enabled; + } + + uint256 private executorsNextIndex; + mapping (uint256 => ExecutorEntry) public executors; + + event EnableExecutor(uint256 indexed executorId, address indexed executorAddress); + event DisableExecutor(uint256 indexed executorId, address indexed executorAddress); + + modifier executorExists(uint256 _executorId) { + require(_executorId > 0 && _executorId < executorsNextIndex, ERROR_INEXISTENT_EXECUTOR); + _; + } + + /** + * @notice Initialize the registry + */ + function initialize() public onlyInit { + initialized(); + // Create empty record to begin executor IDs at 1 + executorsNextIndex = 1; + } + + /** + * @notice Add a new script executor with address `_executor` to the registry + * @param _executor Address of the IEVMScriptExecutor that will be added to the registry + * @return id Identifier of the executor in the registry + */ + function addScriptExecutor(IEVMScriptExecutor _executor) external auth(REGISTRY_ADD_EXECUTOR_ROLE) returns (uint256 id) { + uint256 executorId = executorsNextIndex++; + executors[executorId] = ExecutorEntry(_executor, true); + emit EnableExecutor(executorId, _executor); + return executorId; + } + + /** + * @notice Disable script executor with ID `_executorId` + * @param _executorId Identifier of the executor in the registry + */ + function disableScriptExecutor(uint256 _executorId) + external + authP(REGISTRY_MANAGER_ROLE, arr(_executorId)) + { + // Note that we don't need to check for an executor's existence in this case, as only + // existing executors can be enabled + ExecutorEntry storage executorEntry = executors[_executorId]; + require(executorEntry.enabled, ERROR_EXECUTOR_DISABLED); + executorEntry.enabled = false; + emit DisableExecutor(_executorId, executorEntry.executor); + } + + /** + * @notice Enable script executor with ID `_executorId` + * @param _executorId Identifier of the executor in the registry + */ + function enableScriptExecutor(uint256 _executorId) + external + authP(REGISTRY_MANAGER_ROLE, arr(_executorId)) + executorExists(_executorId) + { + ExecutorEntry storage executorEntry = executors[_executorId]; + require(!executorEntry.enabled, ERROR_EXECUTOR_ENABLED); + executorEntry.enabled = true; + emit EnableExecutor(_executorId, executorEntry.executor); + } + + /** + * @dev Get the script executor that can execute a particular script based on its first 4 bytes + * @param _script EVMScript being inspected + */ + function getScriptExecutor(bytes _script) public view returns (IEVMScriptExecutor) { + uint256 id = _script.getSpecId(); + + // Note that we don't need to check for an executor's existence in this case, as only + // existing executors can be enabled + ExecutorEntry storage entry = executors[id]; + return entry.enabled ? entry.executor : IEVMScriptExecutor(0); + } +} diff --git a/contracts/mutants/EVMScriptRegistryFactory/1/BLR/EVMScriptRegistryFactory.sol b/contracts/mutants/EVMScriptRegistryFactory/1/BLR/EVMScriptRegistryFactory.sol new file mode 100644 index 00000000000..97bf36544d2 --- /dev/null +++ b/contracts/mutants/EVMScriptRegistryFactory/1/BLR/EVMScriptRegistryFactory.sol @@ -0,0 +1,38 @@ +pragma solidity 0.4.24; + +import "../evmscript/IEVMScriptExecutor.sol"; +import "../evmscript/EVMScriptRegistry.sol"; + +import "../evmscript/executors/CallsScript.sol"; + +import "./AppProxyFactory.sol"; +import "../kernel/Kernel.sol"; +import "../acl/ACL.sol"; + + +contract EVMScriptRegistryFactory is AppProxyFactory, EVMScriptRegistryConstants { + EVMScriptRegistry public baseReg; + IEVMScriptExecutor public baseCallScript; + + constructor() public { + baseReg = new EVMScriptRegistry(); + baseCallScript = IEVMScriptExecutor(new CallsScript()); + } + + function newEVMScriptRegistry(Kernel _dao) public returns (EVMScriptRegistry reg) { + bytes memory initPayload = abi.encodeWithSelector(reg.initialize.selector); + reg = EVMScriptRegistry(_dao.newPinnedAppInstance(EVMSCRIPT_REGISTRY_APP_ID, baseReg, initPayload, false)); + + ACL acl = ACL(_dao.acl()); + + acl.createPermission(this, reg, reg.REGISTRY_ADD_EXECUTOR_ROLE(), this); + + reg.addScriptExecutor(baseCallScript); // spec 1 = CallsScript + + // Clean up the permissions + acl.revokePermission(this, reg, reg.REGISTRY_ADD_EXECUTOR_ROLE()); + acl.removePermissionManager(reg, reg.REGISTRY_ADD_EXECUTOR_ROLE()); + + return reg; + } +} diff --git a/contracts/mutants/EVMScriptRegistryFactory/1/BLR/diff_result_difft.json b/contracts/mutants/EVMScriptRegistryFactory/1/BLR/diff_result_difft.json new file mode 100644 index 00000000000..236c0295289 --- /dev/null +++ b/contracts/mutants/EVMScriptRegistryFactory/1/BLR/diff_result_difft.json @@ -0,0 +1,32 @@ +{ + "number_of_changes": 1, + "timing": 0.176832914352417, + "diff_chunks": [ + [ + { + "lhs": { + "line_number": 23, + "changes": [ + { + "start": 107, + "end": 111, + "content": "true", + "highlight": "normal" + } + ] + }, + "rhs": { + "line_number": 23, + "changes": [ + { + "start": 107, + "end": 112, + "content": "false", + "highlight": "normal" + } + ] + } + } + ] + ] +} \ No newline at end of file diff --git a/contracts/mutants/EVMScriptRegistryFactory/1/CCD/EVMScriptRegistryFactory.sol b/contracts/mutants/EVMScriptRegistryFactory/1/CCD/EVMScriptRegistryFactory.sol new file mode 100644 index 00000000000..d46450b6442 --- /dev/null +++ b/contracts/mutants/EVMScriptRegistryFactory/1/CCD/EVMScriptRegistryFactory.sol @@ -0,0 +1,35 @@ +pragma solidity 0.4.24; + +import "../evmscript/IEVMScriptExecutor.sol"; +import "../evmscript/EVMScriptRegistry.sol"; + +import "../evmscript/executors/CallsScript.sol"; + +import "./AppProxyFactory.sol"; +import "../kernel/Kernel.sol"; +import "../acl/ACL.sol"; + + +contract EVMScriptRegistryFactory is AppProxyFactory, EVMScriptRegistryConstants { + EVMScriptRegistry public baseReg; + IEVMScriptExecutor public baseCallScript; + + + + function newEVMScriptRegistry(Kernel _dao) public returns (EVMScriptRegistry reg) { + bytes memory initPayload = abi.encodeWithSelector(reg.initialize.selector); + reg = EVMScriptRegistry(_dao.newPinnedAppInstance(EVMSCRIPT_REGISTRY_APP_ID, baseReg, initPayload, true)); + + ACL acl = ACL(_dao.acl()); + + acl.createPermission(this, reg, reg.REGISTRY_ADD_EXECUTOR_ROLE(), this); + + reg.addScriptExecutor(baseCallScript); // spec 1 = CallsScript + + // Clean up the permissions + acl.revokePermission(this, reg, reg.REGISTRY_ADD_EXECUTOR_ROLE()); + acl.removePermissionManager(reg, reg.REGISTRY_ADD_EXECUTOR_ROLE()); + + return reg; + } +} diff --git a/contracts/mutants/EVMScriptRegistryFactory/1/CCD/diff_result_difft.json b/contracts/mutants/EVMScriptRegistryFactory/1/CCD/diff_result_difft.json new file mode 100644 index 00000000000..151c6fb2fbb --- /dev/null +++ b/contracts/mutants/EVMScriptRegistryFactory/1/CCD/diff_result_difft.json @@ -0,0 +1,166 @@ +{ + "number_of_changes": 21, + "timing": 0.14766693115234375, + "diff_chunks": [ + [ + { + "lhs": { + "line_number": 16, + "changes": [ + { + "start": 4, + "end": 15, + "content": "constructor", + "highlight": "type" + }, + { + "start": 15, + "end": 16, + "content": "(", + "highlight": "delimiter" + }, + { + "start": 16, + "end": 17, + "content": ")", + "highlight": "delimiter" + }, + { + "start": 18, + "end": 24, + "content": "public", + "highlight": "keyword" + }, + { + "start": 25, + "end": 26, + "content": "{", + "highlight": "delimiter" + } + ] + }, + "rhs": { + "line_number": 16, + "changes": [] + } + }, + { + "lhs": { + "line_number": 19, + "changes": [ + { + "start": 4, + "end": 5, + "content": "}", + "highlight": "delimiter" + } + ] + } + }, + { + "lhs": { + "line_number": 17, + "changes": [ + { + "start": 8, + "end": 15, + "content": "baseReg", + "highlight": "normal" + }, + { + "start": 16, + "end": 17, + "content": "=", + "highlight": "normal" + }, + { + "start": 18, + "end": 21, + "content": "new", + "highlight": "keyword" + }, + { + "start": 22, + "end": 39, + "content": "EVMScriptRegistry", + "highlight": "type" + }, + { + "start": 39, + "end": 40, + "content": "(", + "highlight": "delimiter" + }, + { + "start": 40, + "end": 41, + "content": ")", + "highlight": "delimiter" + } + ] + } + }, + { + "lhs": { + "line_number": 18, + "changes": [ + { + "start": 8, + "end": 22, + "content": "baseCallScript", + "highlight": "normal" + }, + { + "start": 23, + "end": 24, + "content": "=", + "highlight": "normal" + }, + { + "start": 25, + "end": 43, + "content": "IEVMScriptExecutor", + "highlight": "normal" + }, + { + "start": 43, + "end": 44, + "content": "(", + "highlight": "delimiter" + }, + { + "start": 44, + "end": 47, + "content": "new", + "highlight": "keyword" + }, + { + "start": 48, + "end": 59, + "content": "CallsScript", + "highlight": "type" + }, + { + "start": 59, + "end": 60, + "content": "(", + "highlight": "delimiter" + }, + { + "start": 60, + "end": 61, + "content": ")", + "highlight": "delimiter" + }, + { + "start": 61, + "end": 62, + "content": ")", + "highlight": "delimiter" + } + ] + } + } + ] + ] +} \ No newline at end of file diff --git a/contracts/mutants/EVMScriptRegistryFactory/1/DLR/EVMScriptRegistryFactory.sol b/contracts/mutants/EVMScriptRegistryFactory/1/DLR/EVMScriptRegistryFactory.sol new file mode 100644 index 00000000000..f63a7caf179 --- /dev/null +++ b/contracts/mutants/EVMScriptRegistryFactory/1/DLR/EVMScriptRegistryFactory.sol @@ -0,0 +1,38 @@ +pragma solidity 0.4.24; + +import "../evmscript/IEVMScriptExecutor.sol"; +import "../evmscript/EVMScriptRegistry.sol"; + +import "../evmscript/executors/CallsScript.sol"; + +import "./AppProxyFactory.sol"; +import "../kernel/Kernel.sol"; +import "../acl/ACL.sol"; + + +contract EVMScriptRegistryFactory is AppProxyFactory, EVMScriptRegistryConstants { + EVMScriptRegistry public baseReg; + IEVMScriptExecutor public baseCallScript; + + constructor() public { + baseReg = new EVMScriptRegistry(); + baseCallScript = IEVMScriptExecutor(new CallsScript()); + } + + function newEVMScriptRegistry(Kernel _dao) public returns (EVMScriptRegistry reg) { + bytes storage initPayload = abi.encodeWithSelector(reg.initialize.selector); + reg = EVMScriptRegistry(_dao.newPinnedAppInstance(EVMSCRIPT_REGISTRY_APP_ID, baseReg, initPayload, true)); + + ACL acl = ACL(_dao.acl()); + + acl.createPermission(this, reg, reg.REGISTRY_ADD_EXECUTOR_ROLE(), this); + + reg.addScriptExecutor(baseCallScript); // spec 1 = CallsScript + + // Clean up the permissions + acl.revokePermission(this, reg, reg.REGISTRY_ADD_EXECUTOR_ROLE()); + acl.removePermissionManager(reg, reg.REGISTRY_ADD_EXECUTOR_ROLE()); + + return reg; + } +} diff --git a/contracts/mutants/EVMScriptRegistryFactory/1/DLR/diff_result_difft.json b/contracts/mutants/EVMScriptRegistryFactory/1/DLR/diff_result_difft.json new file mode 100644 index 00000000000..676f0876e35 --- /dev/null +++ b/contracts/mutants/EVMScriptRegistryFactory/1/DLR/diff_result_difft.json @@ -0,0 +1,32 @@ +{ + "number_of_changes": 1, + "timing": 0.16121697425842285, + "diff_chunks": [ + [ + { + "lhs": { + "line_number": 22, + "changes": [ + { + "start": 14, + "end": 20, + "content": "memory", + "highlight": "keyword" + } + ] + }, + "rhs": { + "line_number": 22, + "changes": [ + { + "start": 14, + "end": 21, + "content": "storage", + "highlight": "keyword" + } + ] + } + } + ] + ] +} \ No newline at end of file diff --git a/contracts/mutants/EVMScriptRegistryFactory/1/FVR/EVMScriptRegistryFactory.sol b/contracts/mutants/EVMScriptRegistryFactory/1/FVR/EVMScriptRegistryFactory.sol new file mode 100644 index 00000000000..8504b841ac1 --- /dev/null +++ b/contracts/mutants/EVMScriptRegistryFactory/1/FVR/EVMScriptRegistryFactory.sol @@ -0,0 +1,38 @@ +pragma solidity 0.4.24; + +import "../evmscript/IEVMScriptExecutor.sol"; +import "../evmscript/EVMScriptRegistry.sol"; + +import "../evmscript/executors/CallsScript.sol"; + +import "./AppProxyFactory.sol"; +import "../kernel/Kernel.sol"; +import "../acl/ACL.sol"; + + +contract EVMScriptRegistryFactory is AppProxyFactory, EVMScriptRegistryConstants { + EVMScriptRegistry public baseReg; + IEVMScriptExecutor public baseCallScript; + + constructor() internal { + baseReg = new EVMScriptRegistry(); + baseCallScript = IEVMScriptExecutor(new CallsScript()); + } + + function newEVMScriptRegistry(Kernel _dao) public returns (EVMScriptRegistry reg) { + bytes memory initPayload = abi.encodeWithSelector(reg.initialize.selector); + reg = EVMScriptRegistry(_dao.newPinnedAppInstance(EVMSCRIPT_REGISTRY_APP_ID, baseReg, initPayload, true)); + + ACL acl = ACL(_dao.acl()); + + acl.createPermission(this, reg, reg.REGISTRY_ADD_EXECUTOR_ROLE(), this); + + reg.addScriptExecutor(baseCallScript); // spec 1 = CallsScript + + // Clean up the permissions + acl.revokePermission(this, reg, reg.REGISTRY_ADD_EXECUTOR_ROLE()); + acl.removePermissionManager(reg, reg.REGISTRY_ADD_EXECUTOR_ROLE()); + + return reg; + } +} diff --git a/contracts/mutants/EVMScriptRegistryFactory/1/FVR/diff_result_difft.json b/contracts/mutants/EVMScriptRegistryFactory/1/FVR/diff_result_difft.json new file mode 100644 index 00000000000..cf77a9598ae --- /dev/null +++ b/contracts/mutants/EVMScriptRegistryFactory/1/FVR/diff_result_difft.json @@ -0,0 +1,32 @@ +{ + "number_of_changes": 1, + "timing": 0.09128165245056152, + "diff_chunks": [ + [ + { + "lhs": { + "line_number": 16, + "changes": [ + { + "start": 18, + "end": 24, + "content": "public", + "highlight": "keyword" + } + ] + }, + "rhs": { + "line_number": 16, + "changes": [ + { + "start": 18, + "end": 26, + "content": "internal", + "highlight": "keyword" + } + ] + } + } + ] + ] +} \ No newline at end of file diff --git a/contracts/mutants/EVMScriptRegistryFactory/1/RSD/EVMScriptRegistryFactory.sol b/contracts/mutants/EVMScriptRegistryFactory/1/RSD/EVMScriptRegistryFactory.sol new file mode 100644 index 00000000000..55ce456f3fc --- /dev/null +++ b/contracts/mutants/EVMScriptRegistryFactory/1/RSD/EVMScriptRegistryFactory.sol @@ -0,0 +1,38 @@ +pragma solidity 0.4.24; + +import "../evmscript/IEVMScriptExecutor.sol"; +import "../evmscript/EVMScriptRegistry.sol"; + +import "../evmscript/executors/CallsScript.sol"; + +import "./AppProxyFactory.sol"; +import "../kernel/Kernel.sol"; +import "../acl/ACL.sol"; + + +contract EVMScriptRegistryFactory is AppProxyFactory, EVMScriptRegistryConstants { + EVMScriptRegistry public baseReg; + IEVMScriptExecutor public baseCallScript; + + constructor() public { + baseReg = new EVMScriptRegistry(); + baseCallScript = IEVMScriptExecutor(new CallsScript()); + } + + function newEVMScriptRegistry(Kernel _dao) public returns (EVMScriptRegistry reg) { + bytes memory initPayload = abi.encodeWithSelector(reg.initialize.selector); + reg = EVMScriptRegistry(_dao.newPinnedAppInstance(EVMSCRIPT_REGISTRY_APP_ID, baseReg, initPayload, true)); + + ACL acl = ACL(_dao.acl()); + + acl.createPermission(this, reg, reg.REGISTRY_ADD_EXECUTOR_ROLE(), this); + + reg.addScriptExecutor(baseCallScript); // spec 1 = CallsScript + + // Clean up the permissions + acl.revokePermission(this, reg, reg.REGISTRY_ADD_EXECUTOR_ROLE()); + acl.removePermissionManager(reg, reg.REGISTRY_ADD_EXECUTOR_ROLE()); + + /* return reg; */ + } +} diff --git a/contracts/mutants/EVMScriptRegistryFactory/1/RSD/diff_result_difft.json b/contracts/mutants/EVMScriptRegistryFactory/1/RSD/diff_result_difft.json new file mode 100644 index 00000000000..4e563cba3b0 --- /dev/null +++ b/contracts/mutants/EVMScriptRegistryFactory/1/RSD/diff_result_difft.json @@ -0,0 +1,38 @@ +{ + "number_of_changes": 2, + "timing": 0.18663525581359863, + "diff_chunks": [ + [ + { + "lhs": { + "line_number": 35, + "changes": [ + { + "start": 8, + "end": 14, + "content": "return", + "highlight": "keyword" + }, + { + "start": 15, + "end": 18, + "content": "reg", + "highlight": "normal" + } + ] + }, + "rhs": { + "line_number": 35, + "changes": [ + { + "start": 8, + "end": 25, + "content": "/* return reg; */", + "highlight": "comment" + } + ] + } + } + ] + ] +} \ No newline at end of file diff --git a/contracts/mutants/EVMScriptRegistryFactory/1/VVR/EVMScriptRegistryFactory.sol b/contracts/mutants/EVMScriptRegistryFactory/1/VVR/EVMScriptRegistryFactory.sol new file mode 100644 index 00000000000..a61418b37ef --- /dev/null +++ b/contracts/mutants/EVMScriptRegistryFactory/1/VVR/EVMScriptRegistryFactory.sol @@ -0,0 +1,38 @@ +pragma solidity 0.4.24; + +import "../evmscript/IEVMScriptExecutor.sol"; +import "../evmscript/EVMScriptRegistry.sol"; + +import "../evmscript/executors/CallsScript.sol"; + +import "./AppProxyFactory.sol"; +import "../kernel/Kernel.sol"; +import "../acl/ACL.sol"; + + +contract EVMScriptRegistryFactory is AppProxyFactory, EVMScriptRegistryConstants { + EVMScriptRegistry internal baseReg; + IEVMScriptExecutor public baseCallScript; + + constructor() public { + baseReg = new EVMScriptRegistry(); + baseCallScript = IEVMScriptExecutor(new CallsScript()); + } + + function newEVMScriptRegistry(Kernel _dao) public returns (EVMScriptRegistry reg) { + bytes memory initPayload = abi.encodeWithSelector(reg.initialize.selector); + reg = EVMScriptRegistry(_dao.newPinnedAppInstance(EVMSCRIPT_REGISTRY_APP_ID, baseReg, initPayload, true)); + + ACL acl = ACL(_dao.acl()); + + acl.createPermission(this, reg, reg.REGISTRY_ADD_EXECUTOR_ROLE(), this); + + reg.addScriptExecutor(baseCallScript); // spec 1 = CallsScript + + // Clean up the permissions + acl.revokePermission(this, reg, reg.REGISTRY_ADD_EXECUTOR_ROLE()); + acl.removePermissionManager(reg, reg.REGISTRY_ADD_EXECUTOR_ROLE()); + + return reg; + } +} diff --git a/contracts/mutants/EVMScriptRegistryFactory/1/VVR/diff_result_difft.json b/contracts/mutants/EVMScriptRegistryFactory/1/VVR/diff_result_difft.json new file mode 100644 index 00000000000..d297bd7e386 --- /dev/null +++ b/contracts/mutants/EVMScriptRegistryFactory/1/VVR/diff_result_difft.json @@ -0,0 +1,32 @@ +{ + "number_of_changes": 1, + "timing": 0.20626401901245117, + "diff_chunks": [ + [ + { + "lhs": { + "line_number": 13, + "changes": [ + { + "start": 22, + "end": 28, + "content": "public", + "highlight": "keyword" + } + ] + }, + "rhs": { + "line_number": 13, + "changes": [ + { + "start": 22, + "end": 30, + "content": "internal", + "highlight": "keyword" + } + ] + } + } + ] + ] +} \ No newline at end of file diff --git a/contracts/mutants/EVMScriptRegistryFactory/2/FVR/EVMScriptRegistryFactory.sol b/contracts/mutants/EVMScriptRegistryFactory/2/FVR/EVMScriptRegistryFactory.sol new file mode 100644 index 00000000000..75abdad8471 --- /dev/null +++ b/contracts/mutants/EVMScriptRegistryFactory/2/FVR/EVMScriptRegistryFactory.sol @@ -0,0 +1,38 @@ +pragma solidity 0.4.24; + +import "../evmscript/IEVMScriptExecutor.sol"; +import "../evmscript/EVMScriptRegistry.sol"; + +import "../evmscript/executors/CallsScript.sol"; + +import "./AppProxyFactory.sol"; +import "../kernel/Kernel.sol"; +import "../acl/ACL.sol"; + + +contract EVMScriptRegistryFactory is AppProxyFactory, EVMScriptRegistryConstants { + EVMScriptRegistry public baseReg; + IEVMScriptExecutor public baseCallScript; + + constructor() internal { + baseReg = new EVMScriptRegistry(); + baseCallScript = IEVMScriptExecutor(new CallsScript()); + } + + function newEVMScriptRegistry(Kernel _dao) external returns (EVMScriptRegistry reg) { + bytes memory initPayload = abi.encodeWithSelector(reg.initialize.selector); + reg = EVMScriptRegistry(_dao.newPinnedAppInstance(EVMSCRIPT_REGISTRY_APP_ID, baseReg, initPayload, true)); + + ACL acl = ACL(_dao.acl()); + + acl.createPermission(this, reg, reg.REGISTRY_ADD_EXECUTOR_ROLE(), this); + + reg.addScriptExecutor(baseCallScript); // spec 1 = CallsScript + + // Clean up the permissions + acl.revokePermission(this, reg, reg.REGISTRY_ADD_EXECUTOR_ROLE()); + acl.removePermissionManager(reg, reg.REGISTRY_ADD_EXECUTOR_ROLE()); + + return reg; + } +} diff --git a/contracts/mutants/EVMScriptRegistryFactory/2/FVR/diff_result_difft.json b/contracts/mutants/EVMScriptRegistryFactory/2/FVR/diff_result_difft.json new file mode 100644 index 00000000000..a86d8e338c8 --- /dev/null +++ b/contracts/mutants/EVMScriptRegistryFactory/2/FVR/diff_result_difft.json @@ -0,0 +1,58 @@ +{ + "number_of_changes": 2, + "timing": 0.22481417655944824, + "diff_chunks": [ + [ + { + "lhs": { + "line_number": 16, + "changes": [ + { + "start": 18, + "end": 24, + "content": "public", + "highlight": "keyword" + } + ] + }, + "rhs": { + "line_number": 16, + "changes": [ + { + "start": 18, + "end": 26, + "content": "internal", + "highlight": "keyword" + } + ] + } + } + ], + [ + { + "lhs": { + "line_number": 21, + "changes": [ + { + "start": 47, + "end": 53, + "content": "public", + "highlight": "keyword" + } + ] + }, + "rhs": { + "line_number": 21, + "changes": [ + { + "start": 47, + "end": 55, + "content": "external", + "highlight": "keyword" + } + ] + } + } + ] + ] +} \ No newline at end of file diff --git a/contracts/mutants/EVMScriptRegistryFactory/2/VVR/EVMScriptRegistryFactory.sol b/contracts/mutants/EVMScriptRegistryFactory/2/VVR/EVMScriptRegistryFactory.sol new file mode 100644 index 00000000000..4b7fe196cf3 --- /dev/null +++ b/contracts/mutants/EVMScriptRegistryFactory/2/VVR/EVMScriptRegistryFactory.sol @@ -0,0 +1,38 @@ +pragma solidity 0.4.24; + +import "../evmscript/IEVMScriptExecutor.sol"; +import "../evmscript/EVMScriptRegistry.sol"; + +import "../evmscript/executors/CallsScript.sol"; + +import "./AppProxyFactory.sol"; +import "../kernel/Kernel.sol"; +import "../acl/ACL.sol"; + + +contract EVMScriptRegistryFactory is AppProxyFactory, EVMScriptRegistryConstants { + EVMScriptRegistry internal baseReg; + IEVMScriptExecutor internal baseCallScript; + + constructor() public { + baseReg = new EVMScriptRegistry(); + baseCallScript = IEVMScriptExecutor(new CallsScript()); + } + + function newEVMScriptRegistry(Kernel _dao) public returns (EVMScriptRegistry reg) { + bytes memory initPayload = abi.encodeWithSelector(reg.initialize.selector); + reg = EVMScriptRegistry(_dao.newPinnedAppInstance(EVMSCRIPT_REGISTRY_APP_ID, baseReg, initPayload, true)); + + ACL acl = ACL(_dao.acl()); + + acl.createPermission(this, reg, reg.REGISTRY_ADD_EXECUTOR_ROLE(), this); + + reg.addScriptExecutor(baseCallScript); // spec 1 = CallsScript + + // Clean up the permissions + acl.revokePermission(this, reg, reg.REGISTRY_ADD_EXECUTOR_ROLE()); + acl.removePermissionManager(reg, reg.REGISTRY_ADD_EXECUTOR_ROLE()); + + return reg; + } +} diff --git a/contracts/mutants/EVMScriptRegistryFactory/2/VVR/diff_result_difft.json b/contracts/mutants/EVMScriptRegistryFactory/2/VVR/diff_result_difft.json new file mode 100644 index 00000000000..7aaf91e98e1 --- /dev/null +++ b/contracts/mutants/EVMScriptRegistryFactory/2/VVR/diff_result_difft.json @@ -0,0 +1,56 @@ +{ + "number_of_changes": 2, + "timing": 0.309830904006958, + "diff_chunks": [ + [ + { + "lhs": { + "line_number": 14, + "changes": [ + { + "start": 23, + "end": 29, + "content": "public", + "highlight": "keyword" + } + ] + }, + "rhs": { + "line_number": 14, + "changes": [ + { + "start": 23, + "end": 31, + "content": "internal", + "highlight": "keyword" + } + ] + } + }, + { + "lhs": { + "line_number": 13, + "changes": [ + { + "start": 22, + "end": 28, + "content": "public", + "highlight": "keyword" + } + ] + }, + "rhs": { + "line_number": 13, + "changes": [ + { + "start": 22, + "end": 30, + "content": "internal", + "highlight": "keyword" + } + ] + } + } + ] + ] +} \ No newline at end of file diff --git a/contracts/mutants/EVMScriptRegistryFactory/original/EVMScriptRegistryFactory.sol b/contracts/mutants/EVMScriptRegistryFactory/original/EVMScriptRegistryFactory.sol new file mode 100644 index 00000000000..329dd738c29 --- /dev/null +++ b/contracts/mutants/EVMScriptRegistryFactory/original/EVMScriptRegistryFactory.sol @@ -0,0 +1,38 @@ +pragma solidity 0.4.24; + +import "../evmscript/IEVMScriptExecutor.sol"; +import "../evmscript/EVMScriptRegistry.sol"; + +import "../evmscript/executors/CallsScript.sol"; + +import "./AppProxyFactory.sol"; +import "../kernel/Kernel.sol"; +import "../acl/ACL.sol"; + + +contract EVMScriptRegistryFactory is AppProxyFactory, EVMScriptRegistryConstants { + EVMScriptRegistry public baseReg; + IEVMScriptExecutor public baseCallScript; + + constructor() public { + baseReg = new EVMScriptRegistry(); + baseCallScript = IEVMScriptExecutor(new CallsScript()); + } + + function newEVMScriptRegistry(Kernel _dao) public returns (EVMScriptRegistry reg) { + bytes memory initPayload = abi.encodeWithSelector(reg.initialize.selector); + reg = EVMScriptRegistry(_dao.newPinnedAppInstance(EVMSCRIPT_REGISTRY_APP_ID, baseReg, initPayload, true)); + + ACL acl = ACL(_dao.acl()); + + acl.createPermission(this, reg, reg.REGISTRY_ADD_EXECUTOR_ROLE(), this); + + reg.addScriptExecutor(baseCallScript); // spec 1 = CallsScript + + // Clean up the permissions + acl.revokePermission(this, reg, reg.REGISTRY_ADD_EXECUTOR_ROLE()); + acl.removePermissionManager(reg, reg.REGISTRY_ADD_EXECUTOR_ROLE()); + + return reg; + } +} diff --git a/contracts/mutants/EVMScriptRunner/1/BOR/EVMScriptRunner.sol b/contracts/mutants/EVMScriptRunner/1/BOR/EVMScriptRunner.sol new file mode 100644 index 00000000000..8779f2c89de --- /dev/null +++ b/contracts/mutants/EVMScriptRunner/1/BOR/EVMScriptRunner.sol @@ -0,0 +1,76 @@ +/* + * SPDX-License-Identitifer: MIT + */ + +pragma solidity ^0.4.24; + +import "./IEVMScriptExecutor.sol"; +import "./IEVMScriptRegistry.sol"; + +import "../apps/AppStorage.sol"; +import "../kernel/KernelConstants.sol"; +import "../common/Initializable.sol"; + + +contract EVMScriptRunner is AppStorage, Initializable, EVMScriptRegistryConstants, KernelConstants { + string private constant ERROR_EXECUTOR_UNAVAILABLE = "EVMRUN_EXECUTOR_UNAVAILABLE"; + string private constant ERROR_EXECUTION_REVERTED = "EVMRUN_EXECUTION_REVERTED"; + string private constant ERROR_PROTECTED_STATE_MODIFIED = "EVMRUN_PROTECTED_STATE_MODIFIED"; + + event ScriptResult(address indexed executor, bytes script, bytes input, bytes returnData); + + function getExecutor(bytes _script) public view returns (IEVMScriptExecutor) { + return IEVMScriptExecutor(getExecutorRegistry().getScriptExecutor(_script)); + } + + function runScript(bytes _script, bytes _input, address[] _blacklist) + internal + isInitialized + protectState + returns (bytes) + { + // TODO: Too much data flying around, maybe extracting spec id here is cheaper + IEVMScriptExecutor executor = getExecutor(_script); + require(address(executor) > address(0), ERROR_EXECUTOR_UNAVAILABLE); + + bytes4 sig = executor.execScript.selector; + bytes memory calldata = abi.encodeWithSelector(sig, _script, _input, _blacklist); + require(address(executor).delegatecall(calldata), ERROR_EXECUTION_REVERTED); + + bytes memory output = returnedDataDecoded(); + + emit ScriptResult(address(executor), _script, _input, output); + + return output; + } + + function getExecutorRegistry() internal view returns (IEVMScriptRegistry) { + address registryAddr = kernel().getApp(APP_ADDR_NAMESPACE, EVMSCRIPT_REGISTRY_APP_ID); + return IEVMScriptRegistry(registryAddr); + } + + /** + * @dev copies and returns last's call data. Needs to ABI decode first + */ + function returnedDataDecoded() internal pure returns (bytes ret) { + assembly { + let size := returndatasize + switch size + case 0 {} + default { + ret := mload(0x40) // free mem ptr get + mstore(0x40, add(ret, add(size, 0x20))) // free mem ptr set + returndatacopy(ret, 0x20, sub(size, 0x20)) // copy return data + } + } + return ret; + } + + modifier protectState { + address preKernel = address(kernel()); + bytes32 preAppId = appId(); + _; // exec + require(address(kernel()) == preKernel, ERROR_PROTECTED_STATE_MODIFIED); + require(appId() == preAppId, ERROR_PROTECTED_STATE_MODIFIED); + } +} diff --git a/contracts/mutants/EVMScriptRunner/1/DLR/EVMScriptRunner.sol b/contracts/mutants/EVMScriptRunner/1/DLR/EVMScriptRunner.sol new file mode 100644 index 00000000000..7d3c3774bf2 --- /dev/null +++ b/contracts/mutants/EVMScriptRunner/1/DLR/EVMScriptRunner.sol @@ -0,0 +1,76 @@ +/* + * SPDX-License-Identitifer: MIT + */ + +pragma solidity ^0.4.24; + +import "./IEVMScriptExecutor.sol"; +import "./IEVMScriptRegistry.sol"; + +import "../apps/AppStorage.sol"; +import "../kernel/KernelConstants.sol"; +import "../common/Initializable.sol"; + + +contract EVMScriptRunner is AppStorage, Initializable, EVMScriptRegistryConstants, KernelConstants { + string private constant ERROR_EXECUTOR_UNAVAILABLE = "EVMRUN_EXECUTOR_UNAVAILABLE"; + string private constant ERROR_EXECUTION_REVERTED = "EVMRUN_EXECUTION_REVERTED"; + string private constant ERROR_PROTECTED_STATE_MODIFIED = "EVMRUN_PROTECTED_STATE_MODIFIED"; + + event ScriptResult(address indexed executor, bytes script, bytes input, bytes returnData); + + function getExecutor(bytes _script) public view returns (IEVMScriptExecutor) { + return IEVMScriptExecutor(getExecutorRegistry().getScriptExecutor(_script)); + } + + function runScript(bytes _script, bytes _input, address[] _blacklist) + internal + isInitialized + protectState + returns (bytes) + { + // TODO: Too much data flying around, maybe extracting spec id here is cheaper + IEVMScriptExecutor executor = getExecutor(_script); + require(address(executor) != address(0), ERROR_EXECUTOR_UNAVAILABLE); + + bytes4 sig = executor.execScript.selector; + bytes storage calldata = abi.encodeWithSelector(sig, _script, _input, _blacklist); + require(address(executor).delegatecall(calldata), ERROR_EXECUTION_REVERTED); + + bytes memory output = returnedDataDecoded(); + + emit ScriptResult(address(executor), _script, _input, output); + + return output; + } + + function getExecutorRegistry() internal view returns (IEVMScriptRegistry) { + address registryAddr = kernel().getApp(APP_ADDR_NAMESPACE, EVMSCRIPT_REGISTRY_APP_ID); + return IEVMScriptRegistry(registryAddr); + } + + /** + * @dev copies and returns last's call data. Needs to ABI decode first + */ + function returnedDataDecoded() internal pure returns (bytes ret) { + assembly { + let size := returndatasize + switch size + case 0 {} + default { + ret := mload(0x40) // free mem ptr get + mstore(0x40, add(ret, add(size, 0x20))) // free mem ptr set + returndatacopy(ret, 0x20, sub(size, 0x20)) // copy return data + } + } + return ret; + } + + modifier protectState { + address preKernel = address(kernel()); + bytes32 preAppId = appId(); + _; // exec + require(address(kernel()) == preKernel, ERROR_PROTECTED_STATE_MODIFIED); + require(appId() == preAppId, ERROR_PROTECTED_STATE_MODIFIED); + } +} diff --git a/contracts/mutants/EVMScriptRunner/1/EED/EVMScriptRunner.sol b/contracts/mutants/EVMScriptRunner/1/EED/EVMScriptRunner.sol new file mode 100644 index 00000000000..a426128ac5f --- /dev/null +++ b/contracts/mutants/EVMScriptRunner/1/EED/EVMScriptRunner.sol @@ -0,0 +1,76 @@ +/* + * SPDX-License-Identitifer: MIT + */ + +pragma solidity ^0.4.24; + +import "./IEVMScriptExecutor.sol"; +import "./IEVMScriptRegistry.sol"; + +import "../apps/AppStorage.sol"; +import "../kernel/KernelConstants.sol"; +import "../common/Initializable.sol"; + + +contract EVMScriptRunner is AppStorage, Initializable, EVMScriptRegistryConstants, KernelConstants { + string private constant ERROR_EXECUTOR_UNAVAILABLE = "EVMRUN_EXECUTOR_UNAVAILABLE"; + string private constant ERROR_EXECUTION_REVERTED = "EVMRUN_EXECUTION_REVERTED"; + string private constant ERROR_PROTECTED_STATE_MODIFIED = "EVMRUN_PROTECTED_STATE_MODIFIED"; + + event ScriptResult(address indexed executor, bytes script, bytes input, bytes returnData); + + function getExecutor(bytes _script) public view returns (IEVMScriptExecutor) { + return IEVMScriptExecutor(getExecutorRegistry().getScriptExecutor(_script)); + } + + function runScript(bytes _script, bytes _input, address[] _blacklist) + internal + isInitialized + protectState + returns (bytes) + { + // TODO: Too much data flying around, maybe extracting spec id here is cheaper + IEVMScriptExecutor executor = getExecutor(_script); + require(address(executor) != address(0), ERROR_EXECUTOR_UNAVAILABLE); + + bytes4 sig = executor.execScript.selector; + bytes memory calldata = abi.encodeWithSelector(sig, _script, _input, _blacklist); + require(address(executor).delegatecall(calldata), ERROR_EXECUTION_REVERTED); + + bytes memory output = returnedDataDecoded(); + + /* emit ScriptResult(address(executor), _script, _input, output); */ + + return output; + } + + function getExecutorRegistry() internal view returns (IEVMScriptRegistry) { + address registryAddr = kernel().getApp(APP_ADDR_NAMESPACE, EVMSCRIPT_REGISTRY_APP_ID); + return IEVMScriptRegistry(registryAddr); + } + + /** + * @dev copies and returns last's call data. Needs to ABI decode first + */ + function returnedDataDecoded() internal pure returns (bytes ret) { + assembly { + let size := returndatasize + switch size + case 0 {} + default { + ret := mload(0x40) // free mem ptr get + mstore(0x40, add(ret, add(size, 0x20))) // free mem ptr set + returndatacopy(ret, 0x20, sub(size, 0x20)) // copy return data + } + } + return ret; + } + + modifier protectState { + address preKernel = address(kernel()); + bytes32 preAppId = appId(); + _; // exec + require(address(kernel()) == preKernel, ERROR_PROTECTED_STATE_MODIFIED); + require(appId() == preAppId, ERROR_PROTECTED_STATE_MODIFIED); + } +} diff --git a/contracts/mutants/EVMScriptRunner/1/EHC/EVMScriptRunner.sol b/contracts/mutants/EVMScriptRunner/1/EHC/EVMScriptRunner.sol new file mode 100644 index 00000000000..71d5a364942 --- /dev/null +++ b/contracts/mutants/EVMScriptRunner/1/EHC/EVMScriptRunner.sol @@ -0,0 +1,76 @@ +/* + * SPDX-License-Identitifer: MIT + */ + +pragma solidity ^0.4.24; + +import "./IEVMScriptExecutor.sol"; +import "./IEVMScriptRegistry.sol"; + +import "../apps/AppStorage.sol"; +import "../kernel/KernelConstants.sol"; +import "../common/Initializable.sol"; + + +contract EVMScriptRunner is AppStorage, Initializable, EVMScriptRegistryConstants, KernelConstants { + string private constant ERROR_EXECUTOR_UNAVAILABLE = "EVMRUN_EXECUTOR_UNAVAILABLE"; + string private constant ERROR_EXECUTION_REVERTED = "EVMRUN_EXECUTION_REVERTED"; + string private constant ERROR_PROTECTED_STATE_MODIFIED = "EVMRUN_PROTECTED_STATE_MODIFIED"; + + event ScriptResult(address indexed executor, bytes script, bytes input, bytes returnData); + + function getExecutor(bytes _script) public view returns (IEVMScriptExecutor) { + return IEVMScriptExecutor(getExecutorRegistry().getScriptExecutor(_script)); + } + + function runScript(bytes _script, bytes _input, address[] _blacklist) + internal + isInitialized + protectState + returns (bytes) + { + // TODO: Too much data flying around, maybe extracting spec id here is cheaper + IEVMScriptExecutor executor = getExecutor(_script); + /* require(address(executor) != address(0), ERROR_EXECUTOR_UNAVAILABLE); */ + + bytes4 sig = executor.execScript.selector; + bytes memory calldata = abi.encodeWithSelector(sig, _script, _input, _blacklist); + require(address(executor).delegatecall(calldata), ERROR_EXECUTION_REVERTED); + + bytes memory output = returnedDataDecoded(); + + emit ScriptResult(address(executor), _script, _input, output); + + return output; + } + + function getExecutorRegistry() internal view returns (IEVMScriptRegistry) { + address registryAddr = kernel().getApp(APP_ADDR_NAMESPACE, EVMSCRIPT_REGISTRY_APP_ID); + return IEVMScriptRegistry(registryAddr); + } + + /** + * @dev copies and returns last's call data. Needs to ABI decode first + */ + function returnedDataDecoded() internal pure returns (bytes ret) { + assembly { + let size := returndatasize + switch size + case 0 {} + default { + ret := mload(0x40) // free mem ptr get + mstore(0x40, add(ret, add(size, 0x20))) // free mem ptr set + returndatacopy(ret, 0x20, sub(size, 0x20)) // copy return data + } + } + return ret; + } + + modifier protectState { + address preKernel = address(kernel()); + bytes32 preAppId = appId(); + _; // exec + require(address(kernel()) == preKernel, ERROR_PROTECTED_STATE_MODIFIED); + require(appId() == preAppId, ERROR_PROTECTED_STATE_MODIFIED); + } +} diff --git a/contracts/mutants/EVMScriptRunner/1/ETR/EVMScriptRunner.sol b/contracts/mutants/EVMScriptRunner/1/ETR/EVMScriptRunner.sol new file mode 100644 index 00000000000..f795587af1a --- /dev/null +++ b/contracts/mutants/EVMScriptRunner/1/ETR/EVMScriptRunner.sol @@ -0,0 +1,76 @@ +/* + * SPDX-License-Identitifer: MIT + */ + +pragma solidity ^0.4.24; + +import "./IEVMScriptExecutor.sol"; +import "./IEVMScriptRegistry.sol"; + +import "../apps/AppStorage.sol"; +import "../kernel/KernelConstants.sol"; +import "../common/Initializable.sol"; + + +contract EVMScriptRunner is AppStorage, Initializable, EVMScriptRegistryConstants, KernelConstants { + string private constant ERROR_EXECUTOR_UNAVAILABLE = "EVMRUN_EXECUTOR_UNAVAILABLE"; + string private constant ERROR_EXECUTION_REVERTED = "EVMRUN_EXECUTION_REVERTED"; + string private constant ERROR_PROTECTED_STATE_MODIFIED = "EVMRUN_PROTECTED_STATE_MODIFIED"; + + event ScriptResult(address indexed executor, bytes script, bytes input, bytes returnData); + + function getExecutor(bytes _script) public view returns (IEVMScriptExecutor) { + return IEVMScriptExecutor(getExecutorRegistry().getScriptExecutor(_script)); + } + + function runScript(bytes _script, bytes _input, address[] _blacklist) + internal + isInitialized + protectState + returns (bytes) + { + // TODO: Too much data flying around, maybe extracting spec id here is cheaper + IEVMScriptExecutor executor = getExecutor(_script); + require(address(executor) != address(0), ERROR_EXECUTOR_UNAVAILABLE); + + bytes4 sig = executor.execScript.selector; + bytes memory calldata = abi.encodeWithSelector(sig, _script, _input, _blacklist); + require(address(executor).call(calldata), ERROR_EXECUTION_REVERTED); + + bytes memory output = returnedDataDecoded(); + + emit ScriptResult(address(executor), _script, _input, output); + + return output; + } + + function getExecutorRegistry() internal view returns (IEVMScriptRegistry) { + address registryAddr = kernel().getApp(APP_ADDR_NAMESPACE, EVMSCRIPT_REGISTRY_APP_ID); + return IEVMScriptRegistry(registryAddr); + } + + /** + * @dev copies and returns last's call data. Needs to ABI decode first + */ + function returnedDataDecoded() internal pure returns (bytes ret) { + assembly { + let size := returndatasize + switch size + case 0 {} + default { + ret := mload(0x40) // free mem ptr get + mstore(0x40, add(ret, add(size, 0x20))) // free mem ptr set + returndatacopy(ret, 0x20, sub(size, 0x20)) // copy return data + } + } + return ret; + } + + modifier protectState { + address preKernel = address(kernel()); + bytes32 preAppId = appId(); + _; // exec + require(address(kernel()) == preKernel, ERROR_PROTECTED_STATE_MODIFIED); + require(appId() == preAppId, ERROR_PROTECTED_STATE_MODIFIED); + } +} diff --git a/contracts/mutants/EVMScriptRunner/1/FVR/EVMScriptRunner.sol b/contracts/mutants/EVMScriptRunner/1/FVR/EVMScriptRunner.sol new file mode 100644 index 00000000000..d274747165a --- /dev/null +++ b/contracts/mutants/EVMScriptRunner/1/FVR/EVMScriptRunner.sol @@ -0,0 +1,76 @@ +/* + * SPDX-License-Identitifer: MIT + */ + +pragma solidity ^0.4.24; + +import "./IEVMScriptExecutor.sol"; +import "./IEVMScriptRegistry.sol"; + +import "../apps/AppStorage.sol"; +import "../kernel/KernelConstants.sol"; +import "../common/Initializable.sol"; + + +contract EVMScriptRunner is AppStorage, Initializable, EVMScriptRegistryConstants, KernelConstants { + string private constant ERROR_EXECUTOR_UNAVAILABLE = "EVMRUN_EXECUTOR_UNAVAILABLE"; + string private constant ERROR_EXECUTION_REVERTED = "EVMRUN_EXECUTION_REVERTED"; + string private constant ERROR_PROTECTED_STATE_MODIFIED = "EVMRUN_PROTECTED_STATE_MODIFIED"; + + event ScriptResult(address indexed executor, bytes script, bytes input, bytes returnData); + + function getExecutor(bytes _script) external view returns (IEVMScriptExecutor) { + return IEVMScriptExecutor(getExecutorRegistry().getScriptExecutor(_script)); + } + + function runScript(bytes _script, bytes _input, address[] _blacklist) + internal + isInitialized + protectState + returns (bytes) + { + // TODO: Too much data flying around, maybe extracting spec id here is cheaper + IEVMScriptExecutor executor = getExecutor(_script); + require(address(executor) != address(0), ERROR_EXECUTOR_UNAVAILABLE); + + bytes4 sig = executor.execScript.selector; + bytes memory calldata = abi.encodeWithSelector(sig, _script, _input, _blacklist); + require(address(executor).delegatecall(calldata), ERROR_EXECUTION_REVERTED); + + bytes memory output = returnedDataDecoded(); + + emit ScriptResult(address(executor), _script, _input, output); + + return output; + } + + function getExecutorRegistry() internal view returns (IEVMScriptRegistry) { + address registryAddr = kernel().getApp(APP_ADDR_NAMESPACE, EVMSCRIPT_REGISTRY_APP_ID); + return IEVMScriptRegistry(registryAddr); + } + + /** + * @dev copies and returns last's call data. Needs to ABI decode first + */ + function returnedDataDecoded() internal pure returns (bytes ret) { + assembly { + let size := returndatasize + switch size + case 0 {} + default { + ret := mload(0x40) // free mem ptr get + mstore(0x40, add(ret, add(size, 0x20))) // free mem ptr set + returndatacopy(ret, 0x20, sub(size, 0x20)) // copy return data + } + } + return ret; + } + + modifier protectState { + address preKernel = address(kernel()); + bytes32 preAppId = appId(); + _; // exec + require(address(kernel()) == preKernel, ERROR_PROTECTED_STATE_MODIFIED); + require(appId() == preAppId, ERROR_PROTECTED_STATE_MODIFIED); + } +} diff --git a/contracts/mutants/EVMScriptRunner/1/ILR/EVMScriptRunner.sol b/contracts/mutants/EVMScriptRunner/1/ILR/EVMScriptRunner.sol new file mode 100644 index 00000000000..6f93393774f --- /dev/null +++ b/contracts/mutants/EVMScriptRunner/1/ILR/EVMScriptRunner.sol @@ -0,0 +1,76 @@ +/* + * SPDX-License-Identitifer: MIT + */ + +pragma solidity ^0.4.24; + +import "./IEVMScriptExecutor.sol"; +import "./IEVMScriptRegistry.sol"; + +import "../apps/AppStorage.sol"; +import "../kernel/KernelConstants.sol"; +import "../common/Initializable.sol"; + + +contract EVMScriptRunner is AppStorage, Initializable, EVMScriptRegistryConstants, KernelConstants { + string private constant ERROR_EXECUTOR_UNAVAILABLE = "EVMRUN_EXECUTOR_UNAVAILABLE"; + string private constant ERROR_EXECUTION_REVERTED = "EVMRUN_EXECUTION_REVERTED"; + string private constant ERROR_PROTECTED_STATE_MODIFIED = "EVMRUN_PROTECTED_STATE_MODIFIED"; + + event ScriptResult(address indexed executor, bytes script, bytes input, bytes returnData); + + function getExecutor(bytes _script) public view returns (IEVMScriptExecutor) { + return IEVMScriptExecutor(getExecutorRegistry().getScriptExecutor(_script)); + } + + function runScript(bytes _script, bytes _input, address[] _blacklist) + internal + isInitialized + protectState + returns (bytes) + { + // TODO: Too much data flying around, maybe extracting spec id here is cheaper + IEVMScriptExecutor executor = getExecutor(_script); + require(address(executor) != address(1), ERROR_EXECUTOR_UNAVAILABLE); + + bytes4 sig = executor.execScript.selector; + bytes memory calldata = abi.encodeWithSelector(sig, _script, _input, _blacklist); + require(address(executor).delegatecall(calldata), ERROR_EXECUTION_REVERTED); + + bytes memory output = returnedDataDecoded(); + + emit ScriptResult(address(executor), _script, _input, output); + + return output; + } + + function getExecutorRegistry() internal view returns (IEVMScriptRegistry) { + address registryAddr = kernel().getApp(APP_ADDR_NAMESPACE, EVMSCRIPT_REGISTRY_APP_ID); + return IEVMScriptRegistry(registryAddr); + } + + /** + * @dev copies and returns last's call data. Needs to ABI decode first + */ + function returnedDataDecoded() internal pure returns (bytes ret) { + assembly { + let size := returndatasize + switch size + case 0 {} + default { + ret := mload(0x40) // free mem ptr get + mstore(0x40, add(ret, add(size, 0x20))) // free mem ptr set + returndatacopy(ret, 0x20, sub(size, 0x20)) // copy return data + } + } + return ret; + } + + modifier protectState { + address preKernel = address(kernel()); + bytes32 preAppId = appId(); + _; // exec + require(address(kernel()) == preKernel, ERROR_PROTECTED_STATE_MODIFIED); + require(appId() == preAppId, ERROR_PROTECTED_STATE_MODIFIED); + } +} diff --git a/contracts/mutants/EVMScriptRunner/1/MOC/EVMScriptRunner.sol b/contracts/mutants/EVMScriptRunner/1/MOC/EVMScriptRunner.sol new file mode 100644 index 00000000000..6a01a45be39 --- /dev/null +++ b/contracts/mutants/EVMScriptRunner/1/MOC/EVMScriptRunner.sol @@ -0,0 +1,76 @@ +/* + * SPDX-License-Identitifer: MIT + */ + +pragma solidity ^0.4.24; + +import "./IEVMScriptExecutor.sol"; +import "./IEVMScriptRegistry.sol"; + +import "../apps/AppStorage.sol"; +import "../kernel/KernelConstants.sol"; +import "../common/Initializable.sol"; + + +contract EVMScriptRunner is AppStorage, Initializable, EVMScriptRegistryConstants, KernelConstants { + string private constant ERROR_EXECUTOR_UNAVAILABLE = "EVMRUN_EXECUTOR_UNAVAILABLE"; + string private constant ERROR_EXECUTION_REVERTED = "EVMRUN_EXECUTION_REVERTED"; + string private constant ERROR_PROTECTED_STATE_MODIFIED = "EVMRUN_PROTECTED_STATE_MODIFIED"; + + event ScriptResult(address indexed executor, bytes script, bytes input, bytes returnData); + + function getExecutor(bytes _script) public view returns (IEVMScriptExecutor) { + return IEVMScriptExecutor(getExecutorRegistry().getScriptExecutor(_script)); + } + + function runScript(bytes _script, bytes _input, address[] _blacklist) + internal + protectState + isInitialized + returns (bytes) + { + // TODO: Too much data flying around, maybe extracting spec id here is cheaper + IEVMScriptExecutor executor = getExecutor(_script); + require(address(executor) != address(0), ERROR_EXECUTOR_UNAVAILABLE); + + bytes4 sig = executor.execScript.selector; + bytes memory calldata = abi.encodeWithSelector(sig, _script, _input, _blacklist); + require(address(executor).delegatecall(calldata), ERROR_EXECUTION_REVERTED); + + bytes memory output = returnedDataDecoded(); + + emit ScriptResult(address(executor), _script, _input, output); + + return output; + } + + function getExecutorRegistry() internal view returns (IEVMScriptRegistry) { + address registryAddr = kernel().getApp(APP_ADDR_NAMESPACE, EVMSCRIPT_REGISTRY_APP_ID); + return IEVMScriptRegistry(registryAddr); + } + + /** + * @dev copies and returns last's call data. Needs to ABI decode first + */ + function returnedDataDecoded() internal pure returns (bytes ret) { + assembly { + let size := returndatasize + switch size + case 0 {} + default { + ret := mload(0x40) // free mem ptr get + mstore(0x40, add(ret, add(size, 0x20))) // free mem ptr set + returndatacopy(ret, 0x20, sub(size, 0x20)) // copy return data + } + } + return ret; + } + + modifier protectState { + address preKernel = address(kernel()); + bytes32 preAppId = appId(); + _; // exec + require(address(kernel()) == preKernel, ERROR_PROTECTED_STATE_MODIFIED); + require(appId() == preAppId, ERROR_PROTECTED_STATE_MODIFIED); + } +} diff --git a/contracts/mutants/EVMScriptRunner/1/MOD/EVMScriptRunner.sol b/contracts/mutants/EVMScriptRunner/1/MOD/EVMScriptRunner.sol new file mode 100644 index 00000000000..6a01a45be39 --- /dev/null +++ b/contracts/mutants/EVMScriptRunner/1/MOD/EVMScriptRunner.sol @@ -0,0 +1,76 @@ +/* + * SPDX-License-Identitifer: MIT + */ + +pragma solidity ^0.4.24; + +import "./IEVMScriptExecutor.sol"; +import "./IEVMScriptRegistry.sol"; + +import "../apps/AppStorage.sol"; +import "../kernel/KernelConstants.sol"; +import "../common/Initializable.sol"; + + +contract EVMScriptRunner is AppStorage, Initializable, EVMScriptRegistryConstants, KernelConstants { + string private constant ERROR_EXECUTOR_UNAVAILABLE = "EVMRUN_EXECUTOR_UNAVAILABLE"; + string private constant ERROR_EXECUTION_REVERTED = "EVMRUN_EXECUTION_REVERTED"; + string private constant ERROR_PROTECTED_STATE_MODIFIED = "EVMRUN_PROTECTED_STATE_MODIFIED"; + + event ScriptResult(address indexed executor, bytes script, bytes input, bytes returnData); + + function getExecutor(bytes _script) public view returns (IEVMScriptExecutor) { + return IEVMScriptExecutor(getExecutorRegistry().getScriptExecutor(_script)); + } + + function runScript(bytes _script, bytes _input, address[] _blacklist) + internal + protectState + isInitialized + returns (bytes) + { + // TODO: Too much data flying around, maybe extracting spec id here is cheaper + IEVMScriptExecutor executor = getExecutor(_script); + require(address(executor) != address(0), ERROR_EXECUTOR_UNAVAILABLE); + + bytes4 sig = executor.execScript.selector; + bytes memory calldata = abi.encodeWithSelector(sig, _script, _input, _blacklist); + require(address(executor).delegatecall(calldata), ERROR_EXECUTION_REVERTED); + + bytes memory output = returnedDataDecoded(); + + emit ScriptResult(address(executor), _script, _input, output); + + return output; + } + + function getExecutorRegistry() internal view returns (IEVMScriptRegistry) { + address registryAddr = kernel().getApp(APP_ADDR_NAMESPACE, EVMSCRIPT_REGISTRY_APP_ID); + return IEVMScriptRegistry(registryAddr); + } + + /** + * @dev copies and returns last's call data. Needs to ABI decode first + */ + function returnedDataDecoded() internal pure returns (bytes ret) { + assembly { + let size := returndatasize + switch size + case 0 {} + default { + ret := mload(0x40) // free mem ptr get + mstore(0x40, add(ret, add(size, 0x20))) // free mem ptr set + returndatacopy(ret, 0x20, sub(size, 0x20)) // copy return data + } + } + return ret; + } + + modifier protectState { + address preKernel = address(kernel()); + bytes32 preAppId = appId(); + _; // exec + require(address(kernel()) == preKernel, ERROR_PROTECTED_STATE_MODIFIED); + require(appId() == preAppId, ERROR_PROTECTED_STATE_MODIFIED); + } +} diff --git a/contracts/mutants/EVMScriptRunner/1/RSD/EVMScriptRunner.sol b/contracts/mutants/EVMScriptRunner/1/RSD/EVMScriptRunner.sol new file mode 100644 index 00000000000..2e158a693d9 --- /dev/null +++ b/contracts/mutants/EVMScriptRunner/1/RSD/EVMScriptRunner.sol @@ -0,0 +1,76 @@ +/* + * SPDX-License-Identitifer: MIT + */ + +pragma solidity ^0.4.24; + +import "./IEVMScriptExecutor.sol"; +import "./IEVMScriptRegistry.sol"; + +import "../apps/AppStorage.sol"; +import "../kernel/KernelConstants.sol"; +import "../common/Initializable.sol"; + + +contract EVMScriptRunner is AppStorage, Initializable, EVMScriptRegistryConstants, KernelConstants { + string private constant ERROR_EXECUTOR_UNAVAILABLE = "EVMRUN_EXECUTOR_UNAVAILABLE"; + string private constant ERROR_EXECUTION_REVERTED = "EVMRUN_EXECUTION_REVERTED"; + string private constant ERROR_PROTECTED_STATE_MODIFIED = "EVMRUN_PROTECTED_STATE_MODIFIED"; + + event ScriptResult(address indexed executor, bytes script, bytes input, bytes returnData); + + function getExecutor(bytes _script) public view returns (IEVMScriptExecutor) { + /* return IEVMScriptExecutor(getExecutorRegistry().getScriptExecutor(_script)); */ + } + + function runScript(bytes _script, bytes _input, address[] _blacklist) + internal + isInitialized + protectState + returns (bytes) + { + // TODO: Too much data flying around, maybe extracting spec id here is cheaper + IEVMScriptExecutor executor = getExecutor(_script); + require(address(executor) != address(0), ERROR_EXECUTOR_UNAVAILABLE); + + bytes4 sig = executor.execScript.selector; + bytes memory calldata = abi.encodeWithSelector(sig, _script, _input, _blacklist); + require(address(executor).delegatecall(calldata), ERROR_EXECUTION_REVERTED); + + bytes memory output = returnedDataDecoded(); + + emit ScriptResult(address(executor), _script, _input, output); + + return output; + } + + function getExecutorRegistry() internal view returns (IEVMScriptRegistry) { + address registryAddr = kernel().getApp(APP_ADDR_NAMESPACE, EVMSCRIPT_REGISTRY_APP_ID); + return IEVMScriptRegistry(registryAddr); + } + + /** + * @dev copies and returns last's call data. Needs to ABI decode first + */ + function returnedDataDecoded() internal pure returns (bytes ret) { + assembly { + let size := returndatasize + switch size + case 0 {} + default { + ret := mload(0x40) // free mem ptr get + mstore(0x40, add(ret, add(size, 0x20))) // free mem ptr set + returndatacopy(ret, 0x20, sub(size, 0x20)) // copy return data + } + } + return ret; + } + + modifier protectState { + address preKernel = address(kernel()); + bytes32 preAppId = appId(); + _; // exec + require(address(kernel()) == preKernel, ERROR_PROTECTED_STATE_MODIFIED); + require(appId() == preAppId, ERROR_PROTECTED_STATE_MODIFIED); + } +} diff --git a/contracts/mutants/EVMScriptRunner/1/SLR/EVMScriptRunner.sol b/contracts/mutants/EVMScriptRunner/1/SLR/EVMScriptRunner.sol new file mode 100644 index 00000000000..c9b04d0f7a7 --- /dev/null +++ b/contracts/mutants/EVMScriptRunner/1/SLR/EVMScriptRunner.sol @@ -0,0 +1,76 @@ +/* + * SPDX-License-Identitifer: MIT + */ + +pragma solidity ^0.4.24; + +import "./IEVMScriptExecutor.sol"; +import "./IEVMScriptRegistry.sol"; + +import "../apps/AppStorage.sol"; +import "../kernel/KernelConstants.sol"; +import "../common/Initializable.sol"; + + +contract EVMScriptRunner is AppStorage, Initializable, EVMScriptRegistryConstants, KernelConstants { + string private constant ERROR_EXECUTOR_UNAVAILABLE = ""; + string private constant ERROR_EXECUTION_REVERTED = "EVMRUN_EXECUTION_REVERTED"; + string private constant ERROR_PROTECTED_STATE_MODIFIED = "EVMRUN_PROTECTED_STATE_MODIFIED"; + + event ScriptResult(address indexed executor, bytes script, bytes input, bytes returnData); + + function getExecutor(bytes _script) public view returns (IEVMScriptExecutor) { + return IEVMScriptExecutor(getExecutorRegistry().getScriptExecutor(_script)); + } + + function runScript(bytes _script, bytes _input, address[] _blacklist) + internal + isInitialized + protectState + returns (bytes) + { + // TODO: Too much data flying around, maybe extracting spec id here is cheaper + IEVMScriptExecutor executor = getExecutor(_script); + require(address(executor) != address(0), ERROR_EXECUTOR_UNAVAILABLE); + + bytes4 sig = executor.execScript.selector; + bytes memory calldata = abi.encodeWithSelector(sig, _script, _input, _blacklist); + require(address(executor).delegatecall(calldata), ERROR_EXECUTION_REVERTED); + + bytes memory output = returnedDataDecoded(); + + emit ScriptResult(address(executor), _script, _input, output); + + return output; + } + + function getExecutorRegistry() internal view returns (IEVMScriptRegistry) { + address registryAddr = kernel().getApp(APP_ADDR_NAMESPACE, EVMSCRIPT_REGISTRY_APP_ID); + return IEVMScriptRegistry(registryAddr); + } + + /** + * @dev copies and returns last's call data. Needs to ABI decode first + */ + function returnedDataDecoded() internal pure returns (bytes ret) { + assembly { + let size := returndatasize + switch size + case 0 {} + default { + ret := mload(0x40) // free mem ptr get + mstore(0x40, add(ret, add(size, 0x20))) // free mem ptr set + returndatacopy(ret, 0x20, sub(size, 0x20)) // copy return data + } + } + return ret; + } + + modifier protectState { + address preKernel = address(kernel()); + bytes32 preAppId = appId(); + _; // exec + require(address(kernel()) == preKernel, ERROR_PROTECTED_STATE_MODIFIED); + require(appId() == preAppId, ERROR_PROTECTED_STATE_MODIFIED); + } +} diff --git a/contracts/mutants/EVMScriptRunner/1/VVR/EVMScriptRunner.sol b/contracts/mutants/EVMScriptRunner/1/VVR/EVMScriptRunner.sol new file mode 100644 index 00000000000..a2322b2fa47 --- /dev/null +++ b/contracts/mutants/EVMScriptRunner/1/VVR/EVMScriptRunner.sol @@ -0,0 +1,76 @@ +/* + * SPDX-License-Identitifer: MIT + */ + +pragma solidity ^0.4.24; + +import "./IEVMScriptExecutor.sol"; +import "./IEVMScriptRegistry.sol"; + +import "../apps/AppStorage.sol"; +import "../kernel/KernelConstants.sol"; +import "../common/Initializable.sol"; + + +contract EVMScriptRunner is AppStorage, Initializable, EVMScriptRegistryConstants, KernelConstants { + string public constant ERROR_EXECUTOR_UNAVAILABLE = "EVMRUN_EXECUTOR_UNAVAILABLE"; + string private constant ERROR_EXECUTION_REVERTED = "EVMRUN_EXECUTION_REVERTED"; + string private constant ERROR_PROTECTED_STATE_MODIFIED = "EVMRUN_PROTECTED_STATE_MODIFIED"; + + event ScriptResult(address indexed executor, bytes script, bytes input, bytes returnData); + + function getExecutor(bytes _script) public view returns (IEVMScriptExecutor) { + return IEVMScriptExecutor(getExecutorRegistry().getScriptExecutor(_script)); + } + + function runScript(bytes _script, bytes _input, address[] _blacklist) + internal + isInitialized + protectState + returns (bytes) + { + // TODO: Too much data flying around, maybe extracting spec id here is cheaper + IEVMScriptExecutor executor = getExecutor(_script); + require(address(executor) != address(0), ERROR_EXECUTOR_UNAVAILABLE); + + bytes4 sig = executor.execScript.selector; + bytes memory calldata = abi.encodeWithSelector(sig, _script, _input, _blacklist); + require(address(executor).delegatecall(calldata), ERROR_EXECUTION_REVERTED); + + bytes memory output = returnedDataDecoded(); + + emit ScriptResult(address(executor), _script, _input, output); + + return output; + } + + function getExecutorRegistry() internal view returns (IEVMScriptRegistry) { + address registryAddr = kernel().getApp(APP_ADDR_NAMESPACE, EVMSCRIPT_REGISTRY_APP_ID); + return IEVMScriptRegistry(registryAddr); + } + + /** + * @dev copies and returns last's call data. Needs to ABI decode first + */ + function returnedDataDecoded() internal pure returns (bytes ret) { + assembly { + let size := returndatasize + switch size + case 0 {} + default { + ret := mload(0x40) // free mem ptr get + mstore(0x40, add(ret, add(size, 0x20))) // free mem ptr set + returndatacopy(ret, 0x20, sub(size, 0x20)) // copy return data + } + } + return ret; + } + + modifier protectState { + address preKernel = address(kernel()); + bytes32 preAppId = appId(); + _; // exec + require(address(kernel()) == preKernel, ERROR_PROTECTED_STATE_MODIFIED); + require(appId() == preAppId, ERROR_PROTECTED_STATE_MODIFIED); + } +} diff --git a/contracts/mutants/EVMScriptRunner/2/BOR/EVMScriptRunner.sol b/contracts/mutants/EVMScriptRunner/2/BOR/EVMScriptRunner.sol new file mode 100644 index 00000000000..564dc63644a --- /dev/null +++ b/contracts/mutants/EVMScriptRunner/2/BOR/EVMScriptRunner.sol @@ -0,0 +1,76 @@ +/* + * SPDX-License-Identitifer: MIT + */ + +pragma solidity ^0.4.24; + +import "./IEVMScriptExecutor.sol"; +import "./IEVMScriptRegistry.sol"; + +import "../apps/AppStorage.sol"; +import "../kernel/KernelConstants.sol"; +import "../common/Initializable.sol"; + + +contract EVMScriptRunner is AppStorage, Initializable, EVMScriptRegistryConstants, KernelConstants { + string private constant ERROR_EXECUTOR_UNAVAILABLE = "EVMRUN_EXECUTOR_UNAVAILABLE"; + string private constant ERROR_EXECUTION_REVERTED = "EVMRUN_EXECUTION_REVERTED"; + string private constant ERROR_PROTECTED_STATE_MODIFIED = "EVMRUN_PROTECTED_STATE_MODIFIED"; + + event ScriptResult(address indexed executor, bytes script, bytes input, bytes returnData); + + function getExecutor(bytes _script) public view returns (IEVMScriptExecutor) { + return IEVMScriptExecutor(getExecutorRegistry().getScriptExecutor(_script)); + } + + function runScript(bytes _script, bytes _input, address[] _blacklist) + internal + isInitialized + protectState + returns (bytes) + { + // TODO: Too much data flying around, maybe extracting spec id here is cheaper + IEVMScriptExecutor executor = getExecutor(_script); + require(address(executor) > address(0), ERROR_EXECUTOR_UNAVAILABLE); + + bytes4 sig = executor.execScript.selector; + bytes memory calldata = abi.encodeWithSelector(sig, _script, _input, _blacklist); + require(address(executor).delegatecall(calldata), ERROR_EXECUTION_REVERTED); + + bytes memory output = returnedDataDecoded(); + + emit ScriptResult(address(executor), _script, _input, output); + + return output; + } + + function getExecutorRegistry() internal view returns (IEVMScriptRegistry) { + address registryAddr = kernel().getApp(APP_ADDR_NAMESPACE, EVMSCRIPT_REGISTRY_APP_ID); + return IEVMScriptRegistry(registryAddr); + } + + /** + * @dev copies and returns last's call data. Needs to ABI decode first + */ + function returnedDataDecoded() internal pure returns (bytes ret) { + assembly { + let size := returndatasize + switch size + case 0 {} + default { + ret := mload(0x40) // free mem ptr get + mstore(0x40, add(ret, add(size, 0x20))) // free mem ptr set + returndatacopy(ret, 0x20, sub(size, 0x20)) // copy return data + } + } + return ret; + } + + modifier protectState { + address preKernel = address(kernel()); + bytes32 preAppId = appId(); + _; // exec + require(address(kernel()) <= preKernel, ERROR_PROTECTED_STATE_MODIFIED); + require(appId() == preAppId, ERROR_PROTECTED_STATE_MODIFIED); + } +} diff --git a/contracts/mutants/EVMScriptRunner/2/DLR/EVMScriptRunner.sol b/contracts/mutants/EVMScriptRunner/2/DLR/EVMScriptRunner.sol new file mode 100644 index 00000000000..7127dfe7377 --- /dev/null +++ b/contracts/mutants/EVMScriptRunner/2/DLR/EVMScriptRunner.sol @@ -0,0 +1,76 @@ +/* + * SPDX-License-Identitifer: MIT + */ + +pragma solidity ^0.4.24; + +import "./IEVMScriptExecutor.sol"; +import "./IEVMScriptRegistry.sol"; + +import "../apps/AppStorage.sol"; +import "../kernel/KernelConstants.sol"; +import "../common/Initializable.sol"; + + +contract EVMScriptRunner is AppStorage, Initializable, EVMScriptRegistryConstants, KernelConstants { + string private constant ERROR_EXECUTOR_UNAVAILABLE = "EVMRUN_EXECUTOR_UNAVAILABLE"; + string private constant ERROR_EXECUTION_REVERTED = "EVMRUN_EXECUTION_REVERTED"; + string private constant ERROR_PROTECTED_STATE_MODIFIED = "EVMRUN_PROTECTED_STATE_MODIFIED"; + + event ScriptResult(address indexed executor, bytes script, bytes input, bytes returnData); + + function getExecutor(bytes _script) public view returns (IEVMScriptExecutor) { + return IEVMScriptExecutor(getExecutorRegistry().getScriptExecutor(_script)); + } + + function runScript(bytes _script, bytes _input, address[] _blacklist) + internal + isInitialized + protectState + returns (bytes) + { + // TODO: Too much data flying around, maybe extracting spec id here is cheaper + IEVMScriptExecutor executor = getExecutor(_script); + require(address(executor) != address(0), ERROR_EXECUTOR_UNAVAILABLE); + + bytes4 sig = executor.execScript.selector; + bytes storage calldata = abi.encodeWithSelector(sig, _script, _input, _blacklist); + require(address(executor).delegatecall(calldata), ERROR_EXECUTION_REVERTED); + + bytes storage output = returnedDataDecoded(); + + emit ScriptResult(address(executor), _script, _input, output); + + return output; + } + + function getExecutorRegistry() internal view returns (IEVMScriptRegistry) { + address registryAddr = kernel().getApp(APP_ADDR_NAMESPACE, EVMSCRIPT_REGISTRY_APP_ID); + return IEVMScriptRegistry(registryAddr); + } + + /** + * @dev copies and returns last's call data. Needs to ABI decode first + */ + function returnedDataDecoded() internal pure returns (bytes ret) { + assembly { + let size := returndatasize + switch size + case 0 {} + default { + ret := mload(0x40) // free mem ptr get + mstore(0x40, add(ret, add(size, 0x20))) // free mem ptr set + returndatacopy(ret, 0x20, sub(size, 0x20)) // copy return data + } + } + return ret; + } + + modifier protectState { + address preKernel = address(kernel()); + bytes32 preAppId = appId(); + _; // exec + require(address(kernel()) == preKernel, ERROR_PROTECTED_STATE_MODIFIED); + require(appId() == preAppId, ERROR_PROTECTED_STATE_MODIFIED); + } +} diff --git a/contracts/mutants/EVMScriptRunner/2/EHC/EVMScriptRunner.sol b/contracts/mutants/EVMScriptRunner/2/EHC/EVMScriptRunner.sol new file mode 100644 index 00000000000..2290556156f --- /dev/null +++ b/contracts/mutants/EVMScriptRunner/2/EHC/EVMScriptRunner.sol @@ -0,0 +1,76 @@ +/* + * SPDX-License-Identitifer: MIT + */ + +pragma solidity ^0.4.24; + +import "./IEVMScriptExecutor.sol"; +import "./IEVMScriptRegistry.sol"; + +import "../apps/AppStorage.sol"; +import "../kernel/KernelConstants.sol"; +import "../common/Initializable.sol"; + + +contract EVMScriptRunner is AppStorage, Initializable, EVMScriptRegistryConstants, KernelConstants { + string private constant ERROR_EXECUTOR_UNAVAILABLE = "EVMRUN_EXECUTOR_UNAVAILABLE"; + string private constant ERROR_EXECUTION_REVERTED = "EVMRUN_EXECUTION_REVERTED"; + string private constant ERROR_PROTECTED_STATE_MODIFIED = "EVMRUN_PROTECTED_STATE_MODIFIED"; + + event ScriptResult(address indexed executor, bytes script, bytes input, bytes returnData); + + function getExecutor(bytes _script) public view returns (IEVMScriptExecutor) { + return IEVMScriptExecutor(getExecutorRegistry().getScriptExecutor(_script)); + } + + function runScript(bytes _script, bytes _input, address[] _blacklist) + internal + isInitialized + protectState + returns (bytes) + { + // TODO: Too much data flying around, maybe extracting spec id here is cheaper + IEVMScriptExecutor executor = getExecutor(_script); + /* require(address(executor) != address(0), ERROR_EXECUTOR_UNAVAILABLE); */ + + bytes4 sig = executor.execScript.selector; + bytes memory calldata = abi.encodeWithSelector(sig, _script, _input, _blacklist); + /* require(address(executor).delegatecall(calldata), ERROR_EXECUTION_REVERTED); */ + + bytes memory output = returnedDataDecoded(); + + emit ScriptResult(address(executor), _script, _input, output); + + return output; + } + + function getExecutorRegistry() internal view returns (IEVMScriptRegistry) { + address registryAddr = kernel().getApp(APP_ADDR_NAMESPACE, EVMSCRIPT_REGISTRY_APP_ID); + return IEVMScriptRegistry(registryAddr); + } + + /** + * @dev copies and returns last's call data. Needs to ABI decode first + */ + function returnedDataDecoded() internal pure returns (bytes ret) { + assembly { + let size := returndatasize + switch size + case 0 {} + default { + ret := mload(0x40) // free mem ptr get + mstore(0x40, add(ret, add(size, 0x20))) // free mem ptr set + returndatacopy(ret, 0x20, sub(size, 0x20)) // copy return data + } + } + return ret; + } + + modifier protectState { + address preKernel = address(kernel()); + bytes32 preAppId = appId(); + _; // exec + require(address(kernel()) == preKernel, ERROR_PROTECTED_STATE_MODIFIED); + require(appId() == preAppId, ERROR_PROTECTED_STATE_MODIFIED); + } +} diff --git a/contracts/mutants/EVMScriptRunner/2/FVR/EVMScriptRunner.sol b/contracts/mutants/EVMScriptRunner/2/FVR/EVMScriptRunner.sol new file mode 100644 index 00000000000..a13bc8ea65c --- /dev/null +++ b/contracts/mutants/EVMScriptRunner/2/FVR/EVMScriptRunner.sol @@ -0,0 +1,76 @@ +/* + * SPDX-License-Identitifer: MIT + */ + +pragma solidity ^0.4.24; + +import "./IEVMScriptExecutor.sol"; +import "./IEVMScriptRegistry.sol"; + +import "../apps/AppStorage.sol"; +import "../kernel/KernelConstants.sol"; +import "../common/Initializable.sol"; + + +contract EVMScriptRunner is AppStorage, Initializable, EVMScriptRegistryConstants, KernelConstants { + string private constant ERROR_EXECUTOR_UNAVAILABLE = "EVMRUN_EXECUTOR_UNAVAILABLE"; + string private constant ERROR_EXECUTION_REVERTED = "EVMRUN_EXECUTION_REVERTED"; + string private constant ERROR_PROTECTED_STATE_MODIFIED = "EVMRUN_PROTECTED_STATE_MODIFIED"; + + event ScriptResult(address indexed executor, bytes script, bytes input, bytes returnData); + + function getExecutor(bytes _script) external view returns (IEVMScriptExecutor) { + return IEVMScriptExecutor(getExecutorRegistry().getScriptExecutor(_script)); + } + + function runScript(bytes _script, bytes _input, address[] _blacklist) + public + isInitialized + protectState + returns (bytes) + { + // TODO: Too much data flying around, maybe extracting spec id here is cheaper + IEVMScriptExecutor executor = getExecutor(_script); + require(address(executor) != address(0), ERROR_EXECUTOR_UNAVAILABLE); + + bytes4 sig = executor.execScript.selector; + bytes memory calldata = abi.encodeWithSelector(sig, _script, _input, _blacklist); + require(address(executor).delegatecall(calldata), ERROR_EXECUTION_REVERTED); + + bytes memory output = returnedDataDecoded(); + + emit ScriptResult(address(executor), _script, _input, output); + + return output; + } + + function getExecutorRegistry() internal view returns (IEVMScriptRegistry) { + address registryAddr = kernel().getApp(APP_ADDR_NAMESPACE, EVMSCRIPT_REGISTRY_APP_ID); + return IEVMScriptRegistry(registryAddr); + } + + /** + * @dev copies and returns last's call data. Needs to ABI decode first + */ + function returnedDataDecoded() internal pure returns (bytes ret) { + assembly { + let size := returndatasize + switch size + case 0 {} + default { + ret := mload(0x40) // free mem ptr get + mstore(0x40, add(ret, add(size, 0x20))) // free mem ptr set + returndatacopy(ret, 0x20, sub(size, 0x20)) // copy return data + } + } + return ret; + } + + modifier protectState { + address preKernel = address(kernel()); + bytes32 preAppId = appId(); + _; // exec + require(address(kernel()) == preKernel, ERROR_PROTECTED_STATE_MODIFIED); + require(appId() == preAppId, ERROR_PROTECTED_STATE_MODIFIED); + } +} diff --git a/contracts/mutants/EVMScriptRunner/2/RSD/EVMScriptRunner.sol b/contracts/mutants/EVMScriptRunner/2/RSD/EVMScriptRunner.sol new file mode 100644 index 00000000000..45d18c63e45 --- /dev/null +++ b/contracts/mutants/EVMScriptRunner/2/RSD/EVMScriptRunner.sol @@ -0,0 +1,76 @@ +/* + * SPDX-License-Identitifer: MIT + */ + +pragma solidity ^0.4.24; + +import "./IEVMScriptExecutor.sol"; +import "./IEVMScriptRegistry.sol"; + +import "../apps/AppStorage.sol"; +import "../kernel/KernelConstants.sol"; +import "../common/Initializable.sol"; + + +contract EVMScriptRunner is AppStorage, Initializable, EVMScriptRegistryConstants, KernelConstants { + string private constant ERROR_EXECUTOR_UNAVAILABLE = "EVMRUN_EXECUTOR_UNAVAILABLE"; + string private constant ERROR_EXECUTION_REVERTED = "EVMRUN_EXECUTION_REVERTED"; + string private constant ERROR_PROTECTED_STATE_MODIFIED = "EVMRUN_PROTECTED_STATE_MODIFIED"; + + event ScriptResult(address indexed executor, bytes script, bytes input, bytes returnData); + + function getExecutor(bytes _script) public view returns (IEVMScriptExecutor) { + /* return IEVMScriptExecutor(getExecutorRegistry().getScriptExecutor(_script)); */ + } + + function runScript(bytes _script, bytes _input, address[] _blacklist) + internal + isInitialized + protectState + returns (bytes) + { + // TODO: Too much data flying around, maybe extracting spec id here is cheaper + IEVMScriptExecutor executor = getExecutor(_script); + require(address(executor) != address(0), ERROR_EXECUTOR_UNAVAILABLE); + + bytes4 sig = executor.execScript.selector; + bytes memory calldata = abi.encodeWithSelector(sig, _script, _input, _blacklist); + require(address(executor).delegatecall(calldata), ERROR_EXECUTION_REVERTED); + + bytes memory output = returnedDataDecoded(); + + emit ScriptResult(address(executor), _script, _input, output); + + /* return output; */ + } + + function getExecutorRegistry() internal view returns (IEVMScriptRegistry) { + address registryAddr = kernel().getApp(APP_ADDR_NAMESPACE, EVMSCRIPT_REGISTRY_APP_ID); + return IEVMScriptRegistry(registryAddr); + } + + /** + * @dev copies and returns last's call data. Needs to ABI decode first + */ + function returnedDataDecoded() internal pure returns (bytes ret) { + assembly { + let size := returndatasize + switch size + case 0 {} + default { + ret := mload(0x40) // free mem ptr get + mstore(0x40, add(ret, add(size, 0x20))) // free mem ptr set + returndatacopy(ret, 0x20, sub(size, 0x20)) // copy return data + } + } + return ret; + } + + modifier protectState { + address preKernel = address(kernel()); + bytes32 preAppId = appId(); + _; // exec + require(address(kernel()) == preKernel, ERROR_PROTECTED_STATE_MODIFIED); + require(appId() == preAppId, ERROR_PROTECTED_STATE_MODIFIED); + } +} diff --git a/contracts/mutants/EVMScriptRunner/2/SLR/EVMScriptRunner.sol b/contracts/mutants/EVMScriptRunner/2/SLR/EVMScriptRunner.sol new file mode 100644 index 00000000000..371a7e449f6 --- /dev/null +++ b/contracts/mutants/EVMScriptRunner/2/SLR/EVMScriptRunner.sol @@ -0,0 +1,76 @@ +/* + * SPDX-License-Identitifer: MIT + */ + +pragma solidity ^0.4.24; + +import "./IEVMScriptExecutor.sol"; +import "./IEVMScriptRegistry.sol"; + +import "../apps/AppStorage.sol"; +import "../kernel/KernelConstants.sol"; +import "../common/Initializable.sol"; + + +contract EVMScriptRunner is AppStorage, Initializable, EVMScriptRegistryConstants, KernelConstants { + string private constant ERROR_EXECUTOR_UNAVAILABLE = ""; + string private constant ERROR_EXECUTION_REVERTED = ""; + string private constant ERROR_PROTECTED_STATE_MODIFIED = "EVMRUN_PROTECTED_STATE_MODIFIED"; + + event ScriptResult(address indexed executor, bytes script, bytes input, bytes returnData); + + function getExecutor(bytes _script) public view returns (IEVMScriptExecutor) { + return IEVMScriptExecutor(getExecutorRegistry().getScriptExecutor(_script)); + } + + function runScript(bytes _script, bytes _input, address[] _blacklist) + internal + isInitialized + protectState + returns (bytes) + { + // TODO: Too much data flying around, maybe extracting spec id here is cheaper + IEVMScriptExecutor executor = getExecutor(_script); + require(address(executor) != address(0), ERROR_EXECUTOR_UNAVAILABLE); + + bytes4 sig = executor.execScript.selector; + bytes memory calldata = abi.encodeWithSelector(sig, _script, _input, _blacklist); + require(address(executor).delegatecall(calldata), ERROR_EXECUTION_REVERTED); + + bytes memory output = returnedDataDecoded(); + + emit ScriptResult(address(executor), _script, _input, output); + + return output; + } + + function getExecutorRegistry() internal view returns (IEVMScriptRegistry) { + address registryAddr = kernel().getApp(APP_ADDR_NAMESPACE, EVMSCRIPT_REGISTRY_APP_ID); + return IEVMScriptRegistry(registryAddr); + } + + /** + * @dev copies and returns last's call data. Needs to ABI decode first + */ + function returnedDataDecoded() internal pure returns (bytes ret) { + assembly { + let size := returndatasize + switch size + case 0 {} + default { + ret := mload(0x40) // free mem ptr get + mstore(0x40, add(ret, add(size, 0x20))) // free mem ptr set + returndatacopy(ret, 0x20, sub(size, 0x20)) // copy return data + } + } + return ret; + } + + modifier protectState { + address preKernel = address(kernel()); + bytes32 preAppId = appId(); + _; // exec + require(address(kernel()) == preKernel, ERROR_PROTECTED_STATE_MODIFIED); + require(appId() == preAppId, ERROR_PROTECTED_STATE_MODIFIED); + } +} diff --git a/contracts/mutants/EVMScriptRunner/2/VVR/EVMScriptRunner.sol b/contracts/mutants/EVMScriptRunner/2/VVR/EVMScriptRunner.sol new file mode 100644 index 00000000000..5f9f6557045 --- /dev/null +++ b/contracts/mutants/EVMScriptRunner/2/VVR/EVMScriptRunner.sol @@ -0,0 +1,76 @@ +/* + * SPDX-License-Identitifer: MIT + */ + +pragma solidity ^0.4.24; + +import "./IEVMScriptExecutor.sol"; +import "./IEVMScriptRegistry.sol"; + +import "../apps/AppStorage.sol"; +import "../kernel/KernelConstants.sol"; +import "../common/Initializable.sol"; + + +contract EVMScriptRunner is AppStorage, Initializable, EVMScriptRegistryConstants, KernelConstants { + string public constant ERROR_EXECUTOR_UNAVAILABLE = "EVMRUN_EXECUTOR_UNAVAILABLE"; + string public constant ERROR_EXECUTION_REVERTED = "EVMRUN_EXECUTION_REVERTED"; + string private constant ERROR_PROTECTED_STATE_MODIFIED = "EVMRUN_PROTECTED_STATE_MODIFIED"; + + event ScriptResult(address indexed executor, bytes script, bytes input, bytes returnData); + + function getExecutor(bytes _script) public view returns (IEVMScriptExecutor) { + return IEVMScriptExecutor(getExecutorRegistry().getScriptExecutor(_script)); + } + + function runScript(bytes _script, bytes _input, address[] _blacklist) + internal + isInitialized + protectState + returns (bytes) + { + // TODO: Too much data flying around, maybe extracting spec id here is cheaper + IEVMScriptExecutor executor = getExecutor(_script); + require(address(executor) != address(0), ERROR_EXECUTOR_UNAVAILABLE); + + bytes4 sig = executor.execScript.selector; + bytes memory calldata = abi.encodeWithSelector(sig, _script, _input, _blacklist); + require(address(executor).delegatecall(calldata), ERROR_EXECUTION_REVERTED); + + bytes memory output = returnedDataDecoded(); + + emit ScriptResult(address(executor), _script, _input, output); + + return output; + } + + function getExecutorRegistry() internal view returns (IEVMScriptRegistry) { + address registryAddr = kernel().getApp(APP_ADDR_NAMESPACE, EVMSCRIPT_REGISTRY_APP_ID); + return IEVMScriptRegistry(registryAddr); + } + + /** + * @dev copies and returns last's call data. Needs to ABI decode first + */ + function returnedDataDecoded() internal pure returns (bytes ret) { + assembly { + let size := returndatasize + switch size + case 0 {} + default { + ret := mload(0x40) // free mem ptr get + mstore(0x40, add(ret, add(size, 0x20))) // free mem ptr set + returndatacopy(ret, 0x20, sub(size, 0x20)) // copy return data + } + } + return ret; + } + + modifier protectState { + address preKernel = address(kernel()); + bytes32 preAppId = appId(); + _; // exec + require(address(kernel()) == preKernel, ERROR_PROTECTED_STATE_MODIFIED); + require(appId() == preAppId, ERROR_PROTECTED_STATE_MODIFIED); + } +} diff --git a/contracts/mutants/EVMScriptRunner/3/BOR/EVMScriptRunner.sol b/contracts/mutants/EVMScriptRunner/3/BOR/EVMScriptRunner.sol new file mode 100644 index 00000000000..e852f4e953b --- /dev/null +++ b/contracts/mutants/EVMScriptRunner/3/BOR/EVMScriptRunner.sol @@ -0,0 +1,76 @@ +/* + * SPDX-License-Identitifer: MIT + */ + +pragma solidity ^0.4.24; + +import "./IEVMScriptExecutor.sol"; +import "./IEVMScriptRegistry.sol"; + +import "../apps/AppStorage.sol"; +import "../kernel/KernelConstants.sol"; +import "../common/Initializable.sol"; + + +contract EVMScriptRunner is AppStorage, Initializable, EVMScriptRegistryConstants, KernelConstants { + string private constant ERROR_EXECUTOR_UNAVAILABLE = "EVMRUN_EXECUTOR_UNAVAILABLE"; + string private constant ERROR_EXECUTION_REVERTED = "EVMRUN_EXECUTION_REVERTED"; + string private constant ERROR_PROTECTED_STATE_MODIFIED = "EVMRUN_PROTECTED_STATE_MODIFIED"; + + event ScriptResult(address indexed executor, bytes script, bytes input, bytes returnData); + + function getExecutor(bytes _script) public view returns (IEVMScriptExecutor) { + return IEVMScriptExecutor(getExecutorRegistry().getScriptExecutor(_script)); + } + + function runScript(bytes _script, bytes _input, address[] _blacklist) + internal + isInitialized + protectState + returns (bytes) + { + // TODO: Too much data flying around, maybe extracting spec id here is cheaper + IEVMScriptExecutor executor = getExecutor(_script); + require(address(executor) > address(0), ERROR_EXECUTOR_UNAVAILABLE); + + bytes4 sig = executor.execScript.selector; + bytes memory calldata = abi.encodeWithSelector(sig, _script, _input, _blacklist); + require(address(executor).delegatecall(calldata), ERROR_EXECUTION_REVERTED); + + bytes memory output = returnedDataDecoded(); + + emit ScriptResult(address(executor), _script, _input, output); + + return output; + } + + function getExecutorRegistry() internal view returns (IEVMScriptRegistry) { + address registryAddr = kernel().getApp(APP_ADDR_NAMESPACE, EVMSCRIPT_REGISTRY_APP_ID); + return IEVMScriptRegistry(registryAddr); + } + + /** + * @dev copies and returns last's call data. Needs to ABI decode first + */ + function returnedDataDecoded() internal pure returns (bytes ret) { + assembly { + let size := returndatasize + switch size + case 0 {} + default { + ret := mload(0x40) // free mem ptr get + mstore(0x40, add(ret, add(size, 0x20))) // free mem ptr set + returndatacopy(ret, 0x20, sub(size, 0x20)) // copy return data + } + } + return ret; + } + + modifier protectState { + address preKernel = address(kernel()); + bytes32 preAppId = appId(); + _; // exec + require(address(kernel()) <= preKernel, ERROR_PROTECTED_STATE_MODIFIED); + require(appId() <= preAppId, ERROR_PROTECTED_STATE_MODIFIED); + } +} diff --git a/contracts/mutants/EVMScriptRunner/3/EHC/EVMScriptRunner.sol b/contracts/mutants/EVMScriptRunner/3/EHC/EVMScriptRunner.sol new file mode 100644 index 00000000000..e8f4fb6d915 --- /dev/null +++ b/contracts/mutants/EVMScriptRunner/3/EHC/EVMScriptRunner.sol @@ -0,0 +1,76 @@ +/* + * SPDX-License-Identitifer: MIT + */ + +pragma solidity ^0.4.24; + +import "./IEVMScriptExecutor.sol"; +import "./IEVMScriptRegistry.sol"; + +import "../apps/AppStorage.sol"; +import "../kernel/KernelConstants.sol"; +import "../common/Initializable.sol"; + + +contract EVMScriptRunner is AppStorage, Initializable, EVMScriptRegistryConstants, KernelConstants { + string private constant ERROR_EXECUTOR_UNAVAILABLE = "EVMRUN_EXECUTOR_UNAVAILABLE"; + string private constant ERROR_EXECUTION_REVERTED = "EVMRUN_EXECUTION_REVERTED"; + string private constant ERROR_PROTECTED_STATE_MODIFIED = "EVMRUN_PROTECTED_STATE_MODIFIED"; + + event ScriptResult(address indexed executor, bytes script, bytes input, bytes returnData); + + function getExecutor(bytes _script) public view returns (IEVMScriptExecutor) { + return IEVMScriptExecutor(getExecutorRegistry().getScriptExecutor(_script)); + } + + function runScript(bytes _script, bytes _input, address[] _blacklist) + internal + isInitialized + protectState + returns (bytes) + { + // TODO: Too much data flying around, maybe extracting spec id here is cheaper + IEVMScriptExecutor executor = getExecutor(_script); + /* require(address(executor) != address(0), ERROR_EXECUTOR_UNAVAILABLE); */ + + bytes4 sig = executor.execScript.selector; + bytes memory calldata = abi.encodeWithSelector(sig, _script, _input, _blacklist); + /* require(address(executor).delegatecall(calldata), ERROR_EXECUTION_REVERTED); */ + + bytes memory output = returnedDataDecoded(); + + emit ScriptResult(address(executor), _script, _input, output); + + return output; + } + + function getExecutorRegistry() internal view returns (IEVMScriptRegistry) { + address registryAddr = kernel().getApp(APP_ADDR_NAMESPACE, EVMSCRIPT_REGISTRY_APP_ID); + return IEVMScriptRegistry(registryAddr); + } + + /** + * @dev copies and returns last's call data. Needs to ABI decode first + */ + function returnedDataDecoded() internal pure returns (bytes ret) { + assembly { + let size := returndatasize + switch size + case 0 {} + default { + ret := mload(0x40) // free mem ptr get + mstore(0x40, add(ret, add(size, 0x20))) // free mem ptr set + returndatacopy(ret, 0x20, sub(size, 0x20)) // copy return data + } + } + return ret; + } + + modifier protectState { + address preKernel = address(kernel()); + bytes32 preAppId = appId(); + _; // exec + /* require(address(kernel()) == preKernel, ERROR_PROTECTED_STATE_MODIFIED); */ + require(appId() == preAppId, ERROR_PROTECTED_STATE_MODIFIED); + } +} diff --git a/contracts/mutants/EVMScriptRunner/3/FVR/EVMScriptRunner.sol b/contracts/mutants/EVMScriptRunner/3/FVR/EVMScriptRunner.sol new file mode 100644 index 00000000000..08f1939fc2c --- /dev/null +++ b/contracts/mutants/EVMScriptRunner/3/FVR/EVMScriptRunner.sol @@ -0,0 +1,76 @@ +/* + * SPDX-License-Identitifer: MIT + */ + +pragma solidity ^0.4.24; + +import "./IEVMScriptExecutor.sol"; +import "./IEVMScriptRegistry.sol"; + +import "../apps/AppStorage.sol"; +import "../kernel/KernelConstants.sol"; +import "../common/Initializable.sol"; + + +contract EVMScriptRunner is AppStorage, Initializable, EVMScriptRegistryConstants, KernelConstants { + string private constant ERROR_EXECUTOR_UNAVAILABLE = "EVMRUN_EXECUTOR_UNAVAILABLE"; + string private constant ERROR_EXECUTION_REVERTED = "EVMRUN_EXECUTION_REVERTED"; + string private constant ERROR_PROTECTED_STATE_MODIFIED = "EVMRUN_PROTECTED_STATE_MODIFIED"; + + event ScriptResult(address indexed executor, bytes script, bytes input, bytes returnData); + + function getExecutor(bytes _script) external view returns (IEVMScriptExecutor) { + return IEVMScriptExecutor(getExecutorRegistry().getScriptExecutor(_script)); + } + + function runScript(bytes _script, bytes _input, address[] _blacklist) + public + isInitialized + protectState + returns (bytes) + { + // TODO: Too much data flying around, maybe extracting spec id here is cheaper + IEVMScriptExecutor executor = getExecutor(_script); + require(address(executor) != address(0), ERROR_EXECUTOR_UNAVAILABLE); + + bytes4 sig = executor.execScript.selector; + bytes memory calldata = abi.encodeWithSelector(sig, _script, _input, _blacklist); + require(address(executor).delegatecall(calldata), ERROR_EXECUTION_REVERTED); + + bytes memory output = returnedDataDecoded(); + + emit ScriptResult(address(executor), _script, _input, output); + + return output; + } + + function getExecutorRegistry() public view returns (IEVMScriptRegistry) { + address registryAddr = kernel().getApp(APP_ADDR_NAMESPACE, EVMSCRIPT_REGISTRY_APP_ID); + return IEVMScriptRegistry(registryAddr); + } + + /** + * @dev copies and returns last's call data. Needs to ABI decode first + */ + function returnedDataDecoded() internal pure returns (bytes ret) { + assembly { + let size := returndatasize + switch size + case 0 {} + default { + ret := mload(0x40) // free mem ptr get + mstore(0x40, add(ret, add(size, 0x20))) // free mem ptr set + returndatacopy(ret, 0x20, sub(size, 0x20)) // copy return data + } + } + return ret; + } + + modifier protectState { + address preKernel = address(kernel()); + bytes32 preAppId = appId(); + _; // exec + require(address(kernel()) == preKernel, ERROR_PROTECTED_STATE_MODIFIED); + require(appId() == preAppId, ERROR_PROTECTED_STATE_MODIFIED); + } +} diff --git a/contracts/mutants/EVMScriptRunner/3/RSD/EVMScriptRunner.sol b/contracts/mutants/EVMScriptRunner/3/RSD/EVMScriptRunner.sol new file mode 100644 index 00000000000..0ba63db5507 --- /dev/null +++ b/contracts/mutants/EVMScriptRunner/3/RSD/EVMScriptRunner.sol @@ -0,0 +1,76 @@ +/* + * SPDX-License-Identitifer: MIT + */ + +pragma solidity ^0.4.24; + +import "./IEVMScriptExecutor.sol"; +import "./IEVMScriptRegistry.sol"; + +import "../apps/AppStorage.sol"; +import "../kernel/KernelConstants.sol"; +import "../common/Initializable.sol"; + + +contract EVMScriptRunner is AppStorage, Initializable, EVMScriptRegistryConstants, KernelConstants { + string private constant ERROR_EXECUTOR_UNAVAILABLE = "EVMRUN_EXECUTOR_UNAVAILABLE"; + string private constant ERROR_EXECUTION_REVERTED = "EVMRUN_EXECUTION_REVERTED"; + string private constant ERROR_PROTECTED_STATE_MODIFIED = "EVMRUN_PROTECTED_STATE_MODIFIED"; + + event ScriptResult(address indexed executor, bytes script, bytes input, bytes returnData); + + function getExecutor(bytes _script) public view returns (IEVMScriptExecutor) { + /* return IEVMScriptExecutor(getExecutorRegistry().getScriptExecutor(_script)); */ + } + + function runScript(bytes _script, bytes _input, address[] _blacklist) + internal + isInitialized + protectState + returns (bytes) + { + // TODO: Too much data flying around, maybe extracting spec id here is cheaper + IEVMScriptExecutor executor = getExecutor(_script); + require(address(executor) != address(0), ERROR_EXECUTOR_UNAVAILABLE); + + bytes4 sig = executor.execScript.selector; + bytes memory calldata = abi.encodeWithSelector(sig, _script, _input, _blacklist); + require(address(executor).delegatecall(calldata), ERROR_EXECUTION_REVERTED); + + bytes memory output = returnedDataDecoded(); + + emit ScriptResult(address(executor), _script, _input, output); + + /* return output; */ + } + + function getExecutorRegistry() internal view returns (IEVMScriptRegistry) { + address registryAddr = kernel().getApp(APP_ADDR_NAMESPACE, EVMSCRIPT_REGISTRY_APP_ID); + /* return IEVMScriptRegistry(registryAddr); */ + } + + /** + * @dev copies and returns last's call data. Needs to ABI decode first + */ + function returnedDataDecoded() internal pure returns (bytes ret) { + assembly { + let size := returndatasize + switch size + case 0 {} + default { + ret := mload(0x40) // free mem ptr get + mstore(0x40, add(ret, add(size, 0x20))) // free mem ptr set + returndatacopy(ret, 0x20, sub(size, 0x20)) // copy return data + } + } + return ret; + } + + modifier protectState { + address preKernel = address(kernel()); + bytes32 preAppId = appId(); + _; // exec + require(address(kernel()) == preKernel, ERROR_PROTECTED_STATE_MODIFIED); + require(appId() == preAppId, ERROR_PROTECTED_STATE_MODIFIED); + } +} diff --git a/contracts/mutants/EVMScriptRunner/3/SLR/EVMScriptRunner.sol b/contracts/mutants/EVMScriptRunner/3/SLR/EVMScriptRunner.sol new file mode 100644 index 00000000000..e4da3c6cbdc --- /dev/null +++ b/contracts/mutants/EVMScriptRunner/3/SLR/EVMScriptRunner.sol @@ -0,0 +1,76 @@ +/* + * SPDX-License-Identitifer: MIT + */ + +pragma solidity ^0.4.24; + +import "./IEVMScriptExecutor.sol"; +import "./IEVMScriptRegistry.sol"; + +import "../apps/AppStorage.sol"; +import "../kernel/KernelConstants.sol"; +import "../common/Initializable.sol"; + + +contract EVMScriptRunner is AppStorage, Initializable, EVMScriptRegistryConstants, KernelConstants { + string private constant ERROR_EXECUTOR_UNAVAILABLE = ""; + string private constant ERROR_EXECUTION_REVERTED = ""; + string private constant ERROR_PROTECTED_STATE_MODIFIED = ""; + + event ScriptResult(address indexed executor, bytes script, bytes input, bytes returnData); + + function getExecutor(bytes _script) public view returns (IEVMScriptExecutor) { + return IEVMScriptExecutor(getExecutorRegistry().getScriptExecutor(_script)); + } + + function runScript(bytes _script, bytes _input, address[] _blacklist) + internal + isInitialized + protectState + returns (bytes) + { + // TODO: Too much data flying around, maybe extracting spec id here is cheaper + IEVMScriptExecutor executor = getExecutor(_script); + require(address(executor) != address(0), ERROR_EXECUTOR_UNAVAILABLE); + + bytes4 sig = executor.execScript.selector; + bytes memory calldata = abi.encodeWithSelector(sig, _script, _input, _blacklist); + require(address(executor).delegatecall(calldata), ERROR_EXECUTION_REVERTED); + + bytes memory output = returnedDataDecoded(); + + emit ScriptResult(address(executor), _script, _input, output); + + return output; + } + + function getExecutorRegistry() internal view returns (IEVMScriptRegistry) { + address registryAddr = kernel().getApp(APP_ADDR_NAMESPACE, EVMSCRIPT_REGISTRY_APP_ID); + return IEVMScriptRegistry(registryAddr); + } + + /** + * @dev copies and returns last's call data. Needs to ABI decode first + */ + function returnedDataDecoded() internal pure returns (bytes ret) { + assembly { + let size := returndatasize + switch size + case 0 {} + default { + ret := mload(0x40) // free mem ptr get + mstore(0x40, add(ret, add(size, 0x20))) // free mem ptr set + returndatacopy(ret, 0x20, sub(size, 0x20)) // copy return data + } + } + return ret; + } + + modifier protectState { + address preKernel = address(kernel()); + bytes32 preAppId = appId(); + _; // exec + require(address(kernel()) == preKernel, ERROR_PROTECTED_STATE_MODIFIED); + require(appId() == preAppId, ERROR_PROTECTED_STATE_MODIFIED); + } +} diff --git a/contracts/mutants/EVMScriptRunner/3/VVR/EVMScriptRunner.sol b/contracts/mutants/EVMScriptRunner/3/VVR/EVMScriptRunner.sol new file mode 100644 index 00000000000..32c9f76a8e6 --- /dev/null +++ b/contracts/mutants/EVMScriptRunner/3/VVR/EVMScriptRunner.sol @@ -0,0 +1,76 @@ +/* + * SPDX-License-Identitifer: MIT + */ + +pragma solidity ^0.4.24; + +import "./IEVMScriptExecutor.sol"; +import "./IEVMScriptRegistry.sol"; + +import "../apps/AppStorage.sol"; +import "../kernel/KernelConstants.sol"; +import "../common/Initializable.sol"; + + +contract EVMScriptRunner is AppStorage, Initializable, EVMScriptRegistryConstants, KernelConstants { + string public constant ERROR_EXECUTOR_UNAVAILABLE = "EVMRUN_EXECUTOR_UNAVAILABLE"; + string public constant ERROR_EXECUTION_REVERTED = "EVMRUN_EXECUTION_REVERTED"; + string public constant ERROR_PROTECTED_STATE_MODIFIED = "EVMRUN_PROTECTED_STATE_MODIFIED"; + + event ScriptResult(address indexed executor, bytes script, bytes input, bytes returnData); + + function getExecutor(bytes _script) public view returns (IEVMScriptExecutor) { + return IEVMScriptExecutor(getExecutorRegistry().getScriptExecutor(_script)); + } + + function runScript(bytes _script, bytes _input, address[] _blacklist) + internal + isInitialized + protectState + returns (bytes) + { + // TODO: Too much data flying around, maybe extracting spec id here is cheaper + IEVMScriptExecutor executor = getExecutor(_script); + require(address(executor) != address(0), ERROR_EXECUTOR_UNAVAILABLE); + + bytes4 sig = executor.execScript.selector; + bytes memory calldata = abi.encodeWithSelector(sig, _script, _input, _blacklist); + require(address(executor).delegatecall(calldata), ERROR_EXECUTION_REVERTED); + + bytes memory output = returnedDataDecoded(); + + emit ScriptResult(address(executor), _script, _input, output); + + return output; + } + + function getExecutorRegistry() internal view returns (IEVMScriptRegistry) { + address registryAddr = kernel().getApp(APP_ADDR_NAMESPACE, EVMSCRIPT_REGISTRY_APP_ID); + return IEVMScriptRegistry(registryAddr); + } + + /** + * @dev copies and returns last's call data. Needs to ABI decode first + */ + function returnedDataDecoded() internal pure returns (bytes ret) { + assembly { + let size := returndatasize + switch size + case 0 {} + default { + ret := mload(0x40) // free mem ptr get + mstore(0x40, add(ret, add(size, 0x20))) // free mem ptr set + returndatacopy(ret, 0x20, sub(size, 0x20)) // copy return data + } + } + return ret; + } + + modifier protectState { + address preKernel = address(kernel()); + bytes32 preAppId = appId(); + _; // exec + require(address(kernel()) == preKernel, ERROR_PROTECTED_STATE_MODIFIED); + require(appId() == preAppId, ERROR_PROTECTED_STATE_MODIFIED); + } +} diff --git a/contracts/mutants/EVMScriptRunner/4/EHC/EVMScriptRunner.sol b/contracts/mutants/EVMScriptRunner/4/EHC/EVMScriptRunner.sol new file mode 100644 index 00000000000..815dee60410 --- /dev/null +++ b/contracts/mutants/EVMScriptRunner/4/EHC/EVMScriptRunner.sol @@ -0,0 +1,76 @@ +/* + * SPDX-License-Identitifer: MIT + */ + +pragma solidity ^0.4.24; + +import "./IEVMScriptExecutor.sol"; +import "./IEVMScriptRegistry.sol"; + +import "../apps/AppStorage.sol"; +import "../kernel/KernelConstants.sol"; +import "../common/Initializable.sol"; + + +contract EVMScriptRunner is AppStorage, Initializable, EVMScriptRegistryConstants, KernelConstants { + string private constant ERROR_EXECUTOR_UNAVAILABLE = "EVMRUN_EXECUTOR_UNAVAILABLE"; + string private constant ERROR_EXECUTION_REVERTED = "EVMRUN_EXECUTION_REVERTED"; + string private constant ERROR_PROTECTED_STATE_MODIFIED = "EVMRUN_PROTECTED_STATE_MODIFIED"; + + event ScriptResult(address indexed executor, bytes script, bytes input, bytes returnData); + + function getExecutor(bytes _script) public view returns (IEVMScriptExecutor) { + return IEVMScriptExecutor(getExecutorRegistry().getScriptExecutor(_script)); + } + + function runScript(bytes _script, bytes _input, address[] _blacklist) + internal + isInitialized + protectState + returns (bytes) + { + // TODO: Too much data flying around, maybe extracting spec id here is cheaper + IEVMScriptExecutor executor = getExecutor(_script); + /* require(address(executor) != address(0), ERROR_EXECUTOR_UNAVAILABLE); */ + + bytes4 sig = executor.execScript.selector; + bytes memory calldata = abi.encodeWithSelector(sig, _script, _input, _blacklist); + /* require(address(executor).delegatecall(calldata), ERROR_EXECUTION_REVERTED); */ + + bytes memory output = returnedDataDecoded(); + + emit ScriptResult(address(executor), _script, _input, output); + + return output; + } + + function getExecutorRegistry() internal view returns (IEVMScriptRegistry) { + address registryAddr = kernel().getApp(APP_ADDR_NAMESPACE, EVMSCRIPT_REGISTRY_APP_ID); + return IEVMScriptRegistry(registryAddr); + } + + /** + * @dev copies and returns last's call data. Needs to ABI decode first + */ + function returnedDataDecoded() internal pure returns (bytes ret) { + assembly { + let size := returndatasize + switch size + case 0 {} + default { + ret := mload(0x40) // free mem ptr get + mstore(0x40, add(ret, add(size, 0x20))) // free mem ptr set + returndatacopy(ret, 0x20, sub(size, 0x20)) // copy return data + } + } + return ret; + } + + modifier protectState { + address preKernel = address(kernel()); + bytes32 preAppId = appId(); + _; // exec + /* require(address(kernel()) == preKernel, ERROR_PROTECTED_STATE_MODIFIED); */ + /* require(appId() == preAppId, ERROR_PROTECTED_STATE_MODIFIED); */ + } +} diff --git a/contracts/mutants/EVMScriptRunner/4/FVR/EVMScriptRunner.sol b/contracts/mutants/EVMScriptRunner/4/FVR/EVMScriptRunner.sol new file mode 100644 index 00000000000..275d1223278 --- /dev/null +++ b/contracts/mutants/EVMScriptRunner/4/FVR/EVMScriptRunner.sol @@ -0,0 +1,76 @@ +/* + * SPDX-License-Identitifer: MIT + */ + +pragma solidity ^0.4.24; + +import "./IEVMScriptExecutor.sol"; +import "./IEVMScriptRegistry.sol"; + +import "../apps/AppStorage.sol"; +import "../kernel/KernelConstants.sol"; +import "../common/Initializable.sol"; + + +contract EVMScriptRunner is AppStorage, Initializable, EVMScriptRegistryConstants, KernelConstants { + string private constant ERROR_EXECUTOR_UNAVAILABLE = "EVMRUN_EXECUTOR_UNAVAILABLE"; + string private constant ERROR_EXECUTION_REVERTED = "EVMRUN_EXECUTION_REVERTED"; + string private constant ERROR_PROTECTED_STATE_MODIFIED = "EVMRUN_PROTECTED_STATE_MODIFIED"; + + event ScriptResult(address indexed executor, bytes script, bytes input, bytes returnData); + + function getExecutor(bytes _script) external view returns (IEVMScriptExecutor) { + return IEVMScriptExecutor(getExecutorRegistry().getScriptExecutor(_script)); + } + + function runScript(bytes _script, bytes _input, address[] _blacklist) + public + isInitialized + protectState + returns (bytes) + { + // TODO: Too much data flying around, maybe extracting spec id here is cheaper + IEVMScriptExecutor executor = getExecutor(_script); + require(address(executor) != address(0), ERROR_EXECUTOR_UNAVAILABLE); + + bytes4 sig = executor.execScript.selector; + bytes memory calldata = abi.encodeWithSelector(sig, _script, _input, _blacklist); + require(address(executor).delegatecall(calldata), ERROR_EXECUTION_REVERTED); + + bytes memory output = returnedDataDecoded(); + + emit ScriptResult(address(executor), _script, _input, output); + + return output; + } + + function getExecutorRegistry() public view returns (IEVMScriptRegistry) { + address registryAddr = kernel().getApp(APP_ADDR_NAMESPACE, EVMSCRIPT_REGISTRY_APP_ID); + return IEVMScriptRegistry(registryAddr); + } + + /** + * @dev copies and returns last's call data. Needs to ABI decode first + */ + function returnedDataDecoded() public pure returns (bytes ret) { + assembly { + let size := returndatasize + switch size + case 0 {} + default { + ret := mload(0x40) // free mem ptr get + mstore(0x40, add(ret, add(size, 0x20))) // free mem ptr set + returndatacopy(ret, 0x20, sub(size, 0x20)) // copy return data + } + } + return ret; + } + + modifier protectState { + address preKernel = address(kernel()); + bytes32 preAppId = appId(); + _; // exec + require(address(kernel()) == preKernel, ERROR_PROTECTED_STATE_MODIFIED); + require(appId() == preAppId, ERROR_PROTECTED_STATE_MODIFIED); + } +} diff --git a/contracts/mutants/EVMScriptRunner/4/RSD/EVMScriptRunner.sol b/contracts/mutants/EVMScriptRunner/4/RSD/EVMScriptRunner.sol new file mode 100644 index 00000000000..df71c3da0ee --- /dev/null +++ b/contracts/mutants/EVMScriptRunner/4/RSD/EVMScriptRunner.sol @@ -0,0 +1,76 @@ +/* + * SPDX-License-Identitifer: MIT + */ + +pragma solidity ^0.4.24; + +import "./IEVMScriptExecutor.sol"; +import "./IEVMScriptRegistry.sol"; + +import "../apps/AppStorage.sol"; +import "../kernel/KernelConstants.sol"; +import "../common/Initializable.sol"; + + +contract EVMScriptRunner is AppStorage, Initializable, EVMScriptRegistryConstants, KernelConstants { + string private constant ERROR_EXECUTOR_UNAVAILABLE = "EVMRUN_EXECUTOR_UNAVAILABLE"; + string private constant ERROR_EXECUTION_REVERTED = "EVMRUN_EXECUTION_REVERTED"; + string private constant ERROR_PROTECTED_STATE_MODIFIED = "EVMRUN_PROTECTED_STATE_MODIFIED"; + + event ScriptResult(address indexed executor, bytes script, bytes input, bytes returnData); + + function getExecutor(bytes _script) public view returns (IEVMScriptExecutor) { + /* return IEVMScriptExecutor(getExecutorRegistry().getScriptExecutor(_script)); */ + } + + function runScript(bytes _script, bytes _input, address[] _blacklist) + internal + isInitialized + protectState + returns (bytes) + { + // TODO: Too much data flying around, maybe extracting spec id here is cheaper + IEVMScriptExecutor executor = getExecutor(_script); + require(address(executor) != address(0), ERROR_EXECUTOR_UNAVAILABLE); + + bytes4 sig = executor.execScript.selector; + bytes memory calldata = abi.encodeWithSelector(sig, _script, _input, _blacklist); + require(address(executor).delegatecall(calldata), ERROR_EXECUTION_REVERTED); + + bytes memory output = returnedDataDecoded(); + + emit ScriptResult(address(executor), _script, _input, output); + + /* return output; */ + } + + function getExecutorRegistry() internal view returns (IEVMScriptRegistry) { + address registryAddr = kernel().getApp(APP_ADDR_NAMESPACE, EVMSCRIPT_REGISTRY_APP_ID); + /* return IEVMScriptRegistry(registryAddr); */ + } + + /** + * @dev copies and returns last's call data. Needs to ABI decode first + */ + function returnedDataDecoded() internal pure returns (bytes ret) { + assembly { + let size := returndatasize + switch size + case 0 {} + default { + ret := mload(0x40) // free mem ptr get + mstore(0x40, add(ret, add(size, 0x20))) // free mem ptr set + returndatacopy(ret, 0x20, sub(size, 0x20)) // copy return data + } + } + /* return ret; */ + } + + modifier protectState { + address preKernel = address(kernel()); + bytes32 preAppId = appId(); + _; // exec + require(address(kernel()) == preKernel, ERROR_PROTECTED_STATE_MODIFIED); + require(appId() == preAppId, ERROR_PROTECTED_STATE_MODIFIED); + } +} diff --git a/contracts/mutants/EVMScriptRunner/original/EVMScriptRunner.sol b/contracts/mutants/EVMScriptRunner/original/EVMScriptRunner.sol new file mode 100644 index 00000000000..2ce4a358d31 --- /dev/null +++ b/contracts/mutants/EVMScriptRunner/original/EVMScriptRunner.sol @@ -0,0 +1,76 @@ +/* + * SPDX-License-Identitifer: MIT + */ + +pragma solidity ^0.4.24; + +import "./IEVMScriptExecutor.sol"; +import "./IEVMScriptRegistry.sol"; + +import "../apps/AppStorage.sol"; +import "../kernel/KernelConstants.sol"; +import "../common/Initializable.sol"; + + +contract EVMScriptRunner is AppStorage, Initializable, EVMScriptRegistryConstants, KernelConstants { + string private constant ERROR_EXECUTOR_UNAVAILABLE = "EVMRUN_EXECUTOR_UNAVAILABLE"; + string private constant ERROR_EXECUTION_REVERTED = "EVMRUN_EXECUTION_REVERTED"; + string private constant ERROR_PROTECTED_STATE_MODIFIED = "EVMRUN_PROTECTED_STATE_MODIFIED"; + + event ScriptResult(address indexed executor, bytes script, bytes input, bytes returnData); + + function getExecutor(bytes _script) public view returns (IEVMScriptExecutor) { + return IEVMScriptExecutor(getExecutorRegistry().getScriptExecutor(_script)); + } + + function runScript(bytes _script, bytes _input, address[] _blacklist) + internal + isInitialized + protectState + returns (bytes) + { + // TODO: Too much data flying around, maybe extracting spec id here is cheaper + IEVMScriptExecutor executor = getExecutor(_script); + require(address(executor) != address(0), ERROR_EXECUTOR_UNAVAILABLE); + + bytes4 sig = executor.execScript.selector; + bytes memory calldata = abi.encodeWithSelector(sig, _script, _input, _blacklist); + require(address(executor).delegatecall(calldata), ERROR_EXECUTION_REVERTED); + + bytes memory output = returnedDataDecoded(); + + emit ScriptResult(address(executor), _script, _input, output); + + return output; + } + + function getExecutorRegistry() internal view returns (IEVMScriptRegistry) { + address registryAddr = kernel().getApp(APP_ADDR_NAMESPACE, EVMSCRIPT_REGISTRY_APP_ID); + return IEVMScriptRegistry(registryAddr); + } + + /** + * @dev copies and returns last's call data. Needs to ABI decode first + */ + function returnedDataDecoded() internal pure returns (bytes ret) { + assembly { + let size := returndatasize + switch size + case 0 {} + default { + ret := mload(0x40) // free mem ptr get + mstore(0x40, add(ret, add(size, 0x20))) // free mem ptr set + returndatacopy(ret, 0x20, sub(size, 0x20)) // copy return data + } + } + return ret; + } + + modifier protectState { + address preKernel = address(kernel()); + bytes32 preAppId = appId(); + _; // exec + require(address(kernel()) == preKernel, ERROR_PROTECTED_STATE_MODIFIED); + require(appId() == preAppId, ERROR_PROTECTED_STATE_MODIFIED); + } +}