/ contracts / utils / Decimal.sol
Decimal.sol
  1  /*
  2      Copyright 2019 dYdX Trading Inc.
  3  
  4      Licensed under the Apache License, Version 2.0 (the "License");
  5      you may not use this file except in compliance with the License.
  6      You may obtain a copy of the License at
  7  
  8      http://www.apache.org/licenses/LICENSE-2.0
  9  
 10      Unless required by applicable law or agreed to in writing, software
 11      distributed under the License is distributed on an "AS IS" BASIS,
 12      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 13      See the License for the specific language governing permissions and
 14      limitations under the License.
 15  */
 16  
 17  pragma solidity >=0.6.0;
 18  pragma experimental ABIEncoderV2;
 19  
 20  import { SafeMath } from "./SafeMath.sol";
 21  
 22  /**
 23   * @title Decimal
 24   * @author dYdX
 25   *
 26   * Library that defines a fixed-point number with 18 decimal places.
 27   */
 28  library Decimal {
 29      using SafeMath for uint256;
 30  
 31      // ============ Constants ============
 32  
 33      uint256 constant BASE = 10**18;
 34  
 35      // ============ Structs ============
 36  
 37  
 38      struct D256 {
 39          uint256 value;
 40      }
 41  
 42      // ============ Static Functions ============
 43  
 44      function zero()
 45      internal
 46      pure
 47      returns (D256 memory)
 48      {
 49          return D256({ value: 0 });
 50      }
 51  
 52      function one()
 53      internal
 54      pure
 55      returns (D256 memory)
 56      {
 57          return D256({ value: BASE });
 58      }
 59  
 60      function from(
 61          uint256 a
 62      )
 63      internal
 64      pure
 65      returns (D256 memory)
 66      {
 67          return D256({ value: a.mul(BASE) });
 68      }
 69  
 70      function ratio(
 71          uint256 a,
 72          uint256 b
 73      )
 74      internal
 75      pure
 76      returns (D256 memory)
 77      {
 78          return D256({ value: getPartial(a, BASE, b) });
 79      }
 80  
 81      // ============ Self Functions ============
 82  
 83      function add(
 84          D256 memory self,
 85          uint256 b
 86      )
 87      internal
 88      pure
 89      returns (D256 memory)
 90      {
 91          return D256({ value: self.value.add(b.mul(BASE)) });
 92      }
 93  
 94      function sub(
 95          D256 memory self,
 96          uint256 b
 97      )
 98      internal
 99      pure
100      returns (D256 memory)
101      {
102          return D256({ value: self.value.sub(b.mul(BASE)) });
103      }
104  
105      function sub(
106          D256 memory self,
107          uint256 b,
108          string memory reason
109      )
110      internal
111      pure
112      returns (D256 memory)
113      {
114          return D256({ value: self.value.sub(b.mul(BASE), reason) });
115      }
116  
117      function mul(
118          D256 memory self,
119          uint256 b
120      )
121      internal
122      pure
123      returns (D256 memory)
124      {
125          return D256({ value: self.value.mul(b) });
126      }
127  
128      function div(
129          D256 memory self,
130          uint256 b
131      )
132      internal
133      pure
134      returns (D256 memory)
135      {
136          return D256({ value: self.value.div(b) });
137      }
138  
139      function pow(
140          D256 memory self,
141          uint256 b
142      )
143      internal
144      pure
145      returns (D256 memory)
146      {
147          if (b == 0) {
148              return from(1);
149          }
150  
151          D256 memory temp = D256({ value: self.value });
152          for (uint256 i = 1; i < b; i++) {
153              temp = mul(temp, self);
154          }
155  
156          return temp;
157      }
158  
159      function add(
160          D256 memory self,
161          D256 memory b
162      )
163      internal
164      pure
165      returns (D256 memory)
166      {
167          return D256({ value: self.value.add(b.value) });
168      }
169  
170      function sub(
171          D256 memory self,
172          D256 memory b
173      )
174      internal
175      pure
176      returns (D256 memory)
177      {
178          return D256({ value: self.value.sub(b.value) });
179      }
180  
181      function sub(
182          D256 memory self,
183          D256 memory b,
184          string memory reason
185      )
186      internal
187      pure
188      returns (D256 memory)
189      {
190          return D256({ value: self.value.sub(b.value, reason) });
191      }
192  
193      function mul(
194          D256 memory self,
195          D256 memory b
196      )
197      internal
198      pure
199      returns (D256 memory)
200      {
201          return D256({ value: getPartial(self.value, b.value, BASE) });
202      }
203  
204      function div(
205          D256 memory self,
206          D256 memory b
207      )
208      internal
209      pure
210      returns (D256 memory)
211      {
212          return D256({ value: getPartial(self.value, BASE, b.value) });
213      }
214  
215      function equals(D256 memory self, D256 memory b) internal pure returns (bool) {
216          return self.value == b.value;
217      }
218  
219      function greaterThan(D256 memory self, D256 memory b) internal pure returns (bool) {
220          return compareTo(self, b) == 2;
221      }
222  
223      function lessThan(D256 memory self, D256 memory b) internal pure returns (bool) {
224          return compareTo(self, b) == 0;
225      }
226  
227      function greaterThanOrEqualTo(D256 memory self, D256 memory b) internal pure returns (bool) {
228          return compareTo(self, b) > 0;
229      }
230  
231      function lessThanOrEqualTo(D256 memory self, D256 memory b) internal pure returns (bool) {
232          return compareTo(self, b) < 2;
233      }
234  
235      function isZero(D256 memory self) internal pure returns (bool) {
236          return self.value == 0;
237      }
238  
239      function asUint256(D256 memory self) internal pure returns (uint256) {
240          return self.value.div(BASE);
241      }
242  
243      // ============ Core Methods ============
244  
245      function getPartial(
246          uint256 target,
247          uint256 numerator,
248          uint256 denominator
249      )
250      private
251      pure
252      returns (uint256)
253      {
254          return target.mul(numerator).div(denominator);
255      }
256  
257      function compareTo(
258          D256 memory a,
259          D256 memory b
260      )
261      private
262      pure
263      returns (uint256)
264      {
265          if (a.value == b.value) {
266              return 1;
267          }
268          return a.value > b.value ? 2 : 0;
269      }
270  }