Commit c464ba77 authored by smartcontracts's avatar smartcontracts Committed by Adrian Sutton

Revert "fix: have MIPS revert on add/sub overflow/underflow (#230)" (#279)

This reverts commit 864e59a821e87f9dd00ae97f85add93fa3857597.
parent 1fd43eac
......@@ -240,29 +240,11 @@ func ExecuteMipsInstruction(insn, opcode, fun, rs, rt, mem uint32) uint32 {
return rs
// The rest includes transformed R-type arith imm instructions
case 0x20: // add
intRs := int32(rs)
intRt := int32(rt)
intRes := intRs + intRt
if intRs > 0 && intRt > 0 && intRes <= 0 {
panic("MIPS: add overflow")
}
if intRs < 0 && intRt < 0 && intRes >= 0 {
panic("MIPS: add underflow")
}
return uint32(intRes)
return rs + rt
case 0x21: // addu
return rs + rt
case 0x22: // sub
intRs := int32(rs)
intRt := int32(rt)
intRes := intRs - intRt
if intRs > 0 && intRt < 0 && intRes < 0 {
panic("MIPS: sub overflow")
}
if intRs < 0 && intRt > 0 && intRes > 0 {
panic("MIPS: sub underflow")
}
return uint32(intRes)
return rs - rt
case 0x23: // subu
return rs - rt
case 0x24: // and
......
.section .test, "x"
.balign 4
.set noreorder
.global test
.ent test
test:
lui $s0, 0xbfff # Load the base address 0xbffffff0
ori $s0, 0xfff0
ori $s1, $0, 1 # Prepare the 'done' status
#### Test code start ####
lui $t0, 0x7fff # A = 0x7fffffff (maximum positive 32-bit integer)
ori $t0, 0xffff
ori $t1, $0, 1 # B = 0x1
add $t2, $t0, $t1 # C = A + B (this should trigger an overflow)
# Unreachable ....
#### Test code end ####
sw $v0, 8($s0) # Set the test result
sw $s1, 4($s0) # Set 'done'
$done:
jr $ra
nop
.end test
.section .test, "x"
.balign 4
.set noreorder
.global test
.ent test
test:
lui $s0, 0xbfff # Load the base address 0xbffffff0
ori $s0, 0xfff0
ori $s1, $0, 1 # Prepare the 'done' status
#### Test code start ####
lui $t0, 0x8000 # A = 0x80000000 (minimum negative 32-bit integer)
ori $t0, 0x0000
lui $t1, 0x8000 # B = 0x80000000 (minimum negative 32-bit integer)
ori $t1, 0x0000
add $t2, $t0, $t1 # C = A + B (this should trigger an underflow)
# Unreachable ....
#### Test code end ####
sw $v0, 8($s0) # Set the test result
sw $s1, 4($s0) # Set 'done'
$done:
jr $ra
nop
.end test
.section .test, "x"
.balign 4
.set noreorder
.global test
.ent test
test:
lui $s0, 0xbfff # Load the base address 0xbffffff0
ori $s0, 0xfff0
ori $s1, $0, 1 # Prepare the 'done' status
#### Test code start ####
lui $t0, 0x7fff # A = 0x7fffffff (maximum positive 32-bit integer)
ori $t0, 0xffff
addi $t1, $t0, 1 # B = A + 1 (this should trigger an overflow)
# Unreachable...
#### Test code end ####
sw $v0, 8($s0) # Set the test result
sw $s1, 4($s0) # Set 'done'
$done:
jr $ra
nop
.end test
.section .test, "x"
.balign 4
.set noreorder
.global test
.ent test
test:
lui $s0, 0xbfff # Load the base address 0xbffffff0
ori $s0, 0xfff0
ori $s1, $0, 1 # Prepare the 'done' status
#### Test code start ####
lui $t0, 0x8000 # A = 0x80000000 (minimum negative 32-bit integer)
ori $t0, 0x0000
addi $t1, $t0, -1 # B = A - 1 (this should trigger an underflow)
# Unreachable...
#### Test code end ####
sw $v0, 8($s0) # Set the test result
sw $s1, 4($s0) # Set 'done'
$done:
jr $ra
nop
.end test
.section .test, "x"
.balign 4
.set noreorder
.global test
.ent test
test:
lui $s0, 0xbfff # Load the base address 0xbffffff0
ori $s0, 0xfff0
ori $s1, $0, 1 # Prepare the 'done' status
#### Test code start ####
lui $t0, 0xffff # A = 0xffffffff (maximum unsigned 32-bit integer)
ori $t0, 0xffff
ori $t1, $0, 1 # B = 1
addu $t2, $t0, $t1 # C = A + B (simulate overflow)
sltu $v0, $t2, $t0 # D = 1 if overflow (C < A)
#### Test code end ####
sw $v0, 8($s0) # Set the test result
sw $s1, 4($s0) # Set 'done'
$done:
jr $ra
nop
.end test
.section .test, "x"
.balign 4
.set noreorder
.global test
.ent test
test:
lui $s0, 0xbfff # Load the base address 0xbffffff0
ori $s0, 0xfff0
ori $s1, $0, 1 # Prepare the 'done' status
#### Test code start ####
lui $t0, 0x7fff # A = 0x7fffffff (maximum positive 32-bit integer)
ori $t0, 0xffff
lui $t1, 0xffff # B = 0xffffffff (-1)
ori $t1, 0xffff
sub $t2, $t0, $t1 # C = A - B = 0x7fffffff - (-1) = 0x80000000 (overflow)
# Unreachable...
#### Test code end ####
sw $v0, 8($s0) # Set the test result
sw $s1, 4($s0) # Set 'done'
$done:
jr $ra
nop
.end test
.section .test, "x"
.balign 4
.set noreorder
.global test
.ent test
test:
lui $s0, 0xbfff # Load the base address 0xbffffff0
ori $s0, 0xfff0
ori $s1, $0, 1 # Prepare the 'done' status
#### Test code start ####
lui $t0, 0x8000 # A = 0x80000000 (minimum negative 32-bit integer)
ori $t0, 0x0000
ori $t1, $0, 1 # B = 1
sub $t2, $t0, $t1 # C = A - B = 0x80000000 - 1 (underflow)
# Unreachable...
#### Test code end ####
sw $v0, 8($s0) # Set the test result
sw $s1, 4($s0) # Set 'done'
$done:
jr $ra
nop
.end test
.section .test, "x"
.balign 4
.set noreorder
.global test
.ent test
test:
lui $s0, 0xbfff # Load the base address 0xbffffff0
ori $s0, 0xfff0
ori $s1, $0, 1 # Prepare the 'done' status
#### Test code start ####
ori $t0, $0, 1 # A = 1
ori $t1, $0, 2 # B = 2
subu $t2, $t0, $t1 # C = A - B = 0xFFFFFFFF
sltu $v0, $t0, $t1 # D = 1 if underflow occurred (A < B)
#### Test code end ####
sw $v0, 8($s0) # Set the test result
sw $s1, 4($s0) # Set 'done'
$done:
jr $ra
nop
.end test
......@@ -140,11 +140,11 @@
"sourceCodeHash": "0x3ff4a3f21202478935412d47fd5ef7f94a170402ddc50e5c062013ce5544c83f"
},
"src/cannon/MIPS.sol": {
"initCodeHash": "0xc783f01a426b889cd80d242cf01901fc34c595e59e74d50e3a0a8cb1fa226b3f",
"initCodeHash": "0x328f14e6c171957a5225378f0b49e3dd5e92c6ddc815552216ce066415bf972a",
"sourceCodeHash": "0xfa6e6eacba6be2c9489f828f8a50dda40565eef5c73a2cf8e274e1fd4410d38a"
},
"src/cannon/MIPS2.sol": {
"initCodeHash": "0xeac747751362183e6e0e4caa34f07284823449867897a39bd036db5ea189e2c7",
"initCodeHash": "0x69bfafb485944e36f95a1123e0da5c7da09cde23a216d0402d3219d2a8df410d",
"sourceCodeHash": "0x115bd6a4c4d77ed210dfd468675b409fdae9f79b932063c138f0765ba9063462"
},
"src/cannon/PreimageOracle.sol": {
......
This source diff could not be displayed because it is too large. You can view the blob instead.
......@@ -364,12 +364,7 @@ library MIPSInstructions {
// The rest includes transformed R-type arith imm instructions
// add
else if (_fun == 0x20) {
int32 rs = int32(_rs);
int32 rt = int32(_rt);
int32 res = rs + rt;
require(!(rs > 0 && rt > 0 && res <= 0), "MIPS: add overflow");
require(!(rs < 0 && rt < 0 && res >= 0), "MIPS: add underflow");
return uint32(res);
return (_rs + _rt);
}
// addu
else if (_fun == 0x21) {
......@@ -377,12 +372,7 @@ library MIPSInstructions {
}
// sub
else if (_fun == 0x22) {
int32 rs = int32(_rs);
int32 rt = int32(_rt);
int32 res = rs - rt;
require(!(rs > 0 && rt < 0 && res <= 0), "MIPS: sub overflow");
require(!(rs < 0 && rt > 0 && res >= 0), "MIPS: sub underflow");
return uint32(res);
return (_rs - _rt);
}
// subu
else if (_fun == 0x23) {
......
......@@ -104,42 +104,6 @@ contract MIPS_Test is CommonTest {
assertEq(postState, outputState(expect), "unexpected post state");
}
/// @notice Tests that add overflow triggers a revert.
/// @param _rs The first operand.
/// @param _rt The second operand.
function testFuzz_add_overflow_fails(int32 _rs, int32 _rt) external {
// Force overflow.
_rs = int32(bound(int256(_rs), int256(1), int256(type(int32).max)));
_rt = int32(bound(int256(_rt), int256(type(int32).max) - int256(_rs) + 1, int256(type(int32).max)));
uint32 insn = encodespec(17, 18, 8, 0x20); // add t0, s1, s2
(MIPS.State memory state, bytes memory proof) = constructMIPSState(0, insn, 0x4, 0);
state.registers[17] = uint32(_rs);
state.registers[18] = uint32(_rt);
bytes memory encodedState = encodeState(state);
vm.expectRevert("MIPS: add overflow");
mips.step(encodedState, proof, 0);
}
/// @notice Tests that add underflow triggers a revert.
/// @param _rs The first operand.
/// @param _rt The second operand.
function testFuzz_add_underflow_fails(int32 _rs, int32 _rt) external {
// Force underflow.
_rs = int32(bound(int256(_rs), int256(type(int32).min), int256(-1)));
_rt = int32(bound(int256(_rt), int256(type(int32).min), int256(type(int32).min) - int256(_rs) - 1));
uint32 insn = encodespec(17, 18, 8, 0x20); // add t0, s1, s2
(MIPS.State memory state, bytes memory proof) = constructMIPSState(0, insn, 0x4, 0);
state.registers[17] = uint32(_rs);
state.registers[18] = uint32(_rt);
bytes memory encodedState = encodeState(state);
vm.expectRevert("MIPS: add underflow");
mips.step(encodedState, proof, 0);
}
function test_add_shamtNotZero_fails() external {
uint32 insn = encodespec(17, 18, 8, 0x20); // add t0, s1, s2
insn |= 0x1F << 6;
......@@ -172,35 +136,6 @@ contract MIPS_Test is CommonTest {
assertEq(postState, outputState(expect), "unexpected post state");
}
/// @notice Tests that addu overflow does not trigger a revert.
/// @param _rs The first operand.
/// @param _rt The second operand.
function testFuzz_addu_overflow_succeeds(uint32 _rs, uint32 _rt) external {
// Force overflow.
_rs = uint32(bound(_rs, 1, type(uint32).max));
_rt = uint32(bound(_rt, type(uint32).max - _rs + 1, type(uint32).max));
uint32 insn = encodespec(17, 18, 8, 0x21); // addu t0, s1, s2
(MIPS.State memory state, bytes memory proof) = constructMIPSState(0, insn, 0x4, 0);
state.registers[17] = _rs;
state.registers[18] = _rt;
bytes memory encodedState = encodeState(state);
MIPS.State memory expect;
unchecked {
expect.memRoot = state.memRoot;
expect.pc = state.nextPC;
expect.nextPC = state.nextPC + 4;
expect.step = state.step + 1;
expect.registers[8] = state.registers[17] + state.registers[18]; // t0
expect.registers[17] = state.registers[17];
expect.registers[18] = state.registers[18];
}
bytes32 postState = mips.step(encodedState, proof, 0);
assertEq(postState, outputState(expect), "unexpected post state");
}
function test_addu_shamtNotZero_fails() external {
uint32 insn = encodespec(17, 18, 8, 0x21); // addu t0, s1, s2
insn |= 0x1F << 6;
......@@ -233,42 +168,6 @@ contract MIPS_Test is CommonTest {
assertEq(postState, outputState(expect), "unexpected post state");
}
/// @notice Tests that the addi overflow triggers a revert.
/// @param _rs The first operand.
/// @param _imm Immediate value.
function testFuzz_addi_overflow_fails(int32 _rs, int16 _imm) external {
// Force overflow.
_imm = int16(bound(int256(_imm), int256(1), int256(type(int16).max)));
_rs = int32(bound(int256(_rs), int256(type(int32).max) - int256(_imm) + 1, int256(type(int32).max)));
uint32 insn = encodeitype(0x8, 17, 8, uint16(_imm)); // addi t0, s1, _imm
(MIPS.State memory state, bytes memory proof) = constructMIPSState(0, insn, 0x4, 0);
state.registers[8] = 1; // t0
state.registers[17] = uint32(_rs); // s1
bytes memory encodedState = encodeState(state);
vm.expectRevert("MIPS: add overflow");
mips.step(encodedState, proof, 0);
}
/// @notice Tests that addi underflow triggers a reverts.
/// @param _rs The first operand.
/// @param _imm Immediate value.
function testFuzz_addi_underflow_fails(int32 _rs, int16 _imm) external {
// Force underflow.
_rs = int32(bound(int256(_rs), int256(type(int32).min), int256(type(int32).min) + int256(type(int16).max) - 2));
_imm = int16(bound(int256(_imm), int256(type(int16).min), int256(type(int32).min) - int256(_rs) - 1));
uint32 insn = encodeitype(0x8, 17, 8, uint16(_imm)); // addi t0, s1, _imm
(MIPS.State memory state, bytes memory proof) = constructMIPSState(0, insn, 0x4, 0);
state.registers[8] = 1; // t0
state.registers[17] = uint32(_rs); // s1
bytes memory encodedState = encodeState(state);
vm.expectRevert("MIPS: add underflow");
mips.step(encodedState, proof, 0);
}
function test_addiSign_succeeds() external {
uint16 imm = 0xfffe; // -2
uint32 insn = encodeitype(0x8, 17, 8, imm); // addi t0, s1, 40
......@@ -309,34 +208,6 @@ contract MIPS_Test is CommonTest {
assertEq(postState, outputState(expect), "unexpected post state");
}
/// @notice Tests that the addui overflow does not trigger a revert.
/// @param _rs The first operand.
/// @param _imm Immediate value.
function testFuzz_addui_overflow_succeeds(int32 _rs, int16 _imm) external {
// Force overflow.
_imm = int16(bound(int256(_imm), int256(1), int256(type(int16).max)));
_rs = int32(bound(int256(_rs), int256(type(int32).max) - int256(_imm) + 1, int256(type(int32).max)));
uint32 insn = encodeitype(0x9, 17, 8, uint16(_imm)); // addui t0, s1, _imm
(MIPS.State memory state, bytes memory proof) = constructMIPSState(0, insn, 0x4, 0);
state.registers[8] = 1; // t0
state.registers[17] = uint32(_rs); // s1
bytes memory encodedState = encodeState(state);
MIPS.State memory expect;
unchecked {
expect.memRoot = state.memRoot;
expect.pc = state.nextPC;
expect.nextPC = state.nextPC + 4;
expect.step = state.step + 1;
expect.registers[8] = uint32(state.registers[17]) + uint16(_imm);
expect.registers[17] = uint32(state.registers[17]);
}
bytes32 postState = mips.step(encodedState, proof, 0);
assertEq(postState, outputState(expect), "unexpected post state");
}
function test_sub_succeeds() external {
uint32 insn = encodespec(17, 18, 8, 0x22); // sub t0, s1, s2
(MIPS.State memory state, bytes memory proof) = constructMIPSState(0, insn, 0x4, 0);
......@@ -357,44 +228,6 @@ contract MIPS_Test is CommonTest {
assertEq(postState, outputState(expect), "unexpected post state");
}
/// @notice Tests that the sub overflow triggers a revert.
/// @param _rs The first operand.
/// @param _rt The second operand.
function testFuzz_sub_overflow_fails(int32 _rs, int32 _rt) external {
// Force overflow.
_rs = int32(bound(int256(_rs), int256(1), int256(type(int32).max)));
_rt = int32(bound(int256(_rt), int256(type(int32).min), int256(_rs) - int256(type(int32).max) - 1));
uint32 insn = encodespec(17, 18, 8, 0x22); // sub t0, s1, s2
(MIPS.State memory state, bytes memory proof) = constructMIPSState(0, insn, 0x4, 0);
state.registers[17] = uint32(_rs);
state.registers[18] = uint32(_rt);
bytes memory encodedState = encodeState(state);
vm.expectRevert("MIPS: sub overflow");
mips.step(encodedState, proof, 0);
}
/// @notice Tests that the sub underflow triggers a revert.
/// @param _rs The first operand.
/// @param _rt The second operand.
function testFuzz_sub_underflow_fails(int32 _rs, int32 _rt) external {
// Force underflow.
// Minimum value for int32 is -2^31 but the maximum value is 2^31 - 1. We therefore cannot
// trigger an underflow for any number >= -1 because -1 - (2^31 - 1) = -2^31.
_rs = int32(bound(int256(_rs), int256(type(int32).min), int256(-2)));
_rt = int32(bound(int256(_rt), int256(type(int32).max) + 2 + int256(_rs), int256(type(int32).max)));
uint32 insn = encodespec(17, 18, 8, 0x22); // sub t0, s1, s2
(MIPS.State memory state, bytes memory proof) = constructMIPSState(0, insn, 0x4, 0);
state.registers[17] = uint32(_rs);
state.registers[18] = uint32(_rt);
bytes memory encodedState = encodeState(state);
vm.expectRevert("MIPS: sub underflow");
mips.step(encodedState, proof, 0);
}
function test_sub_shamtNotZero_fails() external {
uint32 insn = encodespec(17, 18, 8, 0x22); // sub t0, s1, s2
insn |= 0x1F << 6;
......@@ -427,35 +260,6 @@ contract MIPS_Test is CommonTest {
assertEq(postState, outputState(expect), "unexpected post state");
}
/// @notice Tests that subu overflow does not trigger a revert.
/// @param _rs The first operand.
/// @param _rt The second operand.
function testFuzz_subu_underflow_succeeds(uint32 _rs, uint32 _rt) external {
// Force underflow.
_rs = uint32(bound(_rs, 0, type(uint32).max - 1));
_rt = uint32(bound(_rt, type(uint32).max - _rs, type(uint32).max));
uint32 insn = encodespec(17, 18, 8, 0x23); // subu t0, s1, s2
(MIPS.State memory state, bytes memory proof) = constructMIPSState(0, insn, 0x4, 0);
state.registers[17] = _rs;
state.registers[18] = _rt;
bytes memory encodedState = encodeState(state);
MIPS.State memory expect;
unchecked {
expect.memRoot = state.memRoot;
expect.pc = state.nextPC;
expect.nextPC = state.nextPC + 4;
expect.step = state.step + 1;
expect.registers[8] = state.registers[17] - state.registers[18]; // t0
expect.registers[17] = state.registers[17];
expect.registers[18] = state.registers[18];
}
bytes32 postState = mips.step(encodedState, proof, 0);
assertEq(postState, outputState(expect), "unexpected post state");
}
function test_subu_shamtNotZero_fails() external {
uint32 insn = encodespec(17, 18, 8, 0x23); // subu t0, s1, s2
insn |= 0x1F << 6;
......
......@@ -27,7 +27,7 @@ contract DeploymentSummary is DeploymentSummaryCode {
address internal constant l1StandardBridgeProxyAddress = 0x20A42a5a785622c6Ba2576B2D6e924aA82BFA11D;
address internal constant l2OutputOracleAddress = 0x19652082F846171168Daf378C4fD3ee85a0D4A60;
address internal constant l2OutputOracleProxyAddress = 0x39Af23E00F1e662025aA01b0cEdA19542B78DF99;
address internal constant mipsAddress = 0xcFf3d2300Bf09462BBA3D23EF284a5C60Ef7c187;
address internal constant mipsAddress = 0xD9377D0e45e94F9928F419BfFF5097E65A01630B;
address internal constant optimismMintableERC20FactoryAddress = 0x39Aea2Dd53f2d01c15877aCc2791af6BDD7aD567;
address internal constant optimismMintableERC20FactoryProxyAddress = 0xc7B87b2b892EA5C3CfF47168881FE168C00377FB;
address internal constant optimismPortalAddress = 0xbdD90485FCbcac869D5b5752179815a3103d8131;
......
This source diff could not be displayed because it is too large. You can view the blob instead.
......@@ -27,7 +27,7 @@ contract DeploymentSummaryFaultProofs is DeploymentSummaryFaultProofsCode {
address internal constant l1StandardBridgeProxyAddress = 0x20A42a5a785622c6Ba2576B2D6e924aA82BFA11D;
address internal constant l2OutputOracleAddress = 0x19652082F846171168Daf378C4fD3ee85a0D4A60;
address internal constant l2OutputOracleProxyAddress = 0x39Af23E00F1e662025aA01b0cEdA19542B78DF99;
address internal constant mipsAddress = 0xcFf3d2300Bf09462BBA3D23EF284a5C60Ef7c187;
address internal constant mipsAddress = 0xD9377D0e45e94F9928F419BfFF5097E65A01630B;
address internal constant optimismMintableERC20FactoryAddress = 0x39Aea2Dd53f2d01c15877aCc2791af6BDD7aD567;
address internal constant optimismMintableERC20FactoryProxyAddress = 0xc7B87b2b892EA5C3CfF47168881FE168C00377FB;
address internal constant optimismPortalAddress = 0xbdD90485FCbcac869D5b5752179815a3103d8131;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment