Skip to content

Commit def6c99

Browse files
authored
Added scale function (#77)
* Added clampArr functions and tests * Added scale function * Fixed PR comments
1 parent b59c104 commit def6c99

2 files changed

Lines changed: 70 additions & 0 deletions

File tree

src/helpers/HelperMath.sol

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ pragma solidity ^0.8.0;
66
* @author Perimeter <info@perimetersec.io>
77
*/
88
abstract contract HelperMath {
9+
error ExceedMaxValue();
10+
911
/**
1012
* @dev Returns the smallest of two unsigned numbers.
1113
*/
@@ -55,4 +57,16 @@ abstract contract HelperMath {
5557
function diff(uint256 a, uint256 b) public pure returns (uint256) {
5658
return a >= b ? a - b : b - a;
5759
}
60+
61+
/**
62+
* @dev Scales an amount by the given number of decimals.
63+
* @param amount The amount to scale
64+
* @param decimals The number of decimals to scale by. Note: Max value is 77 to prevent overflow.
65+
*/
66+
function scaleDec(uint256 amount, uint256 decimals) public pure returns (uint256) {
67+
if (decimals > 77) {
68+
revert ExceedMaxValue();
69+
}
70+
return amount * (10 ** decimals);
71+
}
5872
}

test/HelperMath.t.sol

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -332,6 +332,62 @@ contract TestHelperMath is Test, HelperMath {
332332
}
333333
}
334334

335+
/**
336+
* Tests for scaleDec(uint256, uint256)
337+
*/
338+
function test_scaleDec_basic() public {
339+
assertEq(scaleDec(1, 18), 1e18);
340+
assertEq(scaleDec(5, 6), 5_000_000);
341+
assertEq(scaleDec(100, 2), 10_000);
342+
}
343+
344+
function test_scaleDec_zero_amount() public {
345+
assertEq(scaleDec(0, 18), 0);
346+
assertEq(scaleDec(0, 0), 0);
347+
assertEq(scaleDec(0, 77), 0);
348+
}
349+
350+
function test_scaleDec_zero_decimals() public {
351+
assertEq(scaleDec(42, 0), 42);
352+
assertEq(scaleDec(1000, 0), 1000);
353+
assertEq(scaleDec(type(uint256).max, 0), type(uint256).max);
354+
}
355+
356+
function test_scaleDec_common_decimals() public {
357+
assertEq(scaleDec(1, 6), 1_000_000);
358+
assertEq(scaleDec(1, 8), 100_000_000);
359+
assertEq(scaleDec(1, 18), 1_000_000_000_000_000_000);
360+
}
361+
362+
function test_scaleDec_large_decimals() public {
363+
assertEq(scaleDec(1, 27), 1e27);
364+
assertEq(scaleDec(2, 30), 2e30);
365+
}
366+
367+
function test_scaleDec_overflow() public {
368+
// Overflow from multiplication when amount is large
369+
vm.expectRevert(stdError.arithmeticError);
370+
this.scaleDec(type(uint256).max, 1);
371+
372+
// Just below overflow threshold should succeed
373+
uint256 maxSafeAmount = type(uint256).max / 10;
374+
assertEq(scaleDec(maxSafeAmount, 1), maxSafeAmount * 10);
375+
376+
// Just above overflow threshold should revert
377+
vm.expectRevert(stdError.arithmeticError);
378+
this.scaleDec(maxSafeAmount + 1, 1);
379+
380+
// Maximum valid decimals value (10**77 is the largest power of 10 that fits in uint256)
381+
assertEq(scaleDec(1, 77), 1e77);
382+
383+
// Decimals > 77 should revert with custom error
384+
vm.expectRevert(HelperMath.ExceedMaxValue.selector);
385+
this.scaleDec(1, 78);
386+
387+
vm.expectRevert(HelperMath.ExceedMaxValue.selector);
388+
this.scaleDec(1, 100);
389+
}
390+
335391
/**
336392
* Edge case tests
337393
*/

0 commit comments

Comments
 (0)