-
Notifications
You must be signed in to change notification settings - Fork 43
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
aab6b9b
commit fa65e86
Showing
5 changed files
with
320 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
33 changes: 33 additions & 0 deletions
33
packages/contracts/src/test/utils/VersionComparisonLibTest.sol
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
// SPDX-License-Identifier: AGPL-3.0-or-later | ||
|
||
pragma solidity 0.8.17; | ||
|
||
import {VersionComparisonLib} from "../../utils/protocol/VersionComparisonLib.sol"; | ||
|
||
contract VersionComparisonLibTest { | ||
using VersionComparisonLib for uint8[3]; | ||
|
||
function eq(uint8[3] memory lhs, uint8[3] memory rhs) public pure returns (bool) { | ||
return lhs.eq(rhs); | ||
} | ||
|
||
function neq(uint8[3] memory lhs, uint8[3] memory rhs) public pure returns (bool) { | ||
return lhs.neq(rhs); | ||
} | ||
|
||
function lt(uint8[3] memory lhs, uint8[3] memory rhs) public pure returns (bool) { | ||
return lhs.lt(rhs); | ||
} | ||
|
||
function lte(uint8[3] memory lhs, uint8[3] memory rhs) public pure returns (bool) { | ||
return lhs.lte(rhs); | ||
} | ||
|
||
function gt(uint8[3] memory lhs, uint8[3] memory rhs) public pure returns (bool) { | ||
return lhs.gt(rhs); | ||
} | ||
|
||
function gte(uint8[3] memory lhs, uint8[3] memory rhs) public pure returns (bool) { | ||
return lhs.gte(rhs); | ||
} | ||
} |
97 changes: 97 additions & 0 deletions
97
packages/contracts/src/utils/protocol/VersionComparisonLib.sol
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,97 @@ | ||
// SPDX-License-Identifier: AGPL-3.0-or-later | ||
|
||
pragma solidity ^0.8.8; | ||
|
||
library VersionComparisonLib { | ||
/// @notice Equality comparator for two semantic version numbers. | ||
/// @param lhs The left-hand side semantic version number. | ||
/// @param lhs The right-hand side semantic version number. | ||
/// @return Whether the two numbers are equal or not. | ||
function eq(uint8[3] memory lhs, uint8[3] memory rhs) internal pure returns (bool) { | ||
if (lhs[0] != rhs[0]) return false; | ||
|
||
if (lhs[1] != rhs[1]) return false; | ||
|
||
if (lhs[2] != rhs[2]) return false; | ||
|
||
return true; | ||
} | ||
|
||
/// @notice Inequality comparator for two semantic version numbers. | ||
/// @param lhs The left-hand side semantic version number. | ||
/// @param lhs The right-hand side semantic version number. | ||
/// @return Whether the two numbers are inequal or not. | ||
function neq(uint8[3] memory lhs, uint8[3] memory rhs) internal pure returns (bool) { | ||
if (lhs[0] != rhs[0]) return true; | ||
|
||
if (lhs[1] != rhs[1]) return true; | ||
|
||
if (lhs[2] != rhs[2]) return true; | ||
|
||
return false; | ||
} | ||
|
||
/// @notice Less than comparator for two semantic version numbers. | ||
/// @param lhs The left-hand side semantic version number. | ||
/// @param lhs The right-hand side semantic version number. | ||
/// @return Whether the first number is less than the second number or not. | ||
function lt(uint8[3] memory lhs, uint8[3] memory rhs) internal pure returns (bool) { | ||
if (lhs[0] < rhs[0]) return true; | ||
if (lhs[0] > rhs[0]) return false; | ||
|
||
if (lhs[1] < rhs[1]) return true; | ||
if (lhs[1] > rhs[1]) return false; | ||
|
||
if (lhs[2] < rhs[2]) return true; | ||
|
||
return false; | ||
} | ||
|
||
/// @notice Less than or equal to comparator for two semantic version numbers. | ||
/// @param lhs The left-hand side semantic version number. | ||
/// @param lhs The right-hand side semantic version number. | ||
/// @return Whether the first number is less than or equal to the second number or not. | ||
function lte(uint8[3] memory lhs, uint8[3] memory rhs) internal pure returns (bool) { | ||
if (lhs[0] < rhs[0]) return true; | ||
if (lhs[0] > rhs[0]) return false; | ||
|
||
if (lhs[1] < rhs[1]) return true; | ||
if (lhs[1] > rhs[1]) return false; | ||
|
||
if (lhs[2] <= rhs[2]) return true; | ||
|
||
return false; | ||
} | ||
|
||
/// @notice Greater than comparator for two semantic version numbers. | ||
/// @param lhs The left-hand side semantic version number. | ||
/// @param lhs The right-hand side semantic version number. | ||
/// @return Whether the first number is greater than the second number or not. | ||
function gt(uint8[3] memory lhs, uint8[3] memory rhs) internal pure returns (bool) { | ||
if (lhs[0] > rhs[0]) return true; | ||
if (lhs[0] < rhs[0]) return false; | ||
|
||
if (lhs[1] > rhs[1]) return true; | ||
if (lhs[1] < rhs[1]) return false; | ||
|
||
if (lhs[2] > rhs[2]) return true; | ||
|
||
return false; | ||
} | ||
|
||
/// @notice Greater than or equal to comparator for two semantic version numbers. | ||
/// @param lhs The left-hand side semantic version number. | ||
/// @param lhs The right-hand side semantic version number. | ||
/// @return Whether the first number is greater than or equal to the second number or not. | ||
function gte(uint8[3] memory lhs, uint8[3] memory rhs) internal pure returns (bool) { | ||
if (lhs[0] > rhs[0]) return true; | ||
if (lhs[0] < rhs[0]) return false; | ||
|
||
if (lhs[1] > rhs[1]) return true; | ||
if (lhs[1] < rhs[1]) return false; | ||
|
||
if (lhs[2] >= rhs[2]) return true; | ||
|
||
return false; | ||
} | ||
} |
185 changes: 185 additions & 0 deletions
185
packages/contracts/test/utils/version-comparison-lib.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,185 @@ | ||
import {expect} from 'chai'; | ||
import {ethers} from 'hardhat'; | ||
|
||
import { | ||
VersionComparisonLibTest, | ||
VersionComparisonLibTest__factory, | ||
} from '../../typechain'; | ||
|
||
type SemVer = [number, number, number]; | ||
|
||
async function lhsEqRhs( | ||
func: (lhs: SemVer, rhs: SemVer) => Promise<boolean>, | ||
expected: boolean | ||
) { | ||
const results: boolean[] = await Promise.all([ | ||
func([1, 1, 1], [1, 1, 1]), | ||
// | ||
func([0, 1, 1], [0, 1, 1]), | ||
func([1, 0, 1], [1, 0, 1]), | ||
func([1, 1, 0], [1, 1, 0]), | ||
// | ||
func([1, 0, 0], [1, 0, 0]), | ||
func([0, 1, 0], [0, 1, 0]), | ||
func([0, 0, 1], [0, 0, 1]), | ||
// | ||
func([0, 0, 0], [0, 0, 0]), | ||
]); | ||
|
||
// Check that all results match the expected value | ||
expect(results.every(v => v === expected)).to.be.true; | ||
} | ||
|
||
async function lhsLtRhs( | ||
func: (lhs: SemVer, rhs: SemVer) => Promise<boolean>, | ||
expected: boolean | ||
) { | ||
const results: boolean[] = await Promise.all([ | ||
func([1, 1, 1], [2, 1, 1]), | ||
func([1, 1, 1], [1, 2, 1]), | ||
func([1, 1, 1], [1, 1, 2]), | ||
// | ||
func([1, 1, 1], [1, 2, 2]), | ||
func([1, 1, 1], [2, 1, 2]), | ||
func([1, 1, 1], [2, 2, 1]), | ||
// | ||
func([1, 1, 1], [2, 2, 2]), | ||
// | ||
func([1, 1, 0], [1, 2, 0]), | ||
func([1, 1, 0], [2, 1, 0]), | ||
// | ||
func([1, 1, 0], [2, 2, 0]), | ||
// | ||
func([0, 1, 1], [0, 1, 2]), | ||
func([0, 1, 1], [0, 2, 1]), | ||
// | ||
func([0, 1, 1], [0, 2, 2]), | ||
// | ||
func([1, 0, 0], [2, 0, 0]), | ||
func([0, 1, 0], [0, 2, 0]), | ||
func([0, 0, 1], [0, 0, 2]), | ||
]); | ||
|
||
// Check that all results match the expected value | ||
expect(results.every(v => v === expected)).to.be.true; | ||
} | ||
|
||
async function lhsGtRhs( | ||
func: (lhs: SemVer, rhs: SemVer) => Promise<boolean>, | ||
expected: boolean | ||
) { | ||
const results: boolean[] = await Promise.all([ | ||
func([2, 1, 1], [1, 1, 1]), | ||
func([1, 2, 1], [1, 1, 1]), | ||
func([1, 1, 2], [1, 1, 1]), | ||
// | ||
func([1, 2, 2], [1, 1, 1]), | ||
func([2, 1, 2], [1, 1, 1]), | ||
func([2, 2, 1], [1, 1, 1]), | ||
// | ||
func([2, 2, 2], [1, 1, 1]), | ||
// | ||
func([1, 2, 0], [1, 1, 0]), | ||
func([2, 1, 0], [1, 1, 0]), | ||
func([2, 2, 0], [1, 1, 0]), | ||
// | ||
func([0, 1, 2], [0, 1, 1]), | ||
func([0, 2, 1], [0, 1, 1]), | ||
func([0, 2, 2], [0, 1, 1]), | ||
// | ||
func([2, 0, 0], [1, 0, 0]), | ||
func([0, 2, 0], [0, 1, 0]), | ||
func([0, 0, 2], [0, 0, 1]), | ||
]); | ||
|
||
// Check that all results match the expected value | ||
expect(results.every(v => v === expected)).to.be.true; | ||
} | ||
|
||
describe('VersionComparisonLib', function () { | ||
let cmp: VersionComparisonLibTest; | ||
|
||
before(async () => { | ||
const signers = await ethers.getSigners(); | ||
cmp = await new VersionComparisonLibTest__factory(signers[0]).deploy(); | ||
}); | ||
|
||
describe('eq', async () => { | ||
async function eq(lhs: SemVer, rhs: SemVer): Promise<boolean> { | ||
return await cmp.eq(lhs, rhs); | ||
} | ||
|
||
it('returns true if lhs equals rhs', async () => { | ||
await lhsEqRhs(eq, true); | ||
}); | ||
|
||
it('returns false if lhs does not equal rhs', async () => { | ||
await lhsLtRhs(eq, false); | ||
await lhsGtRhs(eq, false); | ||
}); | ||
}); | ||
|
||
describe('neq', async () => { | ||
async function neq(lhs: SemVer, rhs: SemVer): Promise<boolean> { | ||
return await cmp.neq(lhs, rhs); | ||
} | ||
|
||
it('returns true if lhs does not equal rhs', async () => { | ||
await lhsLtRhs(neq, true); | ||
await lhsGtRhs(neq, true); | ||
}); | ||
it('returns false if lhs equals rhs', async () => { | ||
await lhsEqRhs(neq, false); | ||
}); | ||
}); | ||
|
||
describe('lt', async () => { | ||
async function lt(lhs: SemVer, rhs: SemVer): Promise<boolean> { | ||
return await cmp.lt(lhs, rhs); | ||
} | ||
it('returns true if lhs is less than rhs', async () => { | ||
await lhsLtRhs(lt, true); | ||
}); | ||
it('returns false if lhs is not less than rhs', async () => { | ||
await lhsGtRhs(lt, false); | ||
await lhsEqRhs(lt, false); | ||
}); | ||
}); | ||
describe('lte', async () => { | ||
async function lte(lhs: SemVer, rhs: SemVer): Promise<boolean> { | ||
return await cmp.lte(lhs, rhs); | ||
} | ||
it('returns true if lhs is less than or equal to rhs', async () => { | ||
await lhsLtRhs(lte, true); | ||
await lhsEqRhs(lte, true); | ||
}); | ||
it('returns false if lhs is not less than or equal to rhs', async () => { | ||
await lhsGtRhs(lte, false); | ||
}); | ||
}); | ||
|
||
describe('gt', async () => { | ||
async function gt(lhs: SemVer, rhs: SemVer): Promise<boolean> { | ||
return await cmp.gt(lhs, rhs); | ||
} | ||
it('returns true if lhs is greater than rhs', async () => { | ||
await lhsGtRhs(gt, true); | ||
}); | ||
it('returns false if lhs is not greater than rhs', async () => { | ||
await lhsLtRhs(gt, false); | ||
await lhsEqRhs(gt, false); | ||
}); | ||
}); | ||
describe('gte', async () => { | ||
async function gte(lhs: SemVer, rhs: SemVer): Promise<boolean> { | ||
return await cmp.gte(lhs, rhs); | ||
} | ||
it('returns true if lhs is greater than or equal to rhs', async () => { | ||
await lhsGtRhs(gte, true); | ||
await lhsEqRhs(gte, true); | ||
}); | ||
it('returns false if lhs is not greater than or equal to rhs', async () => { | ||
await lhsLtRhs(gte, false); | ||
}); | ||
}); | ||
}); |