Skip to content

Commit

Permalink
add checks if b denominator is positive in mul functions
Browse files Browse the repository at this point in the history
  • Loading branch information
zielvna committed Apr 8, 2024
1 parent b6ab198 commit e4cb9a5
Show file tree
Hide file tree
Showing 3 changed files with 69 additions and 24 deletions.
17 changes: 13 additions & 4 deletions contracts/math/uints.ral
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ Contract Uints () {
MulOverflow = 100003
DivNotPositiveDivisor = 100004
DivNotPositiveDenominator = 100005
MulNotPositiveDenominator = 100006
}

pub fn unwrapU256(result: ResultU256) -> U256 {
Expand Down Expand Up @@ -159,20 +160,28 @@ Contract Uints () {
return bigAdd512(result, U512 { higher: higher.value, lower: 0 })
}

pub fn bigMulDiv256(a: U256, b: U256, bDenominator: U256) -> U512 {
pub fn bigMulDiv256(a: U256, b: U256, bDenominator: U256) -> ResultU512 {
if(bDenominator == 0) {
return ResultU512 { value: U512 { higher: MaxU256, lower: MaxU256 }, error: ArithmeticError.MulNotPositiveDenominator }
}

let mut result = bigMul256(a, b)
result = unwrapU512(bigDiv(result, bDenominator, 1))

return result
return ResultU512 { value: result, error: 0 }
}

pub fn bigMulDivUp256(a: U256, b: U256, bDenominator: U256) -> U512 {
pub fn bigMulDivUp256(a: U256, b: U256, bDenominator: U256) -> ResultU512 {
if(bDenominator == 0) {
return ResultU512 { value: U512 { higher: MaxU256, lower: MaxU256 }, error: ArithmeticError.MulNotPositiveDenominator }
}

let mut result = bigMul256(a, b)

result = unwrapU512(bigAdd512(result, U512 { higher: 0, lower: bDenominator - 1 }))
result = unwrapU512(bigDiv(result, bDenominator, 1))

return result
return ResultU512 { value: result, error: 0 }
}

pub fn overflowingAdd(a: U256, b: U256) -> (U256, U256) {
Expand Down
3 changes: 2 additions & 1 deletion src/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -437,7 +437,8 @@ export const ArithmeticError = {
AddOverflow: 100002n,
MulOverflow: 100003n,
DivNotPositiveDivisor: 100004n,
DivNotPositiveDenominator: 100005n
DivNotPositiveDenominator: 100005n,
MulNotPositiveDenominator: 100006n
}

export const MaxU256 = 115792089237316195423570985008687907853269984665640564039457584007913129639935n
73 changes: 54 additions & 19 deletions test/uints.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -553,59 +553,75 @@ describe('uints tests', () => {
const b = 2n
const bDenominator = 1n
const result = (await uints.methods.bigMulDiv256({ args: { a, b, bDenominator } })).returns
expect(result).toStrictEqual({ higher: 0n, lower: 2n })
expect(result).toStrictEqual({ value: { higher: 0n, lower: 2n }, error: 0n })
}
{
const a = MaxU256
const b = 2n
const bDenominator = 1n
const result = (await uints.methods.bigMulDiv256({ args: { a, b, bDenominator } })).returns
expect(result).toStrictEqual({ higher: 1n, lower: MaxU256 - 1n })
expect(result).toStrictEqual({ value: { higher: 1n, lower: MaxU256 - 1n }, error: 0n })
}
{
const a = MaxU256
const b = MaxU256
const bDenominator = 1n
const result = (await uints.methods.bigMulDiv256({ args: { a, b, bDenominator } })).returns
expect(result).toStrictEqual({
higher: MaxU256 - 1n,
lower: 1n
value: {
higher: MaxU256 - 1n,
lower: 1n
},
error: 0n
})
}
{
const a = MaxU256
const b = 0n
const bDenominator = 1n
const result = (await uints.methods.bigMulDiv256({ args: { a, b, bDenominator } })).returns
expect(result).toStrictEqual({ higher: 0n, lower: 0n })
expect(result).toStrictEqual({ value: { higher: 0n, lower: 0n }, error: 0n })
}
{
const a = 0n
const b = 0n
const bDenominator = 1n
const result = (await uints.methods.bigMulDiv256({ args: { a, b, bDenominator } })).returns
expect(result).toStrictEqual({ higher: 0n, lower: 0n })
expect(result).toStrictEqual({ value: { higher: 0n, lower: 0n }, error: 0n })
}
{
const a = 100n
const b = 200n
const bDenominator = 100n
const result = (await uints.methods.bigMulDiv256({ args: { a, b, bDenominator } })).returns
expect(result).toStrictEqual({ higher: 0n, lower: 200n })
expect(result).toStrictEqual({ value: { higher: 0n, lower: 200n }, error: 0n })
}
{
const a = 1n
const b = 150n
const bDenominator = 100n
const result = (await uints.methods.bigMulDiv256({ args: { a, b, bDenominator } })).returns
expect(result).toStrictEqual({ higher: 0n, lower: 1n })
expect(result).toStrictEqual({ value: { higher: 0n, lower: 1n }, error: 0n })
}
{
const a = MaxU256
const b = MaxU256
const bDenominator = MaxU256
const result = (await uints.methods.bigMulDiv256({ args: { a, b, bDenominator } })).returns
expect(result).toStrictEqual({ higher: 0n, lower: MaxU256 - 1n })
expect(result).toStrictEqual({ value: { higher: 0n, lower: MaxU256 - 1n }, error: 0n })
}
})

test('big mul div 256 returns an error if b denominator is zero', async () => {
{
const a = 1n
const b = 1n
const bDenominator = 0n
const result = (await uints.methods.bigMulDiv256({ args: { a, b, bDenominator } })).returns
expect(result).toStrictEqual({
value: { higher: MaxU256, lower: MaxU256 },
error: ArithmeticError.MulNotPositiveDenominator
})
}
})

Expand All @@ -615,61 +631,80 @@ describe('uints tests', () => {
const b = 2n
const bDenominator = 1n
const result = (await uints.methods.bigMulDivUp256({ args: { a, b, bDenominator } })).returns
expect(result).toStrictEqual({ higher: 0n, lower: 2n })
expect(result).toStrictEqual({ value: { higher: 0n, lower: 2n }, error: 0n })
}
{
const a = MaxU256
const b = 2n
const bDenominator = 1n
const result = (await uints.methods.bigMulDivUp256({ args: { a, b, bDenominator } })).returns
expect(result).toStrictEqual({ higher: 1n, lower: MaxU256 - 1n })
expect(result).toStrictEqual({ value: { higher: 1n, lower: MaxU256 - 1n }, error: 0n })
}
{
const a = MaxU256
const b = MaxU256
const bDenominator = 1n
const result = (await uints.methods.bigMulDivUp256({ args: { a, b, bDenominator } })).returns
expect(result).toStrictEqual({
higher: MaxU256 - 1n,
lower: 1n
value: {
higher: MaxU256 - 1n,
lower: 1n
},
error: 0n
})
}
{
const a = MaxU256
const b = 0n
const bDenominator = 1n
const result = (await uints.methods.bigMulDivUp256({ args: { a, b, bDenominator } })).returns
expect(result).toStrictEqual({ higher: 0n, lower: 0n })
expect(result).toStrictEqual({ value: { higher: 0n, lower: 0n }, error: 0n })
}
{
const a = 0n
const b = 0n
const bDenominator = 1n
const result = (await uints.methods.bigMulDivUp256({ args: { a, b, bDenominator } })).returns
expect(result).toStrictEqual({ higher: 0n, lower: 0n })
expect(result).toStrictEqual({ value: { higher: 0n, lower: 0n }, error: 0n })
}
{
const a = 100n
const b = 200n
const bDenominator = 100n
const result = (await uints.methods.bigMulDivUp256({ args: { a, b, bDenominator } })).returns
expect(result).toStrictEqual({ higher: 0n, lower: 200n })
expect(result).toStrictEqual({ value: { higher: 0n, lower: 200n }, error: 0n })
}
{
const a = 1n
const b = 150n
const bDenominator = 100n
const result = (await uints.methods.bigMulDivUp256({ args: { a, b, bDenominator } })).returns
expect(result).toStrictEqual({ higher: 0n, lower: 2n })
expect(result).toStrictEqual({ value: { higher: 0n, lower: 2n }, error: 0n })
}
{
const a = MaxU256
const b = MaxU256
const bDenominator = MaxU256
const result = (await uints.methods.bigMulDivUp256({ args: { a, b, bDenominator } })).returns
expect(result).toStrictEqual({
higher: 0n,
lower: MaxU256
value: {
higher: 0n,
lower: MaxU256
},
error: 0n
})
}
})

test('big mul div up 256 returns an error if b denominator is zero', async () => {
{
const a = 1n
const b = 1n
const bDenominator = 0n
const result = (await uints.methods.bigMulDivUp256({ args: { a, b, bDenominator } })).returns
expect(result).toStrictEqual({
value: { higher: MaxU256, lower: MaxU256 },
error: ArithmeticError.MulNotPositiveDenominator
})
}
})
Expand Down

0 comments on commit e4cb9a5

Please sign in to comment.