This repository has been archived by the owner on Dec 7, 2023. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 16
/
MathOps.sol
133 lines (128 loc) · 3.84 KB
/
MathOps.sol
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
// SPDX-License-Identifier: CAL
pragma solidity =0.8.10;
import {State} from "../RainVM.sol";
/// @title BlockOps
/// @notice RainVM opcode pack to perform basic checked math operations.
/// Underflow and overflow will error as per default solidity behaviour.
library MathOps {
/// Opcode for addition.
uint256 private constant ADD = 0;
/// Opcode for subtraction.
uint256 private constant SUB = 1;
/// Opcode for multiplication.
uint256 private constant MUL = 2;
/// Opcode for division.
uint256 private constant DIV = 3;
/// Opcode for modulo.
uint256 private constant MOD = 4;
/// Opcode for exponentiation.
uint256 private constant EXP = 5;
/// Opcode for minimum.
uint256 private constant MIN = 6;
/// Opcode for maximum.
uint256 private constant MAX = 7;
/// Number of provided opcodes for `MathOps`.
uint256 internal constant OPS_LENGTH = 8;
function applyOp(
bytes memory,
State memory state_,
uint256 opcode_,
uint256 operand_
) internal pure {
require(opcode_ < OPS_LENGTH, "MAX_OPCODE");
uint256 top_;
unchecked {
top_ = state_.stackIndex - 1;
state_.stackIndex -= operand_;
}
uint256 baseIndex_ = state_.stackIndex;
uint256 cursor_ = baseIndex_;
uint256 accumulator_ = state_.stack[cursor_];
// Addition.
if (opcode_ == ADD) {
while (cursor_ < top_) {
unchecked {
cursor_++;
}
accumulator_ += state_.stack[cursor_];
}
}
// Subtraction.
else if (opcode_ == SUB) {
while (cursor_ < top_) {
unchecked {
cursor_++;
}
accumulator_ -= state_.stack[cursor_];
}
}
// Multiplication.
// Slither false positive here complaining about dividing before
// multiplying but both are mututally exclusive according to `opcode_`.
else if (opcode_ == MUL) {
while (cursor_ < top_) {
unchecked {
cursor_++;
}
accumulator_ *= state_.stack[cursor_];
}
}
// Division.
else if (opcode_ == DIV) {
while (cursor_ < top_) {
unchecked {
cursor_++;
}
accumulator_ /= state_.stack[cursor_];
}
}
// Modulo.
else if (opcode_ == MOD) {
while (cursor_ < top_) {
unchecked {
cursor_++;
}
accumulator_ %= state_.stack[cursor_];
}
}
// Exponentiation.
else if (opcode_ == EXP) {
while (cursor_ < top_) {
unchecked {
cursor_++;
}
accumulator_ = accumulator_**state_.stack[cursor_];
}
}
// Minimum.
else if (opcode_ == MIN) {
uint256 item_;
while (cursor_ < top_) {
unchecked {
cursor_++;
}
item_ = state_.stack[cursor_];
if (item_ < accumulator_) {
accumulator_ = item_;
}
}
}
// Maximum.
else if (opcode_ == MAX) {
uint256 item_;
while (cursor_ < top_) {
unchecked {
cursor_++;
}
item_ = state_.stack[cursor_];
if (item_ > accumulator_) {
accumulator_ = item_;
}
}
}
unchecked {
state_.stack[baseIndex_] = accumulator_;
state_.stackIndex++;
}
}
}