Skip to content

Commit

Permalink
add linting
Browse files Browse the repository at this point in the history
  • Loading branch information
moodysalem committed Oct 15, 2020
1 parent 21e66a4 commit 6ddfedd
Show file tree
Hide file tree
Showing 25 changed files with 367 additions and 159 deletions.
25 changes: 0 additions & 25 deletions .github/workflows/CI.yml

This file was deleted.

31 changes: 31 additions & 0 deletions .github/workflows/lint.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
name: Lint

on:
push:
branches:
- master
pull_request_target:

jobs:
run-linters:
name: Run linters
runs-on: ubuntu-latest

steps:
- name: Check out Git repository
uses: actions/checkout@v2

- name: Set up node
uses: actions/setup-node@v1
with:
node-version: 12

- name: Install dependencies
run: yarn

- name: Run linters
uses: wearerequired/lint-action@feature/pull_request_target
with:
github_token: ${{ secrets.github_token }}
prettier: true
auto_fix: true
32 changes: 32 additions & 0 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
name: Tests

on:
push:
branches:
- master
pull_request:

jobs:
unit-tests:
name: Unit Tests
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v1

- uses: actions/setup-node@v1
with:
node-version: 12.x

- id: yarn-cache
run: echo "::set-output name=dir::$(yarn cache dir)"

- uses: actions/cache@v1
with:
path: ${{ steps.yarn-cache.outputs.dir }}
key: yarn-${{ hashFiles('**/yarn.lock') }}
restore-keys: |
yarn-
- run: yarn
- run: yarn test
6 changes: 6 additions & 0 deletions .solhint.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"plugins": ["prettier"],
"rules": {
"prettier/prettier": "error"
}
}
7 changes: 4 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# uniswap-lib

[![Actions Status](https://github.com/Uniswap/uniswap-lib/workflows/CI/badge.svg)](https://github.com/Uniswap/uniswap-lib/actions)
[![Tests](https://github.com/Uniswap/uniswap-lib/workflows/Tests/badge.svg)](https://github.com/Uniswap/uniswap-lib/actions?query=workflow%3ATests)
[![npm](https://img.shields.io/npm/v/@uniswap/lib)](https://unpkg.com/@uniswap/lib@latest/)

Solidity libraries that are shared across Uniswap contracts. These libraries are focused on safety and gas efficiency.
Expand All @@ -15,10 +15,11 @@ Run `yarn test` to execute the test suite.

## Usage

Install this in another project via `yarn add @uniswap/lib`
Install this in another project via `yarn add @uniswap/lib`

Then import the contracts via:

```solidity
import "@uniswap/lib/contracts/libraries/Babylonian.sol";
import '@uniswap/lib/contracts/libraries/Babylonian.sol';
```
14 changes: 7 additions & 7 deletions contracts/libraries/AddressStringUtil.sol
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,12 @@ pragma solidity >=0.5.0;

library AddressStringUtil {
// converts an address to the uppercase hex string, extracting only len bytes (up to 20, multiple of 2)
function toAsciiString(address addr, uint len) internal pure returns (string memory) {
require(len % 2 == 0 && len > 0 && len <= 40, "AddressStringUtil: INVALID_LEN");
function toAsciiString(address addr, uint256 len) internal pure returns (string memory) {
require(len % 2 == 0 && len > 0 && len <= 40, 'AddressStringUtil: INVALID_LEN');

bytes memory s = new bytes(len);
uint addrNum = uint(addr);
for (uint i = 0; i < len / 2; i++) {
uint256 addrNum = uint256(addr);
for (uint256 i = 0; i < len / 2; i++) {
// shift right and truncate all but the least significant byte to extract the byte at position 19-i
uint8 b = uint8(addrNum >> (8 * (19 - i)));
// first hex character is the most significant 4 bits
Expand All @@ -25,11 +25,11 @@ library AddressStringUtil {
// hi and lo are only 4 bits and between 0 and 16
// this method converts those values to the unicode/ascii code point for the hex representation
// uses upper case for the characters
function char(uint8 b) private pure returns (byte c) {
function char(uint8 b) private pure returns (bytes1 c) {
if (b < 10) {
return byte(b + 0x30);
return bytes1(b + 0x30);
} else {
return byte(b + 0x37);
return bytes1(b + 0x37);
}
}
}
4 changes: 2 additions & 2 deletions contracts/libraries/Babylonian.sol
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,10 @@ pragma solidity >=0.4.0;
// computes square roots using the babylonian method
// https://en.wikipedia.org/wiki/Methods_of_computing_square_roots#Babylonian_method
library Babylonian {
function sqrt(uint y) internal pure returns (uint z) {
function sqrt(uint256 y) internal pure returns (uint256 z) {
if (y > 3) {
z = y;
uint x = y / 2 + 1;
uint256 x = y / 2 + 1;
while (x < z) {
z = x;
x = (y / x + x) / 2;
Expand Down
34 changes: 17 additions & 17 deletions contracts/libraries/FixedPoint.sol
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,13 @@ library FixedPoint {
// range: [0, 2**144 - 1]
// resolution: 1 / 2**112
struct uq144x112 {
uint _x;
uint256 _x;
}

uint8 private constant RESOLUTION = 112;
uint private constant Q112 = uint(1) << RESOLUTION;
uint private constant Q224 = Q112 << RESOLUTION;
uint private constant LOWER_MASK = 0xffffffffffffffffffffffffffff; // decimal of UQ*x112 (lower 112 bits)
uint256 private constant Q112 = uint256(1) << RESOLUTION;
uint256 private constant Q224 = Q112 << RESOLUTION;
uint256 private constant LOWER_MASK = 0xffffffffffffffffffffffffffff; // decimal of UQ*x112 (lower 112 bits)

// encode a uint112 as a UQ112x112
function encode(uint112 x) internal pure returns (uq112x112 memory) {
Expand All @@ -30,7 +30,7 @@ library FixedPoint {

// encodes a uint144 as a UQ144x112
function encode144(uint144 x) internal pure returns (uq144x112 memory) {
return uq144x112(uint(x) << RESOLUTION);
return uq144x112(uint256(x) << RESOLUTION);
}

// decode a UQ112x112 into a uint112 by truncating after the radix point
Expand All @@ -45,17 +45,17 @@ library FixedPoint {

// multiply a UQ112x112 by a uint, returning a UQ144x112
// reverts on overflow
function mul(uq112x112 memory self, uint y) internal pure returns (uq144x112 memory) {
uint z;
require(y == 0 || (z = self._x * y) / y == self._x, "FixedPoint: MUL_OVERFLOW");
function mul(uq112x112 memory self, uint256 y) internal pure returns (uq144x112 memory) {
uint256 z;
require(y == 0 || (z = self._x * y) / y == self._x, 'FixedPoint: MUL_OVERFLOW');
return uq144x112(z);
}

// multiply a UQ112x112 by an int and decode, returning an int
// reverts on overflow
function muli(uq112x112 memory self, int y) internal pure returns (int) {
uint144 z = decode144(mul(self, uint(y < 0 ? -y : y)));
return y < 0 ? -int(z) : z;
function muli(uq112x112 memory self, int256 y) internal pure returns (int256) {
uint144 z = decode144(mul(self, uint256(y < 0 ? -y : y)));
return y < 0 ? -int256(z) : z;
}

// multiply a UQ112x112 by a UQ112x112, returning a UQ112x112
Expand All @@ -80,13 +80,13 @@ library FixedPoint {
uint224 uppero_lowers = uint224(upper_other) * lower_self; // * 2^-112

// so the bit shift does not overflow
require(upper <= uint112(-1), "FixedPoint: MULUQ_OVERFLOW_UPPER");
require(upper <= uint112(-1), 'FixedPoint: MULUQ_OVERFLOW_UPPER');

// this cannot exceed 256 bits, all values are 224 bits
uint sum = uint(upper << RESOLUTION) + uppers_lowero + uppero_lowers + (lower >> RESOLUTION);
uint256 sum = uint256(upper << RESOLUTION) + uppers_lowero + uppero_lowers + (lower >> RESOLUTION);

// so the cast does not overflow
require(sum <= uint224(-1), "FixedPoint: MULUQ_OVERFLOW_SUM");
require(sum <= uint224(-1), 'FixedPoint: MULUQ_OVERFLOW_SUM');

return uq112x112(uint224(sum));
}
Expand All @@ -98,7 +98,7 @@ library FixedPoint {
pure
returns (FixedPoint.uq112x112 memory)
{
require(other._x > 0, "FixedPoint: DIV_BY_ZERO_DIVUQ");
require(other._x > 0, 'FixedPoint: DIV_BY_ZERO_DIVUQ');
if (self._x == other._x) {
return uq112x112(uint224(Q112));
}
Expand All @@ -108,7 +108,7 @@ library FixedPoint {
// returns a UQ112x112 which represents the ratio of the numerator to the denominator
// lossy
function fraction(uint112 numerator, uint112 denominator) internal pure returns (uq112x112 memory) {
require(denominator > 0, "FixedPoint: DIV_BY_ZERO_FRACTION");
require(denominator > 0, 'FixedPoint: DIV_BY_ZERO_FRACTION');
return uq112x112((uint224(numerator) << RESOLUTION) / denominator);
}

Expand All @@ -123,6 +123,6 @@ library FixedPoint {
// square root of a UQ112x112
// lossy to 40 bits
function sqrt(uq112x112 memory self) internal pure returns (uq112x112 memory) {
return uq112x112(uint224(Babylonian.sqrt(uint(self._x) << 32) << 40));
return uq112x112(uint224(Babylonian.sqrt(uint256(self._x) << 32) << 40));
}
}
51 changes: 31 additions & 20 deletions contracts/libraries/PairNamer.sol
Original file line number Diff line number Diff line change
Expand Up @@ -10,28 +10,39 @@ library PairNamer {
string private constant TOKEN_SEPARATOR = ':';

// produces a pair descriptor in the format of `${prefix}${name0}:${name1}${suffix}`
function pairName(address token0, address token1, string memory prefix, string memory suffix) internal view returns (string memory) {
return string(
abi.encodePacked(
prefix,
SafeERC20Namer.tokenName(token0),
TOKEN_SEPARATOR,
SafeERC20Namer.tokenName(token1),
suffix
)
);
function pairName(
address token0,
address token1,
string memory prefix,
string memory suffix
) internal view returns (string memory) {
return
string(
abi.encodePacked(
prefix,
SafeERC20Namer.tokenName(token0),
TOKEN_SEPARATOR,
SafeERC20Namer.tokenName(token1),
suffix
)
);
}

// produces a pair symbol in the format of `🦄${symbol0}:${symbol1}${suffix}`
function pairSymbol(address token0, address token1, string memory suffix) internal view returns (string memory) {
return string(
abi.encodePacked(
TOKEN_SYMBOL_PREFIX,
SafeERC20Namer.tokenSymbol(token0),
TOKEN_SEPARATOR,
SafeERC20Namer.tokenSymbol(token1),
suffix
)
);
function pairSymbol(
address token0,
address token1,
string memory suffix
) internal view returns (string memory) {
return
string(
abi.encodePacked(
TOKEN_SYMBOL_PREFIX,
SafeERC20Namer.tokenSymbol(token0),
TOKEN_SEPARATOR,
SafeERC20Namer.tokenSymbol(token1),
suffix
)
);
}
}
28 changes: 14 additions & 14 deletions contracts/libraries/SafeERC20Namer.sol
Original file line number Diff line number Diff line change
Expand Up @@ -7,34 +7,34 @@ import './AddressStringUtil.sol';
// produces token descriptors from inconsistent or absent ERC20 symbol implementations that can return string or bytes32
// this library will always produce a string symbol to represent the token
library SafeERC20Namer {
function bytes32ToString(bytes32 x) pure private returns (string memory) {
function bytes32ToString(bytes32 x) private pure returns (string memory) {
bytes memory bytesString = new bytes(32);
uint charCount = 0;
for (uint j = 0; j < 32; j++) {
byte char = x[j];
uint256 charCount = 0;
for (uint256 j = 0; j < 32; j++) {
bytes1 char = x[j];
if (char != 0) {
bytesString[charCount] = char;
charCount++;
}
}
bytes memory bytesStringTrimmed = new bytes(charCount);
for (uint j = 0; j < charCount; j++) {
for (uint256 j = 0; j < charCount; j++) {
bytesStringTrimmed[j] = bytesString[j];
}
return string(bytesStringTrimmed);
}

// assumes the data is in position 2
function parseStringData(bytes memory b) pure private returns (string memory) {
uint charCount = 0;
function parseStringData(bytes memory b) private pure returns (string memory) {
uint256 charCount = 0;
// first parse the charCount out of the data
for (uint i = 32; i < 64; i++) {
for (uint256 i = 32; i < 64; i++) {
charCount <<= 8;
charCount += uint8(b[i]);
}

bytes memory bytesStringTrimmed = new bytes(charCount);
for (uint i = 0; i < charCount; i++) {
for (uint256 i = 0; i < charCount; i++) {
bytesStringTrimmed[i] = b[i + 64];
}

Expand All @@ -43,22 +43,22 @@ library SafeERC20Namer {

// uses a heuristic to produce a token name from the address
// the heuristic returns the full hex of the address string in upper case
function addressToName(address token) pure private returns (string memory) {
function addressToName(address token) private pure returns (string memory) {
return AddressStringUtil.toAsciiString(token, 40);
}

// uses a heuristic to produce a token symbol from the address
// the heuristic returns the first 6 hex of the address string in upper case
function addressToSymbol(address token) pure private returns (string memory) {
function addressToSymbol(address token) private pure returns (string memory) {
return AddressStringUtil.toAsciiString(token, 6);
}

// calls an external view token contract method that returns a symbol or name, and parses the output into a string
function callAndParseStringReturn(address token, bytes4 selector) view private returns (string memory) {
function callAndParseStringReturn(address token, bytes4 selector) private view returns (string memory) {
(bool success, bytes memory data) = token.staticcall(abi.encodeWithSelector(selector));
// if not implemented, or returns empty data, return empty string
if (!success || data.length == 0) {
return "";
return '';
}
// bytes32 data always has length 32
if (data.length == 32) {
Expand All @@ -67,7 +67,7 @@ library SafeERC20Namer {
} else if (data.length > 64) {
return abi.decode(data, (string));
}
return "";
return '';
}

// attempts to extract the token symbol. if it does not implement symbol, returns a symbol derived from the address
Expand Down
Loading

0 comments on commit 6ddfedd

Please sign in to comment.