Omniscia rain protocol Audit

MathOps Code Style Findings

MathOps Code Style Findings

MOS-01C: Unoptimized Stack Index Adjustment

Description:

The stackIndex is adjusted twice within the applyOp function's execution redundantly as the first subtraction can be offset by a single unit.

Example:

contracts/vm/ops/MathOps.sol
29function applyOp(
30 bytes memory,
31 State memory state_,
32 uint256 opcode_,
33 uint256 operand_
34) internal pure {
35 require(opcode_ < OPS_LENGTH, "MAX_OPCODE");
36 uint256 top_;
37 unchecked {
38 top_ = state_.stackIndex - 1;
39 state_.stackIndex -= operand_;
40 }
41 uint256 baseIndex_ = state_.stackIndex;
42 uint256 cursor_ = baseIndex_;
43 uint256 accumulator_ = state_.stack[cursor_];
44
45 // Addition.
46 if (opcode_ == ADD) {
47 while (cursor_ < top_) {
48 unchecked {
49 cursor_++;
50 }
51 accumulator_ += state_.stack[cursor_];
52 }
53 }
54 // Subtraction.
55 else if (opcode_ == SUB) {
56 while (cursor_ < top_) {
57 unchecked {
58 cursor_++;
59 }
60 accumulator_ -= state_.stack[cursor_];
61 }
62 }
63 // Multiplication.
64 // Slither false positive here complaining about dividing before
65 // multiplying but both are mututally exclusive according to `opcode_`.
66 else if (opcode_ == MUL) {
67 while (cursor_ < top_) {
68 unchecked {
69 cursor_++;
70 }
71 accumulator_ *= state_.stack[cursor_];
72 }
73 }
74 // Division.
75 else if (opcode_ == DIV) {
76 while (cursor_ < top_) {
77 unchecked {
78 cursor_++;
79 }
80 accumulator_ /= state_.stack[cursor_];
81 }
82 }
83 // Modulo.
84 else if (opcode_ == MOD) {
85 while (cursor_ < top_) {
86 unchecked {
87 cursor_++;
88 }
89 accumulator_ %= state_.stack[cursor_];
90 }
91 }
92 // Exponentiation.
93 else if (opcode_ == EXP) {
94 while (cursor_ < top_) {
95 unchecked {
96 cursor_++;
97 }
98 accumulator_**state_.stack[cursor_];
99 }
100 }
101 // Minimum.
102 else if (opcode_ == MIN) {
103 uint256 item_;
104 while (cursor_ < top_) {
105 unchecked {
106 cursor_++;
107 }
108 item_ = state_.stack[cursor_];
109 if (item_ < accumulator_) {
110 accumulator_ = item_;
111 }
112 }
113 }
114 // Maximum.
115 else if (opcode_ == MAX) {
116 uint256 item_;
117 while (cursor_ < top_) {
118 unchecked {
119 cursor_++;
120 }
121 item_ = state_.stack[cursor_];
122 if (item_ > accumulator_) {
123 accumulator_ = item_;
124 }
125 }
126 }
127
128 unchecked {
129 state_.stack[baseIndex_] = accumulator_;
130 state_.stackIndex++;
131 }
132}

Recommendation:

We advise this to be done so to optimize the gas cost of the function.

Alleviation:

The Rain Protocol team has stated that they plan to address this in an upcoming pull request. Given that this is a finding planned to be fixed, we consider this exhibit acknowledged.