Skip to content

Commit 100b480

Browse files
authored
Merge pull request #137 from solidstate-network/math-library
Math library updates
2 parents fac250c + 36d8d25 commit 100b480

File tree

3 files changed

+116
-14
lines changed

3 files changed

+116
-14
lines changed

contracts/utils/Math.sol

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,37 @@
33
pragma solidity ^0.8.8;
44

55
library Math {
6+
/**
7+
* @notice select the greater of two numbers
8+
* @param a first number
9+
* @param b second number
10+
* @return greater number
11+
*/
12+
function max(uint256 a, uint256 b) internal pure returns (uint256) {
13+
return a > b ? a : b;
14+
}
15+
16+
/**
17+
* @notice select the lesser of two numbers
18+
* @param a first number
19+
* @param b second number
20+
* @return lesser number
21+
*/
22+
function min(uint256 a, uint256 b) internal pure returns (uint256) {
23+
return a > b ? b : a;
24+
}
25+
626
/**
727
* @notice calculate the average of two numbers, rounded down
828
* @dev derived from https://github.com/OpenZeppelin/openzeppelin-contracts (MIT license)
929
* @param a first number
1030
* @param b second number
31+
* @return mean value
1132
*/
1233
function average(uint256 a, uint256 b) internal pure returns (uint256) {
13-
return (a >> 1) + (b >> 1) + (((a & 1) + (b & 1)) >> 1);
34+
unchecked {
35+
return (a & b) + ((a ^ b) >> 1);
36+
}
1437
}
1538

1639
/**

contracts/utils/MathMock.sol

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,16 @@ import { Math } from './Math.sol';
77
contract MathMock {
88
using Math for uint256;
99

10+
function max(uint256 a, uint256 b) external pure returns (uint256) {
11+
return Math.max(a, b);
12+
}
13+
14+
function min(uint256 a, uint256 b) external pure returns (uint256) {
15+
return Math.min(a, b);
16+
}
17+
1018
function average(uint256 a, uint256 b) external pure returns (uint256) {
11-
return a.average(b);
19+
return Math.average(a, b);
1220
}
1321

1422
function sqrt(uint256 x) external pure returns (uint256) {

test/utils/Math.ts

Lines changed: 83 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -11,56 +11,127 @@ describe('Math', function () {
1111
});
1212

1313
describe('__internal', function () {
14+
describe('#max(uint256,uint256)', function () {
15+
it('returns the greater of two numbers', async () => {
16+
expect(
17+
await instance.callStatic.max(
18+
ethers.constants.One,
19+
ethers.constants.Two,
20+
),
21+
).to.equal(ethers.constants.Two);
22+
23+
expect(
24+
await instance.callStatic.max(
25+
ethers.constants.Two,
26+
ethers.constants.One,
27+
),
28+
).to.equal(ethers.constants.Two);
29+
30+
expect(
31+
await instance.callStatic.max(
32+
ethers.constants.One,
33+
ethers.constants.One,
34+
),
35+
).to.equal(ethers.constants.One);
36+
37+
expect(
38+
await instance.callStatic.max(
39+
ethers.constants.Zero,
40+
ethers.constants.MaxUint256,
41+
),
42+
).to.equal(ethers.constants.MaxUint256);
43+
});
44+
});
45+
46+
describe('#min(uint256,uint256)', function () {
47+
it('returns the lesser of two numbers', async () => {
48+
expect(
49+
await instance.callStatic.min(
50+
ethers.constants.One,
51+
ethers.constants.Two,
52+
),
53+
).to.equal(ethers.constants.One);
54+
55+
expect(
56+
await instance.callStatic.min(
57+
ethers.constants.Two,
58+
ethers.constants.One,
59+
),
60+
).to.equal(ethers.constants.One);
61+
62+
expect(
63+
await instance.callStatic.min(
64+
ethers.constants.One,
65+
ethers.constants.One,
66+
),
67+
).to.equal(ethers.constants.One);
68+
69+
expect(
70+
await instance.callStatic.min(
71+
ethers.constants.Zero,
72+
ethers.constants.MaxUint256,
73+
),
74+
).to.equal(ethers.constants.Zero);
75+
});
76+
});
77+
1478
describe('#average(uint256,uint256)', function () {
1579
it('returns the average of two positive numbers from 0 to maxUint256', async function () {
1680
expect(
17-
await instance.average(
81+
await instance.callStatic.average(
1882
ethers.BigNumber.from('11'),
1983
ethers.BigNumber.from('5'),
2084
),
2185
).to.equal(ethers.BigNumber.from('8'));
2286

2387
expect(
24-
await instance.average(
88+
await instance.callStatic.average(
2589
ethers.BigNumber.from('6'),
2690
ethers.BigNumber.from('5'),
2791
),
2892
).to.equal(ethers.BigNumber.from('5'));
2993

3094
expect(
31-
await instance.average(
95+
await instance.callStatic.average(
3296
ethers.BigNumber.from('0'),
3397
ethers.BigNumber.from('0'),
3498
),
3599
).to.equal(ethers.BigNumber.from('0'));
36100

37101
expect(
38-
await instance.average(
102+
await instance.callStatic.average(
39103
ethers.constants.MaxUint256,
40104
ethers.constants.MaxUint256,
41105
),
42106
).to.equal(ethers.constants.MaxUint256);
107+
108+
expect(
109+
await instance.callStatic.average(
110+
ethers.constants.MaxUint256,
111+
ethers.constants.MaxUint256.sub(ethers.constants.One),
112+
),
113+
).to.equal(ethers.constants.MaxUint256.sub(ethers.constants.One));
43114
});
44115
});
45116

46117
describe('#sqrt(uint256)', function () {
47118
it('returns the sqrt of a positive integer from 0 to maxUint256', async function () {
48-
expect(await instance.sqrt(ethers.BigNumber.from('16'))).to.eq(
49-
ethers.BigNumber.from('4'),
50-
);
119+
expect(
120+
await instance.callStatic.sqrt(ethers.BigNumber.from('16')),
121+
).to.eq(ethers.BigNumber.from('4'));
51122

52123
for (let i = 10; i < 16; i++) {
53124
expect(
54-
await instance.sqrt(ethers.BigNumber.from(i.toString())),
125+
await instance.callStatic.sqrt(ethers.BigNumber.from(i.toString())),
55126
).to.eq(ethers.BigNumber.from('3'));
56127
}
57128

58-
expect(await instance.sqrt(ethers.BigNumber.from('0'))).to.eq(
59-
ethers.BigNumber.from('0'),
60-
);
129+
expect(
130+
await instance.callStatic.sqrt(ethers.BigNumber.from('0')),
131+
).to.eq(ethers.BigNumber.from('0'));
61132

62133
expect(
63-
await instance.sqrt(
134+
await instance.callStatic.sqrt(
64135
ethers.constants.MaxUint256.sub(ethers.BigNumber.from('1')),
65136
),
66137
).to.eq(

0 commit comments

Comments
 (0)