diff --git a/src/generated/Rainterpreter.pointers.sol b/src/generated/Rainterpreter.pointers.sol index 0be596382..6aece842f 100644 --- a/src/generated/Rainterpreter.pointers.sol +++ b/src/generated/Rainterpreter.pointers.sol @@ -10,11 +10,11 @@ pragma solidity =0.8.25; /// @dev Hash of the known bytecode. -bytes32 constant BYTECODE_HASH = bytes32(0xddf6e7bcbe3d3394d100881801381404f5f91c19b9d21d348482ff09fbabd3f4); +bytes32 constant BYTECODE_HASH = bytes32(0xe67bfbe2d8ebe116b64bcb02d5e29330d9ade17c1c3367def6883adee4d399e7); /// @dev The function pointers known to the interpreter for dynamic dispatch. /// By setting these as a constant they can be inlined into the interpreter /// and loaded at eval time for very low gas (~100) due to the compiler /// optimising it to a single `codecopy` to build the in memory bytes array. bytes constant OPCODE_FUNCTION_POINTERS = - hex"070a073c076008ec09b509c709d909f20a160a4a0a5b0a6c0b0e0b2d0bdc0c600c710c820c820c930d200d390d4d0d660d790ddb0e290e5a0ea80ef60fdd"; + hex"07120744076808f409bd09cf09e109fa0a1e0a520a630a740b160b350be40c680c790c8a0c8a0c9b0d280d410d550d6e0d870d9a0dfc0e4a0e7b0ec90f170ffe"; diff --git a/src/generated/RainterpreterExpressionDeployer.pointers.sol b/src/generated/RainterpreterExpressionDeployer.pointers.sol index 9558e046a..24f41ea60 100644 --- a/src/generated/RainterpreterExpressionDeployer.pointers.sol +++ b/src/generated/RainterpreterExpressionDeployer.pointers.sol @@ -10,11 +10,11 @@ pragma solidity =0.8.25; /// @dev Hash of the known bytecode. -bytes32 constant BYTECODE_HASH = bytes32(0x92914df17907d045c2e205ffc7629e9362435836efff6ff7bf1d5cb6ead71c74); +bytes32 constant BYTECODE_HASH = bytes32(0x84daba4ae586abd5a30c407378175e919ea82b291b9bff08604debfa5e59d183); /// @dev The hash of the meta that describes the contract. -bytes32 constant DESCRIBED_BY_META_HASH = bytes32(0xf2422b9957601bb0f760ed0062347ad9e9fda6fad2f4b119aa9ddb874618397a); +bytes32 constant DESCRIBED_BY_META_HASH = bytes32(0x53bf9fadcc5583af0b446b3d62f227146b09d4476ca6f3998e21c1410fe04965); /// @dev The function pointers for the integrity check fns. bytes constant INTEGRITY_FUNCTION_POINTERS = - hex"0db00e2e0e92100c1016101610201029104410ea10ea114611be10161020100c100c100c100c11cb101610161016100c11d511fd100c11fd11fd102011cb"; + hex"0db80e360e9a1014101e101e10281031104c10f210f2114e11c6101e1028101410141014101411d3101e101e101e101e101411dd1205101412051205102811d3"; diff --git a/src/generated/RainterpreterParser.pointers.sol b/src/generated/RainterpreterParser.pointers.sol index 52ba08368..1f49764ac 100644 --- a/src/generated/RainterpreterParser.pointers.sol +++ b/src/generated/RainterpreterParser.pointers.sol @@ -10,7 +10,7 @@ pragma solidity =0.8.25; /// @dev Hash of the known bytecode. -bytes32 constant BYTECODE_HASH = bytes32(0x58f6018d11af765b99cb6f438c3cfcbb09b18a8406b4fafa5cb1645b3ac674af); +bytes32 constant BYTECODE_HASH = bytes32(0xd292c1e12f252b9afbe785ce00e0c8980c99b3469982fc5ffdab15e8017acd83); /// @dev The parse meta that is used to lookup word definitions. /// The structure of the parse meta is: @@ -29,7 +29,7 @@ bytes32 constant BYTECODE_HASH = bytes32(0x58f6018d11af765b99cb6f438c3cfcbb09b18 /// bit count of the previous bloom filter. If we reach the end of the bloom /// filters then we have a miss. bytes constant PARSE_META = - hex"01092404900810009008201088000400e0010080000800001028010100080900090002cd70471d14fbe61685cf8700f861d119d0e20c0e8be82d1e7c7f8004e5ab37184d06d00d67df8415fedd510602c61f08bcae760bcd088610f1c17805ac4b9f0a09bc09170ce432091ef7b011dfb72601a91367121faf890c2b9f481be804c11abd68ce14811fdb034a067c0fffb07907743c4a1c15024513edf10f"; + hex"01092404940810009008201088000400e0010080000800001028010100080900090002cd70471e14fbe61685cf8700f861d11ad0e20c0e8be82d1f7c7f8004e5ab37194d06d00d67df8415fedd510602c61f08bcae760bcd088610f1c17805ac4b9f0a09bc09180ce432091ef7b011dfb72601a91367121faf890c2b9f481ce804c11bbd68ce14811fdb1726c459034a067c0fffb07907743c4a1d15024513edf10f"; /// @dev The build depth of the parser meta. @@ -39,11 +39,11 @@ uint8 constant PARSE_META_BUILD_DEPTH = 2; /// These positional indexes all map to the same indexes looked up in the parse /// meta. bytes constant OPERAND_HANDLER_FUNCTION_POINTERS = - hex"1992199219921a671b7e1b7e1b7e1a671a671992199219921b7e1b7e1b7e1b7e1b7e1b7e1b7e1b7e1b7e1b7e1b7e1b7e1b7e1b7e1b7e1b7e19921b7e1b7e"; + hex"199a199a199a1a6f1b861b861b861a6f1a6f199a199a199a1b861b861b861b861b861b861b861b861b861b861b861b861b861b861b861b861b86199a1b861b86"; /// @dev Every two bytes is a function pointer for a literal parser. /// Literal dispatches are determined by the first byte(s) of the literal /// rather than a full word lookup, and are done with simple conditional /// jumps as the possibilities are limited compared to the number of words we /// have. -bytes constant LITERAL_PARSER_FUNCTION_POINTERS = hex"14da170c174f17ed"; +bytes constant LITERAL_PARSER_FUNCTION_POINTERS = hex"14e21714175717f5"; diff --git a/src/lib/op/LibAllStandardOps.sol b/src/lib/op/LibAllStandardOps.sol index a8fc10f39..36e1af760 100644 --- a/src/lib/op/LibAllStandardOps.sol +++ b/src/lib/op/LibAllStandardOps.sol @@ -55,7 +55,7 @@ import {LibOpGreaterThan} from "./logic/LibOpGreaterThan.sol"; import {LibOpGreaterThanOrEqualToNP} from "./logic/LibOpGreaterThanOrEqualToNP.sol"; import {LibOpIfNP} from "./logic/LibOpIfNP.sol"; import {LibOpIsZeroNP} from "./logic/LibOpIsZeroNP.sol"; -import {LibOpLessThanNP} from "./logic/LibOpLessThanNP.sol"; +import {LibOpLessThan} from "./logic/LibOpLessThan.sol"; import {LibOpLessThanOrEqualToNP} from "./logic/LibOpLessThanOrEqualToNP.sol"; // import {LibOpExponentialGrowth} from "./math/growth/LibOpExponentialGrowth.sol"; @@ -105,7 +105,7 @@ import {LibParseLiteralHex} from "../parse/literal/LibParseLiteralHex.sol"; import {LibParseLiteralSubParseable} from "../parse/literal/LibParseLiteralSubParseable.sol"; /// @dev Number of ops currently provided by `AllStandardOps`. -uint256 constant ALL_STANDARD_OPS_LENGTH = 31; +uint256 constant ALL_STANDARD_OPS_LENGTH = 32; /// @title LibAllStandardOps /// @notice Every opcode available from the core repository laid out as a single @@ -221,7 +221,7 @@ library LibAllStandardOps { // "If the first input is nonzero, the second input is used. Otherwise, the third input is used. If is eagerly evaluated." // ), // AuthoringMetaV2("is-zero", "1 if the input is 0, 0 otherwise."), - // AuthoringMetaV2("less-than", "1 if the first input is less than the second input, 0 otherwise."), + AuthoringMetaV2("less-than", "true if the first input is less than the second input, false otherwise."), // AuthoringMetaV2( // "less-than-or-equal-to", "1 if the first input is less than or equal to the second input, 0 otherwise." // ), @@ -431,8 +431,8 @@ library LibAllStandardOps { // LibParseOperand.handleOperandDisallowed, // // is-zero // LibParseOperand.handleOperandDisallowed, - // // less-than - // LibParseOperand.handleOperandDisallowed, + // less-than + LibParseOperand.handleOperandDisallowed, // // less-than-or-equal-to // LibParseOperand.handleOperandDisallowed, // // exponential-growth @@ -578,7 +578,7 @@ library LibAllStandardOps { // LibOpGreaterThanOrEqualToNP.integrity, // LibOpIfNP.integrity, // LibOpIsZeroNP.integrity, - // LibOpLessThanNP.integrity, + LibOpLessThan.integrity, // LibOpLessThanOrEqualToNP.integrity, // LibOpExponentialGrowth.integrity, // LibOpLinearGrowth.integrity, @@ -690,7 +690,7 @@ library LibAllStandardOps { // LibOpGreaterThanOrEqualToNP.run, // LibOpIfNP.run, // LibOpIsZeroNP.run, - // LibOpLessThanNP.run, + LibOpLessThan.run, // LibOpLessThanOrEqualToNP.run, // LibOpExponentialGrowth.run, // LibOpLinearGrowth.run, diff --git a/src/lib/op/logic/LibOpLessThanNP.sol b/src/lib/op/logic/LibOpLessThan.sol similarity index 54% rename from src/lib/op/logic/LibOpLessThanNP.sol rename to src/lib/op/logic/LibOpLessThan.sol index fff72ef96..83d408af1 100644 --- a/src/lib/op/logic/LibOpLessThanNP.sol +++ b/src/lib/op/logic/LibOpLessThan.sol @@ -5,11 +5,13 @@ import {OperandV2} from "rain.interpreter.interface/interface/unstable/IInterpre import {Pointer} from "rain.solmem/lib/LibPointer.sol"; import {IntegrityCheckState} from "../../integrity/LibIntegrityCheck.sol"; import {InterpreterState} from "../../state/LibInterpreterState.sol"; +import {StackItem} from "rain.interpreter.interface/interface/unstable/IInterpreterV4.sol"; +import {Float, LibDecimalFloat} from "rain.math.float/lib/LibDecimalFloat.sol"; -/// @title LibOpLessThanNP +/// @title LibOpLessThan /// @notice Opcode to return 1 if the first item on the stack is less than /// the second item on the stack, else 0. -library LibOpLessThanNP { +library LibOpLessThan { function integrity(IntegrityCheckState memory, OperandV2) internal pure returns (uint256, uint256) { return (2, 1); } @@ -17,21 +19,30 @@ library LibOpLessThanNP { /// LT /// LT is 1 if the first item is less than the second item, else 0. function run(InterpreterState memory, OperandV2, Pointer stackTop) internal pure returns (Pointer) { + Float a; + Float b; assembly ("memory-safe") { - let a := mload(stackTop) + a := mload(stackTop) stackTop := add(stackTop, 0x20) - mstore(stackTop, lt(a, mload(stackTop))) + b := mload(stackTop) + } + bool lessThan = LibDecimalFloat.lt(a, b); + assembly ("memory-safe") { + mstore(stackTop, lessThan) } return stackTop; } /// Gas intensive reference implementation of LT for testing. - function referenceFn(InterpreterState memory, OperandV2, uint256[] memory inputs) + function referenceFn(InterpreterState memory, OperandV2, StackItem[] memory inputs) internal pure - returns (uint256[] memory outputs) + returns (StackItem[] memory outputs) { - outputs = new uint256[](1); - outputs[0] = inputs[0] < inputs[1] ? 1 : 0; + Float a = Float.wrap(StackItem.unwrap(inputs[0])); + Float b = Float.wrap(StackItem.unwrap(inputs[1])); + bool lessThan = LibDecimalFloat.lt(a, b); + outputs = new StackItem[](1); + outputs[0] = StackItem.wrap(bytes32(uint256(lessThan ? 1 : 0))); } } diff --git a/test/src/lib/op/logic/LibOpLessThan.t.sol b/test/src/lib/op/logic/LibOpLessThan.t.sol new file mode 100644 index 000000000..0da22e9cd --- /dev/null +++ b/test/src/lib/op/logic/LibOpLessThan.t.sol @@ -0,0 +1,122 @@ +// SPDX-License-Identifier: CAL +pragma solidity =0.8.25; + +import {OpTest} from "test/abstract/OpTest.sol"; +import {LibContext} from "rain.interpreter.interface/lib/caller/LibContext.sol"; +import {LibOpLessThan} from "src/lib/op/logic/LibOpLessThan.sol"; +import { + IInterpreterV4, + OperandV2, + SourceIndexV2, + FullyQualifiedNamespace, + EvalV4 +} from "rain.interpreter.interface/interface/unstable/IInterpreterV4.sol"; +import {SignedContextV1} from "rain.interpreter.interface/interface/IInterpreterCallerV3.sol"; +import {InterpreterState} from "src/lib/state/LibInterpreterState.sol"; +import {IntegrityCheckState, BadOpInputsLength} from "src/lib/integrity/LibIntegrityCheck.sol"; +import {LibOperand} from "test/lib/operand/LibOperand.sol"; +import {StackItem} from "rain.interpreter.interface/interface/unstable/IInterpreterV4.sol"; + +contract LibOpLessThanTest is OpTest { + /// Directly test the integrity logic of LibOpLessThan. No matter the + /// operand inputs, the calc inputs must be 2, and the calc outputs must be + /// 1. + function testOpLessThanIntegrityHappy( + IntegrityCheckState memory state, + uint8 inputs, + uint8 outputs, + uint16 operandData + ) external pure { + inputs = uint8(bound(inputs, 0, 0x0F)); + outputs = uint8(bound(outputs, 0, 0x0F)); + (uint256 calcInputs, uint256 calcOutputs) = + LibOpLessThan.integrity(state, LibOperand.build(inputs, outputs, operandData)); + + // The inputs from the operand are ignored. The op is always 2 inputs. + assertEq(calcInputs, 2); + assertEq(calcOutputs, 1); + } + + /// Directly test the runtime logic of LibOpLessThan. + function testOpLessThanRun(StackItem input1, StackItem input2) external view { + InterpreterState memory state = opTestDefaultInterpreterState(); + StackItem[] memory inputs = new StackItem[](2); + inputs[0] = input1; + inputs[1] = input2; + OperandV2 operand = LibOperand.build(uint8(inputs.length), 1, 0); + opReferenceCheck(state, operand, LibOpLessThan.referenceFn, LibOpLessThan.integrity, LibOpLessThan.run, inputs); + } + + /// Test the eval of less than opcode parsed from a string. Tests 2 inputs. + /// Both inputs are 0. + function testOpLessThanEval2ZeroInputs() external view { + checkHappy("_: less-than(0 0);", 0, ""); + } + + /// Test the eval of less than opcode parsed from a string. Tests 2 inputs. + /// The first input is 0, the second input is 1. + function testOpLessThanEval2InputsFirstZeroSecondOne() external view { + checkHappy("_: less-than(0 1);", bytes32(uint256(1)), ""); + } + + /// Test the eval of less than opcode parsed from a string. Tests 2 inputs. + /// The first input is 1, the second input is 0. + function testOpLessThanNPEval2InputsFirstOneSecondZero() external view { + checkHappy("_: less-than(1 0);", bytes32(uint256(0)), ""); + } + + /// Test the eval of less than opcode parsed from a string. Tests 2 inputs. + /// Both inputs are 1. + function testOpLessThanNPEval2InputsBothOne() external view { + checkHappy("_: less-than(1 1);", bytes32(uint256(0)), ""); + } + + // Test 1.1 lt 1.2, which should return 1. + function testOpLessThanNP1_1Lt1_2() external view { + checkHappy("_: less-than(1.1 1.2);", bytes32(uint256(1)), ""); + } + + /// Test 1.0 lt 1 which should return 0. + function testOpLessThanNP1_0Lt1() external view { + checkHappy("_: less-than(1.0 1);", bytes32(uint256(0)), ""); + } + + // Test -1.1 lt -1.2, which should return 0. + function testOpLessThanNPMinus1_1LtMinus1_2() external view { + checkHappy("_: less-than(-1.1 -1.2);", bytes32(uint256(0)), ""); + } + + /// Test -1 lt 0, which should return 1. + function testOpLessThanNPMinus1Lt0() external view { + checkHappy("_: less-than(-1 0);", bytes32(uint256(1)), ""); + } + + /// Test that a less than to without inputs fails integrity check. + function testOpLessThanToNPEvalFail0Inputs() public { + vm.expectRevert(abi.encodeWithSelector(BadOpInputsLength.selector, 0, 2, 0)); + bytes memory bytecode = iDeployer.parse2("_: less-than();"); + (bytecode); + } + + /// Test that a less than to with 1 input fails integrity check. + function testOpLessThanToNPEvalFail1Input() public { + vm.expectRevert(abi.encodeWithSelector(BadOpInputsLength.selector, 1, 2, 1)); + bytes memory bytecode = iDeployer.parse2("_: less-than(0x00);"); + (bytecode); + } + + /// Test that a less than to with 3 inputs fails integrity check. + function testOpLessThanToNPEvalFail3Inputs() public { + vm.expectRevert(abi.encodeWithSelector(BadOpInputsLength.selector, 3, 2, 3)); + bytes memory bytecode = iDeployer.parse2("_: less-than(0x00 0x00 0x00);"); + (bytecode); + } + + function testOpLessThanNPZeroOutputs() external { + checkBadOutputs(": less-than(0 0);", 2, 1, 0); + } + + function testOpLessThanNPTwoOutputs() external { + checkBadOutputs("_ _: less-than(30 0);", 2, 1, 2); + } +} diff --git a/test/src/lib/op/logic/LibOpLessThanNP.t.sol b/test/src/lib/op/logic/LibOpLessThanNP.t.sol deleted file mode 100644 index 06a87aee9..000000000 --- a/test/src/lib/op/logic/LibOpLessThanNP.t.sol +++ /dev/null @@ -1,164 +0,0 @@ -// SPDX-License-Identifier: CAL -pragma solidity =0.8.25; - -// // import {OpTest} from "test/abstract/OpTest.sol"; -// // import {LibContext} from "rain.interpreter.interface/lib/caller/LibContext.sol"; -// // import {LibOpLessThanNP} from "src/lib/op/logic/LibOpLessThanNP.sol"; -// // import { -// // IInterpreterV4, -// // Operand, -// // SourceIndexV2, -// // FullyQualifiedNamespace, -// // IInterpreterStoreV2, -// // EvalV4 -// // } from "rain.interpreter.interface/interface/unstable/IInterpreterV4.sol"; -// // import {SignedContextV1} from "rain.interpreter.interface/interface/IInterpreterCallerV3.sol"; -// // import {InterpreterState} from "src/lib/state/LibInterpreterState.sol"; -// // import {IntegrityCheckState, BadOpInputsLength} from "src/lib/integrity/LibIntegrityCheck.sol"; -// // import {LibOperand} from "test/lib/operand/LibOperand.sol"; - -// contract LibOpLessThanNPTest is OpTest { -// /// Directly test the integrity logic of LibOpLessThanNP. No matter the -// /// operand inputs, the calc inputs must be 2, and the calc outputs must be -// /// 1. -// function testOpLessThanNPIntegrityHappy( -// IntegrityCheckState memory state, -// uint8 inputs, -// uint8 outputs, -// uint16 operandData -// ) external pure { -// inputs = uint8(bound(inputs, 0, 0x0F)); -// outputs = uint8(bound(outputs, 0, 0x0F)); -// (uint256 calcInputs, uint256 calcOutputs) = -// LibOpLessThanNP.integrity(state, LibOperand.build(inputs, outputs, operandData)); - -// // // The inputs from the operand are ignored. The op is always 2 inputs. -// // assertEq(calcInputs, 2); -// // assertEq(calcOutputs, 1); -// // } - -// /// Directly test the runtime logic of LibOpLessThanNP. -// function testOpLessThanNPRun(uint256 input1, uint256 input2) external view { -// InterpreterState memory state = opTestDefaultInterpreterState(); -// uint256[] memory inputs = new uint256[](2); -// inputs[0] = input1; -// inputs[1] = input2; -// Operand operand = LibOperand.build(uint8(inputs.length), 1, 0); -// opReferenceCheck( -// state, operand, LibOpLessThanNP.referenceFn, LibOpLessThanNP.integrity, LibOpLessThanNP.run, inputs -// ); -// } - -// /// Test the eval of less than opcode parsed from a string. Tests 2 inputs. -// /// Both inputs are 0. -// function testOpLessThanNPEval2ZeroInputs() external view { -// bytes memory bytecode = iDeployer.parse2("_: less-than(0 0);"); -// (uint256[] memory stack, uint256[] memory kvs) = iInterpreter.eval4( -// EvalV4({ -// store: iStore, -// namespace: FullyQualifiedNamespace.wrap(0), -// bytecode: bytecode, -// sourceIndex: SourceIndexV2.wrap(0), -// context: LibContext.build(new uint256[][](0), new SignedContextV1[](0)), -// inputs: new uint256[](0), -// stateOverlay: new uint256[](0) -// }) -// ); - -// // assertEq(stack.length, 1); -// // assertEq(stack[0], 0); -// // assertEq(kvs.length, 0); -// // } - -// /// Test the eval of less than opcode parsed from a string. Tests 2 inputs. -// /// The first input is 0, the second input is 1. -// function testOpLessThanNPEval2InputsFirstZeroSecondOne() external view { -// bytes memory bytecode = iDeployer.parse2("_: less-than(0 1);"); -// (uint256[] memory stack, uint256[] memory kvs) = iInterpreter.eval4( -// EvalV4({ -// store: iStore, -// namespace: FullyQualifiedNamespace.wrap(0), -// bytecode: bytecode, -// sourceIndex: SourceIndexV2.wrap(0), -// context: LibContext.build(new uint256[][](0), new SignedContextV1[](0)), -// inputs: new uint256[](0), -// stateOverlay: new uint256[](0) -// }) -// ); - -// // assertEq(stack.length, 1); -// // assertEq(stack[0], 1); -// // assertEq(kvs.length, 0); -// // } - -// /// Test the eval of less than opcode parsed from a string. Tests 2 inputs. -// /// The first input is 1, the second input is 0. -// function testOpLessThanNPEval2InputsFirstOneSecondZero() external view { -// bytes memory bytecode = iDeployer.parse2("_: less-than(1 0);"); -// (uint256[] memory stack, uint256[] memory kvs) = iInterpreter.eval4( -// EvalV4({ -// store: iStore, -// namespace: FullyQualifiedNamespace.wrap(0), -// bytecode: bytecode, -// sourceIndex: SourceIndexV2.wrap(0), -// context: LibContext.build(new uint256[][](0), new SignedContextV1[](0)), -// inputs: new uint256[](0), -// stateOverlay: new uint256[](0) -// }) -// ); - -// // assertEq(stack.length, 1); -// // assertEq(stack[0], 0); -// // assertEq(kvs.length, 0); -// // } - -// /// Test the eval of less than opcode parsed from a string. Tests 2 inputs. -// /// Both inputs are 1. -// function testOpLessThanNPEval2InputsBothOne() external view { -// bytes memory bytecode = iDeployer.parse2("_: less-than(1 1);"); -// (uint256[] memory stack, uint256[] memory kvs) = iInterpreter.eval4( -// EvalV4({ -// store: iStore, -// namespace: FullyQualifiedNamespace.wrap(0), -// bytecode: bytecode, -// sourceIndex: SourceIndexV2.wrap(0), -// context: LibContext.build(new uint256[][](0), new SignedContextV1[](0)), -// inputs: new uint256[](0), -// stateOverlay: new uint256[](0) -// }) -// ); - -// // assertEq(stack.length, 1); -// // assertEq(stack[0], 0); -// // assertEq(kvs.length, 0); -// // } - -// // /// Test that a less than to without inputs fails integrity check. -// // function testOpLessThanToNPEvalFail0Inputs() public { -// // vm.expectRevert(abi.encodeWithSelector(BadOpInputsLength.selector, 0, 2, 0)); -// // bytes memory bytecode = iDeployer.parse2("_: less-than();"); -// // (bytecode); -// // } - -// // /// Test that a less than to with 1 input fails integrity check. -// // function testOpLessThanToNPEvalFail1Input() public { -// // vm.expectRevert(abi.encodeWithSelector(BadOpInputsLength.selector, 1, 2, 1)); -// // bytes memory bytecode = iDeployer.parse2("_: less-than(0x00);"); -// // (bytecode); -// // } - -// // /// Test that a less than to with 3 inputs fails integrity check. -// // function testOpLessThanToNPEvalFail3Inputs() public { -// // vm.expectRevert(abi.encodeWithSelector(BadOpInputsLength.selector, 3, 2, 3)); -// // bytes memory bytecode = iDeployer.parse2("_: less-than(0x00 0x00 0x00);"); -// // (bytecode); -// // } - -// // function testOpLessThanNPZeroOutputs() external { -// // checkBadOutputs(": less-than(0 0);", 2, 1, 0); -// // } - -// // function testOpLessThanNPTwoOutputs() external { -// // checkBadOutputs("_ _: less-than(30 0);", 2, 1, 2); -// // } -// // } diff --git a/test/src/lib/op/math/LibOpMul.t.sol b/test/src/lib/op/math/LibOpMul.t.sol index 56e3f633f..a415e9711 100644 --- a/test/src/lib/op/math/LibOpMul.t.sol +++ b/test/src/lib/op/math/LibOpMul.t.sol @@ -56,7 +56,7 @@ contract LibOpMulTest is OpTest { try this._testOpMulRun(operand, inputs) {} catch (bytes memory err) { - assert(bytes4(err) == CoefficientOverflow.selector || bytes4(err) == ExponentOverflow.selector); + assertTrue(bytes4(err) == CoefficientOverflow.selector || bytes4(err) == ExponentOverflow.selector); } }