diff --git a/packages/big/uint256/uint256.gno b/packages/big/uint256/uint256.gno index 32359cf9..d78ac6aa 100644 --- a/packages/big/uint256/uint256.gno +++ b/packages/big/uint256/uint256.gno @@ -958,7 +958,7 @@ func (z *Uint) fromDecimal(bs string) error { z.SetUint64(num) } else { base := NewUint(num) - z.UnsafeAdd(z, base.Mul(base, mult)) + z.Add(z, base.Mul(base, mult)) } // Chop off another 19 characters if remaining > 19 { diff --git a/pool/_RPC_dry.gno b/pool/_RPC_dry.gno index d11c0433..c393a6f6 100644 --- a/pool/_RPC_dry.gno +++ b/pool/_RPC_dry.gno @@ -95,13 +95,9 @@ func DrySwap( liquidity: cache.liquidityStart, } } - // println("state.tick:", state.tick) - // println("IN state.sqrtPriceX96:", state.sqrtPriceX96.ToString()) - // println("state.sqrtPriceX96:", state.sqrtPriceX96.ToString()) // continue swapping as long as we haven't used the entire input/output and haven't reached the price limit for !(state.amountSpecifiedRemaining.IsZero()) && !(state.sqrtPriceX96.Eq(sqrtPriceLimitX96)) { - // println("state.amountSpecifiedRemaining:", state.amountSpecifiedRemaining.ToString()) var step StepComputations step.sqrtPriceStartX96 = state.sqrtPriceX96 @@ -131,11 +127,6 @@ func DrySwap( sqrtRatioTargetX96 = step.sqrtPriceNextX96 } - // println("state.sqrtPriceX96:", state.sqrtPriceX96.ToString()) - // println("sqrtRatioTargetX96:", sqrtRatioTargetX96.ToString()) - // println("state.liquidity:", state.liquidity.ToString()) - // println("state.amountSpecifiedRemaining:", state.amountSpecifiedRemaining.ToString()) - // println("pool.fee:", pool.fee) state.sqrtPriceX96, step.amountIn, step.amountOut, step.feeAmount = swapMathComputeSwapStep( state.sqrtPriceX96, sqrtRatioTargetX96, @@ -143,13 +134,6 @@ func DrySwap( state.amountSpecifiedRemaining, uint64(pool.fee), ) - if step.amountIn.ToString() == "271" { - // println("> state.sqrtPriceX96:", state.sqrtPriceX96.ToString()) - // println("step.amountIn:", step.amountIn.ToString()) - // println("step.amountOut:", step.amountOut.ToString()) - // println("step.feeAmount:", step.feeAmount.ToString()) - // panic("FIX") - } amountInWithFee := i256.FromUint256(new(u256.Uint).Add(step.amountIn, step.feeAmount)) if exactInput { diff --git a/pool/_TEST_pool_dryswap_and_swap_test.gno b/pool/_TEST_pool_dryswap_and_swap_test.gnoa similarity index 98% rename from pool/_TEST_pool_dryswap_and_swap_test.gno rename to pool/_TEST_pool_dryswap_and_swap_test.gnoa index 12d9c94f..7aaaf5ed 100644 --- a/pool/_TEST_pool_dryswap_and_swap_test.gno +++ b/pool/_TEST_pool_dryswap_and_swap_test.gnoa @@ -87,7 +87,7 @@ func TestDrySwap_ZeroForOneTrue_AmountSpecified_Negative_16000(t *testing.T) { consts.MIN_PRICE, // sqrtPriceLimitX96 ) - shouldEQ(t, poolIn, "43512") + shouldEQ(t, poolIn, "43512") // r3v4_xxx: ROUNDING ERROR shouldEQ(t, poolOut, "-16000") } diff --git a/pool/_TEST_pool_multi_token_test.gno_OK b/pool/_TEST_pool_multi_token_test.gno_OK deleted file mode 100644 index e69de29b..00000000 diff --git a/pool/_TEST_pool_native_swap_test.gn_OK b/pool/_TEST_pool_native_swap_test.gnoa similarity index 100% rename from pool/_TEST_pool_native_swap_test.gn_OK rename to pool/_TEST_pool_native_swap_test.gnoa diff --git a/pool/_TEST_pool_single_lp_test.gno_OK b/pool/_TEST_pool_single_lp_test.gno_OK deleted file mode 100644 index 10ba3639..00000000 --- a/pool/_TEST_pool_single_lp_test.gno_OK +++ /dev/null @@ -1,471 +0,0 @@ -package pool - -import ( -<<<<<<<< HEAD:pool/_TEST_pool_single_lp_test.gno_OK - "std" - "testing" - -======== ->>>>>>>> 486effd (feat: uint256, int256 instead of bigint):pool/_TEST_pool_single_lp_test.gno - "encoding/gjson" - "std" - "strconv" - "testing" - - "gno.land/r/demo/consts" - -<<<<<<<< HEAD:pool/_TEST_pool_single_lp_test.gno_OK - "gno.land/p/demo/u256" -======== - u256 "gno.land/p/big/uint256" ->>>>>>>> 486effd (feat: uint256, int256 instead of bigint):pool/_TEST_pool_single_lp_test.gno -) - -var ( - test_tickLower = int32(9000) - test_tickUpper = int32(11000) - test_liquidityExpectStr = "1000" - test_liquidityExpect256 = u256.NewUint(1000) - - test_tickLower2 = int32(50000) - test_tickUpper2 = int32(100000) -) - -// 1. Init & Create Pool using Factory Contract by Gnoswap Admin -func TestInitCreatePool(t *testing.T) { - std.TestSetOrigCaller(test1) - InitManual() - -<<<<<<<< HEAD:pool/_TEST_pool_single_lp_test.gno_OK - std.TestSetOrigCaller(test1) - CreatePool(barPath, fooPath, fee500, 130621891405341611593710811006) - - // sqrtPrice - // 130621891405341611593710811006 // tick = 10000 - shouldPanic(t, func() { CreatePool(barPath, fooPath, 500, 130621891405341611593710811006) }) -======== - std.TestSetPrevAddr(test1) - gns.Approve(a2u(consts.POOL_ADDR), consts.POOL_CREATION_FEE) - CreatePool(barPath, fooPath, fee500, "130621891405341611593710811006") // x2.7 ->>>>>>>> 486effd (feat: uint256, int256 instead of bigint):pool/_TEST_pool_single_lp_test.gno -} - -// 2. Mint by test1 -func TestMint(t *testing.T) { -<<<<<<<< HEAD:pool/_TEST_pool_single_lp_test.gno_OK -======== - std.TestSetPrevAddr(test1) - - bar.Approve(a2u(consts.POOL_ADDR), consts.UINT64_MAX) - foo.Approve(a2u(consts.POOL_ADDR), consts.UINT64_MAX) - ->>>>>>>> 486effd (feat: uint256, int256 instead of bigint):pool/_TEST_pool_single_lp_test.gno - std.TestSetPrevRealm(consts.POSITION_PATH) - std.TestSetOrigCaller(test1) - - Mint( - fooPath, - barPath, - fee500, - consts.POSITION_ADDR, - test_tickLower, - test_tickUpper, - test_liquidityExpectStr, - ) -<<<<<<<< HEAD:pool/_TEST_pool_single_lp_test.gno_OK - - pool := GetPool(barPath, fooPath, fee500) - test_liquidity := pool.PoolGetLiquidity() - shouldEQ(t, test_liquidity.Eq(u256.FromBigint(test_liquidityExpect)), true) -======== - shouldEQ(t, amount0, "29") - shouldEQ(t, amount1, "80") - - pool := GetPool(barPath, fooPath, fee500) - test_liquidity := pool.PoolGetLiquidity() - shouldEQ(t, test_liquidity.Dec(), test_liquidityExpectStr) ->>>>>>>> 486effd (feat: uint256, int256 instead of bigint):pool/_TEST_pool_single_lp_test.gno - - Mint(barPath, fooPath, fee500, consts.POSITION_ADDR, test_tickLower, test_tickUpper, test_liquidityExpectStr) - Mint(barPath, fooPath, fee500, consts.POSITION_ADDR, test_tickLower, test_tickUpper, test_liquidityExpectStr) - Mint(barPath, fooPath, fee500, consts.POSITION_ADDR, test_tickLower, test_tickUpper, test_liquidityExpectStr) - Mint(barPath, fooPath, fee500, consts.POSITION_ADDR, test_tickLower, test_tickUpper, test_liquidityExpectStr) - Mint(barPath, fooPath, fee500, consts.POSITION_ADDR, test_tickLower, test_tickUpper, test_liquidityExpectStr) - Mint(barPath, fooPath, fee500, consts.POSITION_ADDR, test_tickLower, test_tickUpper, test_liquidityExpectStr) - - m81, m82 := Mint(barPath, fooPath, fee500, consts.POSITION_ADDR, test_tickLower, test_tickUpper, test_liquidityExpectStr) - Mint(barPath, fooPath, fee500, consts.POSITION_ADDR, test_tickLower, test_tickUpper, test_liquidityExpectStr) - m101, m102 := Mint(barPath, fooPath, fee500, consts.POSITION_ADDR, test_tickLower, test_tickUpper, test_liquidityExpectStr) - - shouldNEQ(t, m81, "0") - shouldNEQ(t, m82, "0") - shouldEQ(t, m81, m101) - shouldEQ(t, m82, m102) - - test_liquidity = pool.PoolGetLiquidity() -<<<<<<<< HEAD:pool/_TEST_pool_single_lp_test.gno_OK - shouldEQ(t, test_liquidity.Eq(u256.FromBigint(test_liquidityExpect*10)), true) -======== - shouldEQ(t, true, test_liquidity.Eq(new(u256.Uint).Mul(test_liquidityExpect256, u256.NewUint(10)))) ->>>>>>>> 486effd (feat: uint256, int256 instead of bigint):pool/_TEST_pool_single_lp_test.gno - - // tickLower > currentTick == don't add to current liquidity - Mint(barPath, fooPath, fee500, consts.POSITION_ADDR, test_tickLower2, test_tickUpper2, test_liquidityExpectStr) - - // tickUpper < current tick == don't add to current liquidity - Mint(barPath, fooPath, fee500, consts.POSITION_ADDR, -test_tickUpper2, -test_tickLower2, test_liquidityExpectStr) - - // tickUpper < tickLower == don't add to current liquidity - Mint(barPath, fooPath, fee500, consts.POSITION_ADDR, -test_tickUpper, -test_tickLower, test_liquidityExpectStr) - - // test_liquidity = pool.PoolGetLiquidity() - shouldEQ(t, true, test_liquidity.Eq(new(u256.Uint).Mul(test_liquidityExpect256, u256.NewUint(10)))) - - Mint(barPath, fooPath, fee500, consts.POSITION_ADDR, test_tickLower, test_tickUpper, test_liquidityExpectStr) - Mint(barPath, fooPath, fee500, consts.POSITION_ADDR, test_tickLower, test_tickUpper, test_liquidityExpectStr) - Mint(barPath, fooPath, fee500, consts.POSITION_ADDR, test_tickLower, test_tickUpper, test_liquidityExpectStr) - Mint(barPath, fooPath, fee500, consts.POSITION_ADDR, test_tickLower, test_tickUpper, test_liquidityExpectStr) - Mint(barPath, fooPath, fee500, consts.POSITION_ADDR, test_tickLower, test_tickUpper, test_liquidityExpectStr) - Mint(barPath, fooPath, fee500, consts.POSITION_ADDR, test_tickLower, test_tickUpper, test_liquidityExpectStr) - Mint(barPath, fooPath, fee500, consts.POSITION_ADDR, test_tickLower, test_tickUpper, test_liquidityExpectStr) - Mint(barPath, fooPath, fee500, consts.POSITION_ADDR, test_tickLower, test_tickUpper, test_liquidityExpectStr) - Mint(barPath, fooPath, fee500, consts.POSITION_ADDR, test_tickLower, test_tickUpper, test_liquidityExpectStr) - Mint(barPath, fooPath, fee500, consts.POSITION_ADDR, test_tickLower, test_tickUpper, test_liquidityExpectStr) - - test_liquidity = pool.PoolGetLiquidity() -<<<<<<<< HEAD:pool/_TEST_pool_single_lp_test.gno_OK - shouldEQ(t, test_liquidity.Eq(u256.FromBigint(test_liquidityExpect*10)), true) - - Mint(barPath, fooPath, fee500, consts.POSITION_ADDR, test_tickLower, test_tickUpper, test_liquidityExpect) - Mint(barPath, fooPath, fee500, consts.POSITION_ADDR, test_tickLower, test_tickUpper, test_liquidityExpect) - Mint(barPath, fooPath, fee500, consts.POSITION_ADDR, test_tickLower, test_tickUpper, test_liquidityExpect) - Mint(barPath, fooPath, fee500, consts.POSITION_ADDR, test_tickLower, test_tickUpper, test_liquidityExpect) - Mint(barPath, fooPath, fee500, consts.POSITION_ADDR, test_tickLower, test_tickUpper, test_liquidityExpect) - Mint(barPath, fooPath, fee500, consts.POSITION_ADDR, test_tickLower, test_tickUpper, test_liquidityExpect) - Mint(barPath, fooPath, fee500, consts.POSITION_ADDR, test_tickLower, test_tickUpper, test_liquidityExpect) - Mint(barPath, fooPath, fee500, consts.POSITION_ADDR, test_tickLower, test_tickUpper, test_liquidityExpect) - Mint(barPath, fooPath, fee500, consts.POSITION_ADDR, test_tickLower, test_tickUpper, test_liquidityExpect) - Mint(barPath, fooPath, fee500, consts.POSITION_ADDR, test_tickLower, test_tickUpper, test_liquidityExpect) - - test_liquidity = pool.PoolGetLiquidity() - shouldEQ(t, test_liquidity.Eq(u256.FromBigint(test_liquidityExpect*20)), true) -======== - shouldEQ(t, true, test_liquidity.Eq(new(u256.Uint).Mul(test_liquidityExpect256, u256.NewUint(20)))) - ->>>>>>>> 486effd (feat: uint256, int256 instead of bigint):pool/_TEST_pool_single_lp_test.gno -} - -// 3. Burn by test1 -func TestBurn(t *testing.T) { - std.TestSetPrevRealm(consts.POSITION_PATH) - std.TestSetOrigCaller(test1) - - b11, b12 := Burn(barPath, fooPath, fee500, test_tickLower, test_tickUpper, test_liquidityExpectStr) - b21, b22 := Burn(barPath, fooPath, fee500, test_tickLower, test_tickUpper, test_liquidityExpectStr) - shouldEQ(t, b11, b21) - shouldEQ(t, b12, b22) - - pool := GetPool(barPath, fooPath, fee500) - test_liquidity := pool.PoolGetLiquidity() -<<<<<<<< HEAD:pool/_TEST_pool_single_lp_test.gno_OK - shouldEQ(t, test_liquidity.Eq(u256.FromBigint(test_liquidityExpect*18)), true) -======== - shouldEQ(t, true, test_liquidity.Eq(new(u256.Uint).Mul(test_liquidityExpect256, u256.NewUint(18)))) ->>>>>>>> 486effd (feat: uint256, int256 instead of bigint):pool/_TEST_pool_single_lp_test.gno - - Burn(barPath, fooPath, fee500, test_tickLower, test_tickUpper, new(u256.Uint).Mul(test_liquidityExpect256, u256.NewUint(8)).ToString()) - test_liquidity = pool.PoolGetLiquidity() -<<<<<<<< HEAD:pool/_TEST_pool_single_lp_test.gno_OK - shouldEQ(t, test_liquidity.Eq(u256.FromBigint(test_liquidityExpect*10)), true) -======== - shouldEQ(t, true, test_liquidity.Eq(new(u256.Uint).Mul(test_liquidityExpect256, u256.NewUint(10)))) ->>>>>>>> 486effd (feat: uint256, int256 instead of bigint):pool/_TEST_pool_single_lp_test.gno - - Burn(barPath, fooPath, fee500, test_tickLower, test_tickUpper, "1") - test_liquidity = pool.PoolGetLiquidity() -<<<<<<<< HEAD:pool/_TEST_pool_single_lp_test.gno_OK - shouldEQ(t, test_liquidity.Eq(u256.FromBigint(9999)), true) -======== - shouldEQ(t, test_liquidity.ToString(), "9999") ->>>>>>>> 486effd (feat: uint256, int256 instead of bigint):pool/_TEST_pool_single_lp_test.gno - - Burn(barPath, fooPath, fee500, test_tickLower, test_tickUpper, "999") - test_liquidity = pool.PoolGetLiquidity() -<<<<<<<< HEAD:pool/_TEST_pool_single_lp_test.gno_OK - shouldEQ(t, test_liquidity.Eq(u256.FromBigint(test_liquidityExpect*9)), true) -======== - shouldEQ(t, true, test_liquidity.Eq(new(u256.Uint).Mul(test_liquidityExpect256, u256.NewUint(9)))) ->>>>>>>> 486effd (feat: uint256, int256 instead of bigint):pool/_TEST_pool_single_lp_test.gno - - Burn(barPath, fooPath, fee500, test_tickLower, test_tickUpper, new(u256.Uint).Mul(test_liquidityExpect256, u256.NewUint(9)).ToString()) - test_liquidity = pool.PoolGetLiquidity() -<<<<<<<< HEAD:pool/_TEST_pool_single_lp_test.gno_OK - shouldEQ(t, test_liquidity.IsZero(), true) -======== - shouldEQ(t, test_liquidity.ToString(), "0") ->>>>>>>> 486effd (feat: uint256, int256 instead of bigint):pool/_TEST_pool_single_lp_test.gno -} - -// 4. Collect -func TestCollect(t *testing.T) { - std.TestSetPrevRealm(consts.POSITION_PATH) - std.TestSetOrigCaller(test1) - - // withdraw all token before test `Collect` - Collect(barPath, fooPath, fee500, test1, test_tickLower, test_tickUpper, "50000000", "50000000") - - // pool should have zero liquidity - pool := GetPool(barPath, fooPath, fee500) - test_liquidity := pool.PoolGetLiquidity() -<<<<<<<< HEAD:pool/_TEST_pool_single_lp_test.gno_OK - shouldEQ(t, test_liquidity.IsZero(), true) -======== - shouldEQ(t, test_liquidity.ToString(), "0") ->>>>>>>> 486effd (feat: uint256, int256 instead of bigint):pool/_TEST_pool_single_lp_test.gno - - Mint(barPath, fooPath, fee500, consts.POSITION_ADDR, test_tickLower, test_tickUpper, new(u256.Uint).Mul(test_liquidityExpect256, u256.NewUint(15)).ToString()) - Burn(barPath, fooPath, fee500, test_tickLower, test_tickUpper, new(u256.Uint).Mul(test_liquidityExpect256, u256.NewUint(15)).ToString()) - c11, c12 := Collect(barPath, fooPath, fee500, test1, test_tickLower, test_tickUpper, "50000000", "50000000") - - Mint(barPath, fooPath, fee500, consts.POSITION_ADDR, test_tickLower, test_tickUpper, new(u256.Uint).Mul(test_liquidityExpect256, u256.NewUint(15)).ToString()) - Burn(barPath, fooPath, fee500, test_tickLower, test_tickUpper, new(u256.Uint).Mul(test_liquidityExpect256, u256.NewUint(15)).ToString()) - c21, c22 := Collect(barPath, fooPath, fee500, test1, test_tickLower, test_tickUpper, "50000000", "50000000") - - shouldEQ(t, c11, c21) // 443 - shouldEQ(t, c12, c22) // 1206 - - Mint(barPath, fooPath, fee500, consts.POSITION_ADDR, test_tickLower, test_tickUpper, new(u256.Uint).Mul(test_liquidityExpect256, u256.NewUint(15)).ToString()) - Burn(barPath, fooPath, fee500, test_tickLower, test_tickUpper, new(u256.Uint).Mul(test_liquidityExpect256, u256.NewUint(15)).ToString()) - c31, c32 := Collect(barPath, fooPath, fee500, test1, test_tickLower, test_tickUpper, "100", "100") - shouldEQ(t, c31, "100") - shouldEQ(t, c32, "100") - - c41, c42 := Collect(barPath, fooPath, fee500, test1, test_tickLower, test_tickUpper, "50000000", "50000000") - shouldEQ(t, c41, "343") // 343 = c21 - 100 - shouldEQ(t, c42, "1106") // 1106 = c22 - 100 - - // Mint > No Burn => nothing to collect - Mint(barPath, fooPath, fee500, consts.POSITION_ADDR, test_tickLower, test_tickUpper, new(u256.Uint).Mul(test_liquidityExpect256, u256.NewUint(15)).ToString()) - // Burn(barPath, fooPath, fee500, test_tickLower, test_tickUpper, test_liquidityExpectStr*15) - c51, c52 := Collect(barPath, fooPath, fee500, test1, test_tickLower, test_tickUpper, "50000000", "50000000") - shouldEQ(t, c51, "0") - shouldEQ(t, c52, "0") - - // Burn Now => something to collect - Burn(barPath, fooPath, fee500, test_tickLower, test_tickUpper, new(u256.Uint).Mul(test_liquidityExpect256, u256.NewUint(15)).ToString()) - c61, c62 := Collect(barPath, fooPath, fee500, test1, test_tickLower, test_tickUpper, "50000000", "50000000") - shouldNEQ(t, c61, "0") - shouldNEQ(t, c62, "0") -} - -// 5. Swap by test1 -func TestSwap(t *testing.T) { - pool := GetPool(barPath, fooPath, fee500) - test_liquidity := pool.PoolGetLiquidity() -<<<<<<<< HEAD:pool/_TEST_pool_single_lp_test.gno_OK - shouldEQ(t, test_liquidity.IsZero(), true) -======== - shouldEQ(t, test_liquidity.ToString(), "0") ->>>>>>>> 486effd (feat: uint256, int256 instead of bigint):pool/_TEST_pool_single_lp_test.gno - - std.TestSetPrevRealm(consts.POSITION_PATH) - std.TestSetOrigCaller(test1) - Mint(barPath, fooPath, fee500, consts.POSITION_ADDR, test_tickLower, test_tickUpper, new(u256.Uint).Mul(test_liquidityExpect256, u256.NewUint(20000)).ToString()) - - // Swap several times - std.TestSetPrevRealm(consts.ROUTER_PATH) - std.TestSetOrigCaller(test1) - test_price := consts.MIN_PRICE - { - poolOldToken0Bal := balanceOfByRegisterCall(pool.token0Path, consts.POOL_ADDR) - poolOldToken1Bal := balanceOfByRegisterCall(pool.token1Path, consts.POOL_ADDR) - - userOldToken0Bal := balanceOfByRegisterCall(pool.token0Path, test1) - userOldToken1Bal := balanceOfByRegisterCall(pool.token1Path, test1) - - amount0, amount1 := Swap( - fooPath, // token0Path - barPath, // token1Path - fee500, // fee - test1, // recipient - true, // zeroForOne - "10000", // _amountSpecified - test_price, // _sqrtPriceLimitX96 - std.GetOrigCaller(), // payer - ) - shouldNEQ(t, amount0, "0") - shouldNEQ(t, amount1, "0") - intAmount0, _ := strconv.Atoi(amount0) - intAmount1, _ := strconv.Atoi(amount1) - - poolNewToken0Bal := balanceOfByRegisterCall(pool.token0Path, consts.POOL_ADDR) - poolNewToken1Bal := balanceOfByRegisterCall(pool.token1Path, consts.POOL_ADDR) - - userNewToken0Bal := balanceOfByRegisterCall(pool.token0Path, test1) - userNewToken1Bal := balanceOfByRegisterCall(pool.token1Path, test1) - - shouldEQ(t, userOldToken0Bal-userNewToken0Bal, int64(intAmount0)) - shouldEQ(t, userNewToken1Bal-userOldToken1Bal, int64(-intAmount1)) - shouldEQ(t, poolNewToken0Bal-poolOldToken0Bal, int64(intAmount0)) - shouldEQ(t, poolOldToken1Bal-poolNewToken1Bal, int64(-intAmount1)) - } - - { - poolOldToken0Bal := balanceOfByRegisterCall(pool.token0Path, consts.POOL_ADDR) - poolOldToken1Bal := balanceOfByRegisterCall(pool.token1Path, consts.POOL_ADDR) - - userOldToken0Bal := balanceOfByRegisterCall(pool.token0Path, test1) - userOldToken1Bal := balanceOfByRegisterCall(pool.token1Path, test1) - - amount0, amount1 := Swap(barPath, fooPath, fee500, test1, true, "5000", test_price, std.GetOrigCaller()) // give enough amount to take fees away - intAmount0, _ := strconv.Atoi(amount0) - intAmount1, _ := strconv.Atoi(amount1) - - poolNewToken0Bal := balanceOfByRegisterCall(pool.token0Path, consts.POOL_ADDR) - poolNewToken1Bal := balanceOfByRegisterCall(pool.token1Path, consts.POOL_ADDR) - - userNewToken0Bal := balanceOfByRegisterCall(pool.token0Path, test1) - userNewToken1Bal := balanceOfByRegisterCall(pool.token1Path, test1) - - shouldEQ(t, userOldToken0Bal-userNewToken0Bal, int64(intAmount0)) - shouldEQ(t, userNewToken1Bal-userOldToken1Bal, int64(-intAmount1)) - shouldEQ(t, poolNewToken0Bal-poolOldToken0Bal, int64(intAmount0)) - shouldEQ(t, poolOldToken1Bal-poolNewToken1Bal, int64(-intAmount1)) - } - - { - poolOldToken0Bal := balanceOfByRegisterCall(pool.token0Path, consts.POOL_ADDR) - poolOldToken1Bal := balanceOfByRegisterCall(pool.token1Path, consts.POOL_ADDR) - - userOldToken0Bal := balanceOfByRegisterCall(pool.token0Path, test1) - userOldToken1Bal := balanceOfByRegisterCall(pool.token1Path, test1) - - amount0, amount1 := Swap(barPath, fooPath, fee500, test1, true, "1000", test_price, std.GetOrigCaller()) // give enough amount to take fees away - intAmount0, _ := strconv.Atoi(amount0) - intAmount1, _ := strconv.Atoi(amount1) - - poolNewToken0Bal := balanceOfByRegisterCall(pool.token0Path, consts.POOL_ADDR) - poolNewToken1Bal := balanceOfByRegisterCall(pool.token1Path, consts.POOL_ADDR) - - userNewToken0Bal := balanceOfByRegisterCall(pool.token0Path, test1) - userNewToken1Bal := balanceOfByRegisterCall(pool.token1Path, test1) - - shouldEQ(t, userOldToken0Bal-userNewToken0Bal, int64(intAmount0)) - shouldEQ(t, userNewToken1Bal-userOldToken1Bal, int64(-intAmount1)) - shouldEQ(t, poolNewToken0Bal-poolOldToken0Bal, int64(intAmount0)) - shouldEQ(t, poolOldToken1Bal-poolNewToken1Bal, int64(-intAmount1)) - } - - // Swap token1 -> token0 - { - poolOldToken0Bal := balanceOfByRegisterCall(pool.token0Path, consts.POOL_ADDR) - poolOldToken1Bal := balanceOfByRegisterCall(pool.token1Path, consts.POOL_ADDR) - - userOldToken0Bal := balanceOfByRegisterCall(pool.token0Path, test1) - userOldToken1Bal := balanceOfByRegisterCall(pool.token1Path, test1) - - amount0, amount1 := Swap(barPath, fooPath, fee500, test1, false, "16000", consts.MAX_PRICE, std.GetOrigCaller()) // give enough amount to take fees away - intAmount0, _ := strconv.Atoi(amount0) - intAmount1, _ := strconv.Atoi(amount1) - - poolNewToken0Bal := balanceOfByRegisterCall(pool.token0Path, consts.POOL_ADDR) - poolNewToken1Bal := balanceOfByRegisterCall(pool.token1Path, consts.POOL_ADDR) - - userNewToken0Bal := balanceOfByRegisterCall(pool.token0Path, test1) - userNewToken1Bal := balanceOfByRegisterCall(pool.token1Path, test1) - - shouldEQ(t, userOldToken0Bal-userNewToken0Bal, int64(intAmount0)) - shouldEQ(t, userNewToken1Bal-userOldToken1Bal, int64(-intAmount1)) - shouldEQ(t, poolNewToken0Bal-poolOldToken0Bal, int64(intAmount0)) - shouldEQ(t, poolOldToken1Bal-poolNewToken1Bal, int64(-intAmount1)) - } -} - -// 6. SetFeeProtocol by Gnoswap Admin -func TestSetFeeProtocol(t *testing.T) { - // non admin call - std.TestSetOrigCaller(test1) - shouldPanic(t, func() { SetFeeProtocol(2, 2) }) - - // admin call - std.TestSetOrigCaller(test1) - SetFeeProtocol(6, 8) - - for _, pool := range pools { - shouldEQ(t, pool.PoolGetSlot0().feeProtocol, 134) - } -} - -// 7. CollectProtocol by Gnoswap Admin -func TestCollectProtocol(t *testing.T) { - std.TestSetOrigCaller(test1) - - SetFeeProtocol(6, 8) - pool := GetPool(barPath, fooPath, fee500) - test_slot0 := pool.PoolGetSlot0() - shouldEQ(t, test_slot0.feeProtocol, 134) - - // Make ProtocolFee via Swap by test1 ( Mint by test1 ) - std.TestSetOrigCaller(test1) - { - - std.TestSetPrevRealm(consts.ROUTER_PATH) - std.TestSetOrigCaller(test1) - Swap(barPath, fooPath, fee500, test1, true, "200000", consts.MIN_PRICE, std.GetOrigCaller()) // swap token0 -> token1 => fee only in token0 - - test1OldToken0Bal := balanceOfByRegisterCall(pool.token0Path, test1) - test1OldToken1Bal := balanceOfByRegisterCall(pool.token1Path, test1) - -<<<<<<<< HEAD:pool/_TEST_pool_single_lp_test.gno_OK - std.TestSetPrevAddr(test1) - amount0, amount1 := CollectProtocol(barPath, fooPath, fee500, test1, u256.NewUint(100000), u256.NewUint(100000)) -======== - std.TestSetPrevAddr(gsa) - amount0, amount1 := CollectProtocol(barPath, fooPath, fee500, test1, "100000", "100000") ->>>>>>>> 486effd (feat: uint256, int256 instead of bigint):pool/_TEST_pool_single_lp_test.gno - - test1NewToken0Bal := balanceOfByRegisterCall(pool.token0Path, test1) - test1NewToken1Bal := balanceOfByRegisterCall(pool.token1Path, test1) - - _token0Diff := test1NewToken0Bal - test1OldToken0Bal - _token1Diff := test1NewToken1Bal - test1OldToken1Bal - -<<<<<<<< HEAD:pool/_TEST_pool_single_lp_test.gno_OK - { - std.TestSetPrevRealm(consts.ROUTER_PATH) - std.TestSetOrigCaller(test1) - Swap(barPath, fooPath, fee500, test1, false, 200000, consts.MAX_SQRT_RATIO-1, std.GetOrigCaller()) // swap token0 -> token1 => fee only in token0 - - test1OldToken0Bal := balanceOfByRegisterCall(pool.token0Path, test1) - test1OldToken1Bal := balanceOfByRegisterCall(pool.token1Path, test1) - - std.TestSetPrevAddr(test1) - amount0, amount1 := CollectProtocol(barPath, fooPath, fee500, test1, u256.NewUint(100000), u256.NewUint(100000)) - - test1NewToken0Bal := balanceOfByRegisterCall(pool.token0Path, test1) - test1NewToken1Bal := balanceOfByRegisterCall(pool.token1Path, test1) -======== - token0DiffStr := strconv.Itoa(int(_token0Diff)) - token1DiffStr := strconv.Itoa(int(_token1Diff)) - - shouldEQ(t, token0DiffStr, amount0) - shouldEQ(t, token1DiffStr, amount1) ->>>>>>>> 486effd (feat: uint256, int256 instead of bigint):pool/_TEST_pool_single_lp_test.gno - } -} - -/* GETTER_API TEST */ -func TestApiGetPools(t *testing.T) { - gpls := ApiGetPools() - jsonStr := gjson.Parse(gpls) - -<<<<<<<< HEAD:pool/_TEST_pool_single_lp_test.gno_OK - shouldEQ(t, jsonStr.Get("stat.height").Int(), GetHeight()) - shouldEQ(t, jsonStr.Get("stat.timestamp").Int(), GetTimestamp()) -======== - // shouldEQ(t, jsonStr.Get("stat.height").Int(), std.GetHeight()) - // shouldEQ(t, jsonStr.Get("stat.timestamp").Int(), time.Now().Unix()) ->>>>>>>> 486effd (feat: uint256, int256 instead of bigint):pool/_TEST_pool_single_lp_test.gno - - // shouldEQ(t, len(jsonStr.Get("response").Array()), 1) -} diff --git a/pool/_TEST_rpc_test.gno_OK b/pool/_TEST_rpc_test.gno_OK deleted file mode 100644 index 18fbdaed..00000000 --- a/pool/_TEST_rpc_test.gno_OK +++ /dev/null @@ -1,81 +0,0 @@ -package pool - -import ( - "std" - "testing" - - "encoding/gjson" - - _ "gno.land/r/demo/grc20_wrapper" -) - -var ( - test_tickLower = int32(9000) - test_tickUpper = int32(11000) - test_liquidityExpect = bigint(100_000_000) - - test_tickLower2 = int32(50000) - test_tickUpper2 = int32(100000) -) - -// 1. Init Pool -func TestInit(t *testing.T) { - std.TestSetOrigCaller(test1) - InitManual() -} - -// 2. Create Foo:Bar Pool -func TestCreateFooBarPool(t *testing.T) { - std.TestSetOrigCaller(test1) - CreatePool(fooPath, barPath, fee500, 130621891405341611593710811006) - shouldEQ(t, len(pools), 1) -} - -// 3. Create Bar:Baz Pool -func TestCreateBarBazPool(t *testing.T) { - std.TestSetOrigCaller(test1) - CreatePool(barPath, bazPath, fee500, 130621891405341611593710811006) - shouldEQ(t, len(pools), 2) -} - -// 4. Mint Foo:Bar Liquidity by test1 -func TestMintFooBarLiquidity(t *testing.T) { - std.TestSetPrevRealm("gno.land/r/demo/position") - std.TestSetOrigCaller(test1) - - Mint( - fooPath, - barPath, - fee500, - posAddr, - -test_tickUpper, - -test_tickLower, - test_liquidityExpect, - ) -} - -// 5. Mint Bar:Baz Liquidity by test1 -func TestMintBarBazLiquidity(t *testing.T) { - std.TestSetPrevRealm("gno.land/r/demo/position") - std.TestSetOrigCaller(test1) - - Mint( - barPath, - bazPath, - fee500, - posAddr, - test_tickLower, - test_tickUpper, - test_liquidityExpect, - ) -} - -// API TESTS -func TestApiGetPools(t *testing.T) { - jsonStr := ApiGetPools() - jsonArr := gjson.Parse(jsonStr).Get("response").Array() - shouldEQ(t, len(jsonArr), 2) - - // debug - println(jsonStr) -} diff --git a/pool/gno.mod b/pool/gno.mod index 4ccbab82..a45f3e80 100644 --- a/pool/gno.mod +++ b/pool/gno.mod @@ -1,15 +1,18 @@ module gno.land/r/demo/pool require ( - gno.land/p/demo/u256 v0.0.0-latest + gno.land/p/demo/common v0.0.0-latest gno.land/p/demo/ufmt v0.0.0-latest gno.land/r/demo/bar v0.0.0-latest gno.land/r/demo/baz v0.0.0-latest gno.land/r/demo/consts v0.0.0-latest gno.land/r/demo/foo v0.0.0-latest + gno.land/r/demo/fred v0.0.0-latest gno.land/r/demo/gns v0.0.0-latest gno.land/r/demo/gov v0.0.0-latest - gno.land/r/demo/grc20_wrapper v0.0.0-latest + gno.land/r/demo/obl v0.0.0-latest + gno.land/r/demo/qux v0.0.0-latest + gno.land/r/demo/thud v0.0.0-latest gno.land/r/demo/users v0.0.0-latest gno.land/r/demo/wugnot v0.0.0-latest ) diff --git a/pool/swap_math.gno b/pool/swap_math.gno index d3120fad..20df7fbf 100644 --- a/pool/swap_math.gno +++ b/pool/swap_math.gno @@ -18,10 +18,6 @@ func swapMathComputeSwapStep( // NEGATIVE == EXACT_OUT => Estimated AmountIn exactIn := !(amountRemaining.IsNeg()) // amountRemaining >= 0 - // println() - // println("exactIn", exactIn) // f - // println("isToken1Expensive", isToken1Expensive) // t - if exactIn { amountRemainingLessFee := u256.Zero() @@ -47,31 +43,20 @@ func swapMathComputeSwapStep( } } else { if isToken1Expensive { - // println(1) amountOut = sqrtPriceMathGetAmount1DeltaHelper(sqrtRatioTargetX96, sqrtRatioCurrentX96, liquidity, false) } else { - // println(2) amountOut = sqrtPriceMathGetAmount0DeltaHelper(sqrtRatioCurrentX96, sqrtRatioTargetX96, liquidity, false) } if amountRemaining.Abs().Gte(amountOut) { - // println(3) sqrtRatioNextX96 = sqrtRatioTargetX96 } else { - // println(4) - // println("sqrtRatioCurrentX96:", sqrtRatioCurrentX96.ToString()) - // println("liquidity:", liquidity.ToString()) - // println("amountRemaining.Abs():", amountRemaining.Abs().ToString()) - // println("isToken1Expensive:", isToken1Expensive) - // println("<< SQRT") sqrtRatioNextX96 = sqrtPriceMathGetNextSqrtPriceFromOutput( sqrtRatioCurrentX96, liquidity, amountRemaining.Abs(), isToken1Expensive, ) - // println("sqrtRatioNextX96:", sqrtRatioNextX96.ToString()) - // panic("F") } } @@ -117,6 +102,5 @@ func swapMathComputeSwapStep( if !exactIn && !(amountOut.IsZero()) { amountOut = amountOut.Add(amountOut, u256.NewUint(1)) } - // println() return sqrtRatioNextX96, amountIn, amountOut, feeAmount } diff --git a/pool/tick_bitmap_test.gno b/pool/tick_bitmap_test.gno deleted file mode 100644 index b7ae48fc..00000000 --- a/pool/tick_bitmap_test.gno +++ /dev/null @@ -1,174 +0,0 @@ -package pool - -import ( - "testing" - - "gno.land/p/demo/ufmt" - "gno.land/r/demo/consts" -) - -func TestTickBitmapPosition(t *testing.T) { - tests := []struct { - name string - tick int32 - expected struct { - wordPos int16 - bitPos uint8 - } - }{ - {"tick at beginning", 0, struct { - wordPos int16 - bitPos uint8 - }{0, 0}}, - {"tick at end of first word", 255, struct { - wordPos int16 - bitPos uint8 - }{0, 255}}, - {"tick at beginning of second word", 256, struct { - wordPos int16 - bitPos uint8 - }{1, 0}}, - {"negative tick", -1, struct { - wordPos int16 - bitPos uint8 - }{-1, 255}}, - } - - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - wordPos, bitPos := tickBitmapPosition(tt.tick) - if wordPos != tt.expected.wordPos || bitPos != tt.expected.bitPos { - t.Errorf("tickBitmapPosition(%d) = %d, %d; expected %d, %d", - tt.tick, wordPos, bitPos, tt.expected.wordPos, tt.expected.bitPos) - } - }) - } -} - -func TestPool_tickBitmapFlipTick(t *testing.T) { - pool := &Pool{ - tickBitmaps: make(TickBitmaps), - } - - tests := []struct { - name string - tick int32 - tickSpacing int32 - setup func() - verify func() bool - expectPanic bool - }{ - { - name: "flip tick within range", - tick: 0, - tickSpacing: 1, - setup: func() {}, - verify: func() bool { - // Check if the bit at position 0 has been flipped - return pool.tickBitmaps[0]&1 == 1 - }, - }, - { - name: "flip tick out of range", - tick: 256, - tickSpacing: 1, - setup: func() {}, - verify: func() bool { - // Check if the bit at position 1 (word 0, bit 256) has been flipped - return pool.tickBitmaps[1]&1 == 1 - }, - }, - } - - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - if tt.expectPanic { - defer func() { - if r := recover(); r == nil { - t.Errorf("The code did not panic") - } - }() - } - - tt.setup() - pool.tickBitmapFlipTick(tt.tick, tt.tickSpacing) - - if !tt.expectPanic { - if !tt.verify() { - t.Errorf("Failed to verify test: %s", tt.name) - } - } - }) - } -} - -func TestPool_tickBitmapNextInitializedTickWithInOneWord(t *testing.T) { - pool := &Pool{ - tickBitmaps: make(TickBitmaps), - tickSpacing: 1, // Assuming tickSpacing is 1 for simplicity - } - - // Setup: Initialize the tickBitmaps for testing - // For simplicity, let's assume we're working with a single word (int16) and we initialize it directly. - // Example: Initialize the bitmap with some bits set. Adjust this based on your specific test scenario. - // Let's say we initialize the bitmap such that ticks at positions 3, 5, and 8 are initialized. - wordPos := int16(0) - pool.tickBitmaps[wordPos] = 0b0000000100101000 // Binary representation for simplicity - - tests := []struct { - name string - tick int32 - lte bool - expected struct { - nextTick int32 - initialized bool - } - }{ - { - name: "Find next initialized tick, lte true, tick before first initialized", - tick: 2, // Tick before the first initialized tick - lte: true, - expected: struct { - nextTick int32 - initialized bool - }{0, false}, // The next initialized tick is 3 - }, - { - name: "Find next initialized tick, lte false, tick before first initialized", - tick: 2, - lte: false, - expected: struct { - nextTick int32 - initialized bool - }{3, true}, - }, - { - name: "Find next initialized tick, lte true, tick after last initialized", - tick: 9, - lte: true, - expected: struct { - nextTick int32 - initialized bool - }{8, true}, - }, - { - name: "No next initialized tick, lte false, tick after last initialized", - tick: 9, - lte: false, - expected: struct { - nextTick int32 - initialized bool - }{255, false}, - }, - } - - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - nextTick, initialized := pool.tickBitmapNextInitializedTickWithInOneWord(tt.tick, pool.tickSpacing, tt.lte) - if nextTick != tt.expected.nextTick || initialized != tt.expected.initialized { - t.Errorf("(%s) tickBitmapNextInitializedTickWithInOneWord(%d, %d, %t) = %d, %t; expected %d, %t", - tt.name, tt.tick, pool.tickSpacing, tt.lte, nextTick, initialized, tt.expected.nextTick, tt.expected.initialized) - } - }) - } -} diff --git a/pool/tick_math.gno b/pool/tick_math.gno deleted file mode 100644 index e1cc165c..00000000 --- a/pool/tick_math.gno +++ /dev/null @@ -1,223 +0,0 @@ -package pool - -import ( - "gno.land/p/demo/u256" - "gno.land/p/demo/ufmt" - - "gno.land/r/demo/consts" -) - -func TickMathGetSqrtRatioAtTick(tick int32) *u256.Uint { - var absTick *u256.Uint - if tick < 0 { - absTick = u256.NewUint(uint64(-tick)) - } else { - absTick = u256.NewUint(uint64(tick)) - } - - require(!absTick.Lte(u256.NewUint(uint64(consts.MAX_TICK))), ufmt.Sprintf("[POOL] tick_math.gno__TickMathGetSqrtRatioAtTick() || Tick out of range [absTick(%s) <= MAX_TICK(%d)]", absTick.Dec(), consts.MAX_TICK)) - - var ratio *u256.Uint - if !new(u256.Uint).And(absTick, u256.NewUint(0x1)).IsZero() { - ratio = u256.FromBigint(0xfffcb933bd6fad37aa2d162d1a594001) - } else { - ratio = u256.FromBigint(0x100000000000000000000000000000000) - } - - if !new(u256.Uint).And(absTick, u256.NewUint(0x2)).IsZero() { - ratio.Mul(ratio, u256.FromBigint(0xfff97272373d413259a46990580e213a)) - ratio.Rsh(ratio, 128) - } - - if !new(u256.Uint).And(absTick, u256.NewUint(0x4)).IsZero() { - ratio.Mul(ratio, u256.FromBigint(0xfff2e50f5f656932ef12357cf3c7fdcc)) - ratio.Rsh(ratio, 128) - } - - if !new(u256.Uint).And(absTick, u256.NewUint(0x8)).IsZero() { - ratio.Mul(ratio, u256.FromBigint(0xffe5caca7e10e4e61c3624eaa0941cd0)) - ratio.Rsh(ratio, 128) - } - - if !new(u256.Uint).And(absTick, u256.NewUint(0x10)).IsZero() { - ratio.Mul(ratio, u256.FromBigint(0xffcb9843d60f6159c9db58835c926644)) - ratio.Rsh(ratio, 128) - } - - if !new(u256.Uint).And(absTick, u256.NewUint(0x20)).IsZero() { - ratio.Mul(ratio, u256.FromBigint(0xff973b41fa98c081472e6896dfb254c0)) - ratio.Rsh(ratio, 128) - } - - if !new(u256.Uint).And(absTick, u256.NewUint(0x40)).IsZero() { - ratio.Mul(ratio, u256.FromBigint(0xff2ea16466c96a3843ec78b326b52861)) - ratio.Rsh(ratio, 128) - } - - if !new(u256.Uint).And(absTick, u256.NewUint(0x80)).IsZero() { - ratio.Mul(ratio, u256.FromBigint(0xfe5dee046a99a2a811c461f1969c3053)) - ratio.Rsh(ratio, 128) - } - - if !new(u256.Uint).And(absTick, u256.NewUint(0x100)).IsZero() { - ratio.Mul(ratio, u256.FromBigint(0xfcbe86c7900a88aedcffc83b479aa3a4)) - ratio.Rsh(ratio, 128) - } - - if !new(u256.Uint).And(absTick, u256.NewUint(0x200)).IsZero() { - ratio.Mul(ratio, u256.FromBigint(0xf987a7253ac413176f2b074cf7815e54)) - ratio.Rsh(ratio, 128) - } - - if !new(u256.Uint).And(absTick, u256.NewUint(0x400)).IsZero() { - ratio.Mul(ratio, u256.FromBigint(0xf3392b0822b70005940c7a398e4b70f3)) - ratio.Rsh(ratio, 128) - } - - if !new(u256.Uint).And(absTick, u256.NewUint(0x800)).IsZero() { - ratio.Mul(ratio, u256.FromBigint(0xe7159475a2c29b7443b29c7fa6e889d9)) - ratio.Rsh(ratio, 128) - } - - if !new(u256.Uint).And(absTick, u256.NewUint(0x1000)).IsZero() { - ratio.Mul(ratio, u256.FromBigint(0xd097f3bdfd2022b8845ad8f792aa5825)) - ratio.Rsh(ratio, 128) - } - - if !new(u256.Uint).And(absTick, u256.NewUint(0x2000)).IsZero() { - ratio.Mul(ratio, u256.FromBigint(0xa9f746462d870fdf8a65dc1f90e061e5)) - ratio.Rsh(ratio, 128) - } - - if !new(u256.Uint).And(absTick, u256.NewUint(0x4000)).IsZero() { - ratio.Mul(ratio, u256.FromBigint(0x70d869a156d2a1b890bb3df62baf32f7)) - ratio.Rsh(ratio, 128) - } - - if !new(u256.Uint).And(absTick, u256.NewUint(0x8000)).IsZero() { - ratio.Mul(ratio, u256.FromBigint(0x31be135f97d08fd981231505542fcfa6)) - ratio.Rsh(ratio, 128) - } - - if !new(u256.Uint).And(absTick, u256.NewUint(0x10000)).IsZero() { - ratio.Mul(ratio, u256.FromBigint(0x9aa508b5b7a84e1c677de54f3e99bc9)) - ratio.Rsh(ratio, 128) - } - - if !new(u256.Uint).And(absTick, u256.NewUint(0x20000)).IsZero() { - ratio.Mul(ratio, u256.FromBigint(0x5d6af8dedb81196699c329225ee604)) - ratio.Rsh(ratio, 128) - } - - if !new(u256.Uint).And(absTick, u256.NewUint(0x40000)).IsZero() { - ratio.Mul(ratio, u256.FromBigint(0x2216e584f5fa1ea926041bedfe98)) - ratio.Rsh(ratio, 128) - } - - if !new(u256.Uint).And(absTick, u256.NewUint(0x80000)).IsZero() { - ratio.Mul(ratio, u256.FromBigint(0x48a170391f7dc42444e8fa2)) - ratio.Rsh(ratio, 128) - } - - if tick > 0 { - ratio.Div(u256.FromBigint(consts.MAX_UINT256), ratio) - } - - shiftedRatio := new(u256.Uint).Rsh(ratio, 32) - - remainder := new(u256.Uint).Mod(ratio, u256.NewUint(1<<32)) - - if new(u256.Uint).Add(shiftedRatio, remainder).IsZero() { - return shiftedRatio - } else { - return shiftedRatio.Add(shiftedRatio, u256.One()) - } -} - -func TickMathGetTickAtSqrtRatio(sqrtPriceX96 *u256.Uint) int32 { - require(sqrtPriceX96.Gte(u256.FromBigint(consts.MIN_SQRT_RATIO)) && sqrtPriceX96.Lt(u256.FromBigint(consts.MAX_SQRT_RATIO)), ufmt.Sprintf("[POOL] tick_math.gno__tickMathGetTickAtSqrtRatio() || Tick out of range [sqrtPriceX96(%s) >= MIN_SQRT_RATIO(%d) && sqrtPriceX96(%s) < MAX_SQRT_RATIO(%d)]", sqrtPriceX96.Dec(), consts.MIN_SQRT_RATIO, sqrtPriceX96.Dec(), consts.MAX_SQRT_RATIO)) - ratio := new(u256.Uint).Lsh(sqrtPriceX96, 32) - - r := ratio.Clone() - msb := uint64(0) - - // array - _tv := [8]*u256.Uint{ - u256.FromBigint(0), - u256.FromBigint(3), - u256.FromBigint(15), - u256.FromBigint(255), - u256.FromBigint(65535), - u256.FromBigint(4294967295), - u256.FromBigint(18446744073709551615), - u256.FromBigint(340282366920938463463374607431768211455), - } - - for i := 7; i >= 1; i-- { - f := gt(r, _tv[i]) << uint(i) - msb = msb | f - r.Rsh(r, uint(f)) - } - { - f := gt(r, u256.One()) - msb = msb | f - } - - if msb >= 128 { - r = new(u256.Uint).Rsh(ratio, uint(msb-127)) - } else { - r = new(u256.Uint).Lsh(ratio, uint(127-msb)) - } - - log_2 := u256.NewInt(int64(msb - 128)) - log_2.Lsh(log_2, 64) // -18446744073709551616 - - for i := 63; i >= 51; i-- { - - r.Mul(r, r) - r.Rsh(r, 127) - f := new(u256.Uint).Rsh(r, 128) - - _temp := new(u256.Uint).Lsh(f, uint(i)) - - log_2.Or(log_2, new(u256.Uint).Lsh(f, uint(i)).Int()) - - r.Rsh(r, uint(f.Uint64())) // XXXXXXXXX possibly overflow - } - - { - r.Mul(r, r) - r.Rsh(r, 127) - f := new(u256.Uint).Rsh(r, 128) - log_2.Or(log_2, new(u256.Uint).Lsh(f, uint(50)).Int()) - } - - log_sqrt10001 := new(u256.Int).Mul(log_2, u256.FromBigint(255738958999603826347141).Int()) - - tickLow256 := new(u256.Int).Sub(log_sqrt10001, u256.FromBigint(3402992956809132418596140100660247210).Int()) - tickLow256.Rsh(tickLow256, 128) - tickLow := int32(tickLow256.Int64()) // XXXXX: needs to be checked if bound - - tickHi256 := new(u256.Int).Add(log_sqrt10001, u256.FromBigint(291339464771989622907027621153398088495).Int()) - tickHi256.Rsh(tickHi256, 128) - tickHi := int32(tickHi256.Int64()) // XXXXX: needs to be checked if bound - - var tick int32 - if tickLow == tickHi { - tick = tickLow - } else if TickMathGetSqrtRatioAtTick(tickHi).Lte(sqrtPriceX96) { - tick = tickHi - } else { - tick = tickLow - } - - return tick -} - -func gt(x, y *u256.Uint) uint64 { - if x.Gt(y) { - return 1 - } else { - return 0 - } -} diff --git a/position/_RPC_api.gno b/position/_RPC_api.gno index 30c19ca0..5a1578fe 100644 --- a/position/_RPC_api.gno +++ b/position/_RPC_api.gno @@ -82,8 +82,8 @@ func rpcMakePosition(lpTokenId uint64) RpcPosition { token0Balance, token1Balance := common.GetAmountsForLiquidity( currentX96, - lowerX96.Bigint(), - upperX96.Bigint(), + lowerX96, + upperX96, position.liquidity, ) diff --git a/position/liquidity_management.gno b/position/liquidity_management.gno index 4cf29d51..cacccd49 100644 --- a/position/liquidity_management.gno +++ b/position/liquidity_management.gno @@ -15,8 +15,8 @@ func addLiquidity(params AddLiquidityParams) (*u256.Uint, *u256.Uint, *u256.Uint pool := pl.GetPoolFromPoolPath(params.poolKey) sqrtPriceX96 := pool.PoolGetSlot0SqrtPriceX96() - sqrtRatioAX96 := p.TickMathGetSqrtRatioAtTick(params.tickLower).Bigint() - sqrtRatioBX96 := p.TickMathGetSqrtRatioAtTick(params.tickUpper).Bigint() + sqrtRatioAX96 := common.TickMathGetSqrtRatioAtTick(params.tickLower) + sqrtRatioBX96 := common.TickMathGetSqrtRatioAtTick(params.tickUpper) liquidity := common.GetLiquidityForAmounts( sqrtPriceX96, diff --git a/position/sqrt_price_math.gno b/position/sqrt_price_math.gno index 3de01094..8ccf6415 100644 --- a/position/sqrt_price_math.gno +++ b/position/sqrt_price_math.gno @@ -80,34 +80,6 @@ func sqrtPriceMathGetNextSqrtPriceFromAmount1RoundingDown( quotient = new(u256.Uint).Sub(quotient, u256.One()) return new(u256.Uint).Sub(sqrtPX96, quotient) } - - // quotient mutst be positive when amount and liquidity are positive - if add { - if amount.Lte(u256.UnsafeFromDecimal(consts.MAX_UINT160)) { - quotient = new(u256.Uint).Lsh(amount, 96) - quotient = new(u256.Uint).Div(quotient, liquidity) - } else { - quotient = u256.MulDiv(amount, u256.UnsafeFromDecimal(consts.Q96), liquidity) - } - - quotient = new(u256.Uint).Sub(quotient, u256.One()) - return new(u256.Uint).Add(sqrtPX96, quotient) - } else { - if amount.Lte(u256.UnsafeFromDecimal(consts.MAX_UINT160)) { - value1 := new(u256.Uint).Lsh(amount, 96) - quotient = u256.DivRoundingUp(value1, liquidity) - } else { - quotient = u256.MulDiv(amount, u256.UnsafeFromDecimal(consts.Q96), liquidity) - } - - if !(sqrtPX96.Gt(quotient)) { - panic("position_sqrt price math #2") - } - - // roundDown - quotient = new(u256.Uint).Sub(quotient, u256.One()) - return new(u256.Uint).Sub(sqrtPX96, quotient) - } } func sqrtPriceMathGetNextSqrtPriceFromInput( diff --git a/router/_RPC_api.gno b/router/_RPC_api.gno index 18f59875..5e09bb93 100644 --- a/router/_RPC_api.gno +++ b/router/_RPC_api.gno @@ -52,7 +52,7 @@ func ApiGetRatiosFromBase() string { func findRatios(maxHops int) []TokenRatio { var tokenRatio = make(map[string]*u256.Uint, 0) // WGNOT - tokenRatio[consts.WRAPPED_WUGNOT] = consts.Q96 // ~= 1 + tokenRatio[consts.WRAPPED_WUGNOT] = u256.MustFromDecimal(consts.Q96) // ~= 1 tokens := getTokenList() @@ -71,7 +71,7 @@ func findRatios(maxHops int) []TokenRatio { } else { numRoutes := uint64(len(routes)) - var _tokenRatioX96 bigint + _tokenRatioX96 := u256.Zero() for _, route := range routes { numHops := uint64(len(route.route)) @@ -125,19 +125,18 @@ func calculateTokenRatio(currentToken string, routes []PoolWithMeta, proceed int currentToken = token1Path } else { // wrong condition - // panic("[ROUTER] _RPC_api.gno__calculateTokenRatio() || wrong condition") - return 0 - + panic("[ROUTER] _RPC_api.gno__calculateTokenRatio() || wrong condition") + return u256.Zero() } proceed += 1 - if proceed == len(routes) { // numHops - for { // remove as much X96 as possible - tempPriceX96 := priceX96 - priceX96 /= consts.Q96 + for { // remove as much X96 as possible + tempPriceX96 := priceX96.Clone() + priceX96 = new(u256.Uint).Div(priceX96, u256.MustFromDecimal(consts.Q96)) - if priceX96 < consts.MIN_PRICE { + if priceX96.Lt(u256.MustFromDecimal(consts.MIN_PRICE)) { + if proceed == len(routes) { return tempPriceX96 } return calculateTokenRatio(currentToken, routes, proceed, priceX96) diff --git a/router/router.gno b/router/router.gno index fc936fda..89b603b1 100644 --- a/router/router.gno +++ b/router/router.gno @@ -46,7 +46,8 @@ func SwapRoute( // check route length ( should be 1 ~ 7 ) routes := strings.Split(strRouteArr, ",") - if !(1 <= len(routes) && len(routes) <= 7) { + isValidRouteLength := (1 <= len(routes)) && (len(routes) <= 7) + if !isValidRouteLength { panic(ufmt.Sprintf("[ROUTER] router.gno__SwapRoute() || len(routes) should be 1 ~ 7 (len(routes)[%d])", len(routes))) } diff --git a/router/router_dry.gno b/router/router_dry.gno index a0d73afa..d06dccf6 100644 --- a/router/router_dry.gno +++ b/router/router_dry.gno @@ -37,7 +37,8 @@ func DrySwapRoute( // check route length ( should be 1 ~ 7 ) routes := strings.Split(strRouteArr, ",") - if !(1 <= len(routes) && len(routes) <= 7) { + isValidRouteLength := (1 <= len(routes)) && (len(routes) <= 7) + if !isValidRouteLength { panic(ufmt.Sprintf("[ROUTER] router_dry.gno__DrySwapRoute() || len(routes) should be 1 ~ 7 (len(routes)[%d])", len(routes))) } diff --git a/staker/_TEST_staker_manage_pool_tiers_test.gnoa b/staker/_TEST_staker_manage_pool_tiers_test.gnoa new file mode 100644 index 00000000..11a6b805 --- /dev/null +++ b/staker/_TEST_staker_manage_pool_tiers_test.gnoa @@ -0,0 +1,54 @@ +package staker + +import ( + "std" + "testing" + + pl "gno.land/r/demo/pool" + + "gno.land/r/demo/consts" + + "gno.land/r/demo/gns" +) + +func TestPoolInitCreatePool(t *testing.T) { + std.TestSetPrevAddr(gsa) + pl.InitManual() + std.TestSkipHeights(1) + + std.TestSetPrevAddr(test1) + gns.Approve(a2u(consts.POOL_ADDR), consts.POOL_CREATION_FEE) + std.TestSkipHeights(1) + + pl.CreatePool(fooPath, barPath, 500, "130621891405341611593710811006") // tick 10_000 ≈ x2.7 + std.TestSkipHeights(1) +} + +func TestSetPoolTier(t *testing.T) { + std.TestSetOrigCaller(consts.GNOSWAP_ADMIN) + SetPoolTier("gno.land/r/demo/bar:gno.land/r/demo/foo:500", 2) +} + +func TestGetPoolWithTiers(t *testing.T) { + poolTiers := GetPoolWithTiers() + if len(poolTiers) != 2 { + t.Error("Expected 2 pools") + } +} + +func TestChangePoolTier(t *testing.T) { + std.TestSetOrigCaller(consts.GNOSWAP_ADMIN) + ChangePoolTier("gno.land/r/demo/bar:gno.land/r/demo/foo:500", 3) + if poolTiers["gno.land/r/demo/bar:gno.land/r/demo/foo:500"] != 3 { + t.Error("Expected tier to be 3") + } +} + +func TestRemovePoolTier(t *testing.T) { + std.TestSetOrigCaller(consts.GNOSWAP_ADMIN) + RemovePoolTier("gno.land/r/demo/bar:gno.land/r/demo/foo:500") + if len(poolTiers) != 1 { + t.Error("Expected 1 pool") + } + +} diff --git a/staker/_TEST_staker_rpc_get_test.gno b/staker/_TEST_staker_rpc_get_test.gnoa similarity index 100% rename from staker/_TEST_staker_rpc_get_test.gno rename to staker/_TEST_staker_rpc_get_test.gnoa diff --git a/staker/manage_pool_tiers.gno b/staker/manage_pool_tiers.gno new file mode 100644 index 00000000..b1f50e81 --- /dev/null +++ b/staker/manage_pool_tiers.gno @@ -0,0 +1,78 @@ +package staker + +import ( + "std" + + pl "gno.land/r/demo/pool" + + "gno.land/p/demo/ufmt" + + "gno.land/r/demo/consts" +) + +func GetPoolWithTiers() map[string]uint64 { + return poolTiers +} + +func SetPoolTier(pool string, tier uint64) { + // check if caller is admin + isAdmin() + + // panic if pool does not exist + if !(pl.DoesPoolPathExist(pool)) { + panic(ufmt.Sprintf("[STAKER] manage_pool_tiers.gno__SetPoolTier() || pool(%s) does not exist")) + } + + // panic if pool exists in poolTiers + if _, exist := poolTiers[pool]; exist { + panic(ufmt.Sprintf("[STAKER] manage_pool_tiers.gno__SetPoolTier() || pool(%s) already exists in poolTiers")) + } + + // check if tier is valid + validTier(tier) + + poolTiers[pool] = tier +} + +func ChangePoolTier(pool string, tier uint64) { + // check if caller is admin + isAdmin() + + // panic if pool does not exist in poolTiers + if _, exist := poolTiers[pool]; !exist { + panic(ufmt.Sprintf("[STAKER] manage_pool_tiers.gno__ChangePoolTier() || pool(%s) does not exist in poolTiers")) + } + + // check if tier is valid + validTier(tier) + + // CAN'T CHANGE TIER OF THIS GNS:GNOT 0.03% + if pool == MUST_EXISTS_IN_TIER_1 { + panic(ufmt.Sprintf("[STAKER] manage_pool_tiers.gno__ChangePoolTier() || Cannot change tier of this pool(%s)")) + } + + poolTiers[pool] = tier +} + +func RemovePoolTier(pool string) { + // check if caller is admin + isAdmin() + + if pool == MUST_EXISTS_IN_TIER_1 { + panic(ufmt.Sprintf("[STAKER] manage_pool_tiers.gno__RemovePoolTier() || Cannot change tier of this pool")) + } + + delete(poolTiers, pool) +} + +func isAdmin() { + if std.GetOrigCaller() != consts.GNOSWAP_ADMIN { + panic(ufmt.Sprintf("caller(%s) is not admin", std.GetOrigCaller())) + } +} + +func validTier(tier uint64) { + if tier < 1 || tier > 3 { + panic(ufmt.Sprintf("tier(%d) is not valid", tier)) + } +} diff --git a/staker/staker.gno b/staker/staker.gno index 66c675c1..caa6df8d 100644 --- a/staker/staker.gno +++ b/staker/staker.gno @@ -30,12 +30,14 @@ const ( TIMESTAMP_90DAYS = 7776000 TIMESTAMP_180DAYS = 15552000 TIMESTAMP_360DAYS = 31104000 + + MUST_EXISTS_IN_TIER_1 = "gno.land/r/demo/gns:gno.land/r/demo/wugnot:3000" ) func init() { // init pool tiers // tier 1 - poolTiers["gno.land/r/demo/gns:gno.land/r/demo/wugnot:500"] = 1 // r3v4_xxx: INITIALIZE TIER 1 POOL + poolTiers[MUST_EXISTS_IN_TIER_1] = 1 // ONLY GNOT:GNS 0.03% } func CreateExternalIncentive( @@ -256,8 +258,8 @@ func getTokenPairBalanceFromPosition(tokenId uint64) (*u256.Uint, *u256.Uint) { pool := pl.GetPoolFromPoolPath(poolKey) currentX96 := pool.PoolGetSlot0SqrtPriceX96() - lowerX96 := pl.TickMathGetSqrtRatioAtTick(pos.PositionGetPositionTickLower(tokenId)).Bigint() - upperX96 := pl.TickMathGetSqrtRatioAtTick(pos.PositionGetPositionTickUpper(tokenId)).Bigint() + lowerX96 := common.TickMathGetSqrtRatioAtTick(pn.PositionGetPositionTickLower(tokenId)) + upperX96 := common.TickMathGetSqrtRatioAtTick(pn.PositionGetPositionTickUpper(tokenId)) token0Balance, token1Balance := common.GetAmountsForLiquidity( currentX96, diff --git a/u256/bits.gno b/u256/bits.gno deleted file mode 100644 index 7195d38f..00000000 --- a/u256/bits.gno +++ /dev/null @@ -1,601 +0,0 @@ - - -// Copyright 2017 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:generate go run make_tables.go - -// Package bits implements bit counting and manipulation -// functions for the predeclared unsigned integer types. -// -// Functions in this package may be implemented directly by -// the compiler, for better performance. For those functions -// the code in this package will not be used. Which -// functions are implemented by the compiler depends on the -// architecture and the Go release. -package u256 - -const uintSize = 32 << (^uint(0) >> 63) // 32 or 64 - -// UintSize is the size of a uint in bits. -const UintSize = uintSize - -// --- LeadingZeros --- - -// LeadingZeros returns the number of leading zero bits in x; the result is [UintSize] for x == 0. -func LeadingZeros(x uint) int { return UintSize - Len(x) } - -// LeadingZeros8 returns the number of leading zero bits in x; the result is 8 for x == 0. -func LeadingZeros8(x uint8) int { return 8 - Len8(x) } - -// LeadingZeros16 returns the number of leading zero bits in x; the result is 16 for x == 0. -func LeadingZeros16(x uint16) int { return 16 - Len16(x) } - -// LeadingZeros32 returns the number of leading zero bits in x; the result is 32 for x == 0. -func LeadingZeros32(x uint32) int { return 32 - Len32(x) } - -// LeadingZeros64 returns the number of leading zero bits in x; the result is 64 for x == 0. -func LeadingZeros64(x uint64) int { return 64 - Len64(x) } - -// --- TrailingZeros --- - -// See http://supertech.csail.mit.edu/papers/debruijn.pdf -const deBruijn32 = 0x077CB531 - -var deBruijn32tab = [32]byte{ - 0, 1, 28, 2, 29, 14, 24, 3, 30, 22, 20, 15, 25, 17, 4, 8, - 31, 27, 13, 23, 21, 19, 16, 7, 26, 12, 18, 6, 11, 5, 10, 9, -} - -const deBruijn64 = 0x03f79d71b4ca8b09 - -var deBruijn64tab = [64]byte{ - 0, 1, 56, 2, 57, 49, 28, 3, 61, 58, 42, 50, 38, 29, 17, 4, - 62, 47, 59, 36, 45, 43, 51, 22, 53, 39, 33, 30, 24, 18, 12, 5, - 63, 55, 48, 27, 60, 41, 37, 16, 46, 35, 44, 21, 52, 32, 23, 11, - 54, 26, 40, 15, 34, 20, 31, 10, 25, 14, 19, 9, 13, 8, 7, 6, -} - -// TrailingZeros returns the number of trailing zero bits in x; the result is [UintSize] for x == 0. -func TrailingZeros(x uint) int { - if UintSize == 32 { - return TrailingZeros32(uint32(x)) - } - return TrailingZeros64(uint64(x)) -} - -// TrailingZeros8 returns the number of trailing zero bits in x; the result is 8 for x == 0. -func TrailingZeros8(x uint8) int { - return int(ntz8tab[x]) -} - -// TrailingZeros16 returns the number of trailing zero bits in x; the result is 16 for x == 0. -func TrailingZeros16(x uint16) int { - if x == 0 { - return 16 - } - // see comment in TrailingZeros64 - return int(deBruijn32tab[uint32(x&-x)*deBruijn32>>(32-5)]) -} - -// TrailingZeros32 returns the number of trailing zero bits in x; the result is 32 for x == 0. -func TrailingZeros32(x uint32) int { - if x == 0 { - return 32 - } - // see comment in TrailingZeros64 - return int(deBruijn32tab[(x&-x)*deBruijn32>>(32-5)]) -} - -// TrailingZeros64 returns the number of trailing zero bits in x; the result is 64 for x == 0. -func TrailingZeros64(x uint64) int { - if x == 0 { - return 64 - } - // If popcount is fast, replace code below with return popcount(^x & (x - 1)). - // - // x & -x leaves only the right-most bit set in the word. Let k be the - // index of that bit. Since only a single bit is set, the value is two - // to the power of k. Multiplying by a power of two is equivalent to - // left shifting, in this case by k bits. The de Bruijn (64 bit) constant - // is such that all six bit, consecutive substrings are distinct. - // Therefore, if we have a left shifted version of this constant we can - // find by how many bits it was shifted by looking at which six bit - // substring ended up at the top of the word. - // (Knuth, volume 4, section 7.3.1) - return int(deBruijn64tab[(x&-x)*deBruijn64>>(64-6)]) -} - -// --- OnesCount --- - -const m0 = 0x5555555555555555 // 01010101 ... -const m1 = 0x3333333333333333 // 00110011 ... -const m2 = 0x0f0f0f0f0f0f0f0f // 00001111 ... -const m3 = 0x00ff00ff00ff00ff // etc. -const m4 = 0x0000ffff0000ffff - -// OnesCount returns the number of one bits ("population count") in x. -func OnesCount(x uint) int { - if UintSize == 32 { - return OnesCount32(uint32(x)) - } - return OnesCount64(uint64(x)) -} - -// OnesCount8 returns the number of one bits ("population count") in x. -func OnesCount8(x uint8) int { - return int(pop8tab[x]) -} - -// OnesCount16 returns the number of one bits ("population count") in x. -func OnesCount16(x uint16) int { - return int(pop8tab[x>>8] + pop8tab[x&0xff]) -} - -// OnesCount32 returns the number of one bits ("population count") in x. -func OnesCount32(x uint32) int { - return int(pop8tab[x>>24] + pop8tab[x>>16&0xff] + pop8tab[x>>8&0xff] + pop8tab[x&0xff]) -} - -// OnesCount64 returns the number of one bits ("population count") in x. -func OnesCount64(x uint64) int { - // Implementation: Parallel summing of adjacent bits. - // See "Hacker's Delight", Chap. 5: Counting Bits. - // The following pattern shows the general approach: - // - // x = x>>1&(m0&m) + x&(m0&m) - // x = x>>2&(m1&m) + x&(m1&m) - // x = x>>4&(m2&m) + x&(m2&m) - // x = x>>8&(m3&m) + x&(m3&m) - // x = x>>16&(m4&m) + x&(m4&m) - // x = x>>32&(m5&m) + x&(m5&m) - // return int(x) - // - // Masking (& operations) can be left away when there's no - // danger that a field's sum will carry over into the next - // field: Since the result cannot be > 64, 8 bits is enough - // and we can ignore the masks for the shifts by 8 and up. - // Per "Hacker's Delight", the first line can be simplified - // more, but it saves at best one instruction, so we leave - // it alone for clarity. - const m = 1<<64 - 1 - x = x>>1&(m0&m) + x&(m0&m) - x = x>>2&(m1&m) + x&(m1&m) - x = (x>>4 + x) & (m2 & m) - x += x >> 8 - x += x >> 16 - x += x >> 32 - return int(x) & (1<<7 - 1) -} - -// --- RotateLeft --- - -// RotateLeft returns the value of x rotated left by (k mod [UintSize]) bits. -// To rotate x right by k bits, call RotateLeft(x, -k). -// -// This function's execution time does not depend on the inputs. -func RotateLeft(x uint, k int) uint { - if UintSize == 32 { - return uint(RotateLeft32(uint32(x), k)) - } - return uint(RotateLeft64(uint64(x), k)) -} - -// RotateLeft8 returns the value of x rotated left by (k mod 8) bits. -// To rotate x right by k bits, call RotateLeft8(x, -k). -// -// This function's execution time does not depend on the inputs. -func RotateLeft8(x uint8, k int) uint8 { - const n = 8 - s := uint(k) & (n - 1) - return x<>(n-s) -} - -// RotateLeft16 returns the value of x rotated left by (k mod 16) bits. -// To rotate x right by k bits, call RotateLeft16(x, -k). -// -// This function's execution time does not depend on the inputs. -func RotateLeft16(x uint16, k int) uint16 { - const n = 16 - s := uint(k) & (n - 1) - return x<>(n-s) -} - -// RotateLeft32 returns the value of x rotated left by (k mod 32) bits. -// To rotate x right by k bits, call RotateLeft32(x, -k). -// -// This function's execution time does not depend on the inputs. -func RotateLeft32(x uint32, k int) uint32 { - const n = 32 - s := uint(k) & (n - 1) - return x<>(n-s) -} - -// RotateLeft64 returns the value of x rotated left by (k mod 64) bits. -// To rotate x right by k bits, call RotateLeft64(x, -k). -// -// This function's execution time does not depend on the inputs. -func RotateLeft64(x uint64, k int) uint64 { - const n = 64 - s := uint(k) & (n - 1) - return x<>(n-s) -} - -// --- Reverse --- - -// Reverse returns the value of x with its bits in reversed order. -func Reverse(x uint) uint { - if UintSize == 32 { - return uint(Reverse32(uint32(x))) - } - return uint(Reverse64(uint64(x))) -} - -// Reverse8 returns the value of x with its bits in reversed order. -func Reverse8(x uint8) uint8 { - return rev8tab[x] -} - -// Reverse16 returns the value of x with its bits in reversed order. -func Reverse16(x uint16) uint16 { - return uint16(rev8tab[x>>8]) | uint16(rev8tab[x&0xff])<<8 -} - -// Reverse32 returns the value of x with its bits in reversed order. -func Reverse32(x uint32) uint32 { - const m = 1<<32 - 1 - x = x>>1&(m0&m) | x&(m0&m)<<1 - x = x>>2&(m1&m) | x&(m1&m)<<2 - x = x>>4&(m2&m) | x&(m2&m)<<4 - return ReverseBytes32(x) -} - -// Reverse64 returns the value of x with its bits in reversed order. -func Reverse64(x uint64) uint64 { - const m = 1<<64 - 1 - x = x>>1&(m0&m) | x&(m0&m)<<1 - x = x>>2&(m1&m) | x&(m1&m)<<2 - x = x>>4&(m2&m) | x&(m2&m)<<4 - return ReverseBytes64(x) -} - -// --- ReverseBytes --- - -// ReverseBytes returns the value of x with its bytes in reversed order. -// -// This function's execution time does not depend on the inputs. -func ReverseBytes(x uint) uint { - if UintSize == 32 { - return uint(ReverseBytes32(uint32(x))) - } - return uint(ReverseBytes64(uint64(x))) -} - -// ReverseBytes16 returns the value of x with its bytes in reversed order. -// -// This function's execution time does not depend on the inputs. -func ReverseBytes16(x uint16) uint16 { - return x>>8 | x<<8 -} - -// ReverseBytes32 returns the value of x with its bytes in reversed order. -// -// This function's execution time does not depend on the inputs. -func ReverseBytes32(x uint32) uint32 { - const m = 1<<32 - 1 - x = x>>8&(m3&m) | x&(m3&m)<<8 - return x>>16 | x<<16 -} - -// ReverseBytes64 returns the value of x with its bytes in reversed order. -// -// This function's execution time does not depend on the inputs. -func ReverseBytes64(x uint64) uint64 { - const m = 1<<64 - 1 - x = x>>8&(m3&m) | x&(m3&m)<<8 - x = x>>16&(m4&m) | x&(m4&m)<<16 - return x>>32 | x<<32 -} - -// --- Len --- - -// Len returns the minimum number of bits required to represent x; the result is 0 for x == 0. -func Len(x uint) int { - if UintSize == 32 { - return Len32(uint32(x)) - } - return Len64(uint64(x)) -} - -// Len8 returns the minimum number of bits required to represent x; the result is 0 for x == 0. -func Len8(x uint8) int { - return int(len8tab[x]) -} - -// Len16 returns the minimum number of bits required to represent x; the result is 0 for x == 0. -func Len16(x uint16) (n int) { - if x >= 1<<8 { - x >>= 8 - n = 8 - } - return n + int(len8tab[x]) -} - -// Len32 returns the minimum number of bits required to represent x; the result is 0 for x == 0. -func Len32(x uint32) (n int) { - if x >= 1<<16 { - x >>= 16 - n = 16 - } - if x >= 1<<8 { - x >>= 8 - n += 8 - } - return n + int(len8tab[x]) -} - -// Len64 returns the minimum number of bits required to represent x; the result is 0 for x == 0. -func Len64(x uint64) (n int) { - if x >= 1<<32 { - x >>= 32 - n = 32 - } - if x >= 1<<16 { - x >>= 16 - n += 16 - } - if x >= 1<<8 { - x >>= 8 - n += 8 - } - return n + int(len8tab[x]) -} - -// --- Add with carry --- - -// Add returns the sum with carry of x, y and carry: sum = x + y + carry. -// The carry input must be 0 or 1; otherwise the behavior is undefined. -// The carryOut output is guaranteed to be 0 or 1. -// -// This function's execution time does not depend on the inputs. -func Add(x, y, carry uint) (sum, carryOut uint) { - if UintSize == 32 { - s32, c32 := Add32(uint32(x), uint32(y), uint32(carry)) - return uint(s32), uint(c32) - } - s64, c64 := Add64(uint64(x), uint64(y), uint64(carry)) - return uint(s64), uint(c64) -} - -// Add32 returns the sum with carry of x, y and carry: sum = x + y + carry. -// The carry input must be 0 or 1; otherwise the behavior is undefined. -// The carryOut output is guaranteed to be 0 or 1. -// -// This function's execution time does not depend on the inputs. -func Add32(x, y, carry uint32) (sum, carryOut uint32) { - sum64 := uint64(x) + uint64(y) + uint64(carry) - sum = uint32(sum64) - carryOut = uint32(sum64 >> 32) - return -} - -// Add64 returns the sum with carry of x, y and carry: sum = x + y + carry. -// The carry input must be 0 or 1; otherwise the behavior is undefined. -// The carryOut output is guaranteed to be 0 or 1. -// -// This function's execution time does not depend on the inputs. -func Add64(x, y, carry uint64) (sum, carryOut uint64) { - sum = x + y + carry - // The sum will overflow if both top bits are set (x & y) or if one of them - // is (x | y), and a carry from the lower place happened. If such a carry - // happens, the top bit will be 1 + 0 + 1 = 0 (&^ sum). - carryOut = ((x & y) | ((x | y) &^ sum)) >> 63 - return -} - -// --- Subtract with borrow --- - -// Sub returns the difference of x, y and borrow: diff = x - y - borrow. -// The borrow input must be 0 or 1; otherwise the behavior is undefined. -// The borrowOut output is guaranteed to be 0 or 1. -// -// This function's execution time does not depend on the inputs. -func Sub(x, y, borrow uint) (diff, borrowOut uint) { - if UintSize == 32 { - d32, b32 := Sub32(uint32(x), uint32(y), uint32(borrow)) - return uint(d32), uint(b32) - } - d64, b64 := Sub64(uint64(x), uint64(y), uint64(borrow)) - return uint(d64), uint(b64) -} - -// Sub32 returns the difference of x, y and borrow, diff = x - y - borrow. -// The borrow input must be 0 or 1; otherwise the behavior is undefined. -// The borrowOut output is guaranteed to be 0 or 1. -// -// This function's execution time does not depend on the inputs. -func Sub32(x, y, borrow uint32) (diff, borrowOut uint32) { - diff = x - y - borrow - // The difference will underflow if the top bit of x is not set and the top - // bit of y is set (^x & y) or if they are the same (^(x ^ y)) and a borrow - // from the lower place happens. If that borrow happens, the result will be - // 1 - 1 - 1 = 0 - 0 - 1 = 1 (& diff). - borrowOut = ((^x & y) | (^(x ^ y) & diff)) >> 31 - return -} - -// Sub64 returns the difference of x, y and borrow: diff = x - y - borrow. -// The borrow input must be 0 or 1; otherwise the behavior is undefined. -// The borrowOut output is guaranteed to be 0 or 1. -// -// This function's execution time does not depend on the inputs. -func Sub64(x, y, borrow uint64) (diff, borrowOut uint64) { - diff = x - y - borrow - // See Sub32 for the bit logic. - borrowOut = ((^x & y) | (^(x ^ y) & diff)) >> 63 - return -} - -// --- Full-width multiply --- - -// Mul returns the full-width product of x and y: (hi, lo) = x * y -// with the product bits' upper half returned in hi and the lower -// half returned in lo. -// -// This function's execution time does not depend on the inputs. -func Mul(x, y uint) (hi, lo uint) { - if UintSize == 32 { - h, l := Mul32(uint32(x), uint32(y)) - return uint(h), uint(l) - } - h, l := Mul64(uint64(x), uint64(y)) - return uint(h), uint(l) -} - -// Mul32 returns the 64-bit product of x and y: (hi, lo) = x * y -// with the product bits' upper half returned in hi and the lower -// half returned in lo. -// -// This function's execution time does not depend on the inputs. -func Mul32(x, y uint32) (hi, lo uint32) { - tmp := uint64(x) * uint64(y) - hi, lo = uint32(tmp>>32), uint32(tmp) - return -} - -// Mul64 returns the 128-bit product of x and y: (hi, lo) = x * y -// with the product bits' upper half returned in hi and the lower -// half returned in lo. -// -// This function's execution time does not depend on the inputs. -func Mul64(x, y uint64) (hi, lo uint64) { - const mask32 = 1<<32 - 1 - x0 := x & mask32 - x1 := x >> 32 - y0 := y & mask32 - y1 := y >> 32 - w0 := x0 * y0 - t := x1*y0 + w0>>32 - w1 := t & mask32 - w2 := t >> 32 - w1 += x0 * y1 - hi = x1*y1 + w2 + w1>>32 - lo = x * y - return -} - -// --- Full-width divide --- - -// Div returns the quotient and remainder of (hi, lo) divided by y: -// quo = (hi, lo)/y, rem = (hi, lo)%y with the dividend bits' upper -// half in parameter hi and the lower half in parameter lo. -// Div panics for y == 0 (division by zero) or y <= hi (quotient overflow). -func Div(hi, lo, y uint) (quo, rem uint) { - if UintSize == 32 { - q, r := Div32(uint32(hi), uint32(lo), uint32(y)) - return uint(q), uint(r) - } - q, r := Div64(uint64(hi), uint64(lo), uint64(y)) - return uint(q), uint(r) -} - -// Div32 returns the quotient and remainder of (hi, lo) divided by y: -// quo = (hi, lo)/y, rem = (hi, lo)%y with the dividend bits' upper -// half in parameter hi and the lower half in parameter lo. -// Div32 panics for y == 0 (division by zero) or y <= hi (quotient overflow). -func Div32(hi, lo, y uint32) (quo, rem uint32) { - if y != 0 && y <= hi { - panic(overflowError) - } - z := uint64(hi)<<32 | uint64(lo) - quo, rem = uint32(z/uint64(y)), uint32(z%uint64(y)) - return -} - -// Div64 returns the quotient and remainder of (hi, lo) divided by y: -// quo = (hi, lo)/y, rem = (hi, lo)%y with the dividend bits' upper -// half in parameter hi and the lower half in parameter lo. -// Div64 panics for y == 0 (division by zero) or y <= hi (quotient overflow). -func Div64(hi, lo, y uint64) (quo, rem uint64) { - if y == 0 { - panic(divideError) - } - if y <= hi { - panic(overflowError) - } - - // If high part is zero, we can directly return the results. - if hi == 0 { - return lo / y, lo % y - } - - s := uint(LeadingZeros64(y)) - y <<= s - - const ( - two32 = 1 << 32 - mask32 = two32 - 1 - ) - yn1 := y >> 32 - yn0 := y & mask32 - un32 := hi<>(64-s) - un10 := lo << s - un1 := un10 >> 32 - un0 := un10 & mask32 - q1 := un32 / yn1 - rhat := un32 - q1*yn1 - - for q1 >= two32 || q1*yn0 > two32*rhat+un1 { - q1-- - rhat += yn1 - if rhat >= two32 { - break - } - } - - un21 := un32*two32 + un1 - q1*y - q0 := un21 / yn1 - rhat = un21 - q0*yn1 - - for q0 >= two32 || q0*yn0 > two32*rhat+un0 { - q0-- - rhat += yn1 - if rhat >= two32 { - break - } - } - - return q1*two32 + q0, (un21*two32 + un0 - q0*y) >> s -} - -// Rem returns the remainder of (hi, lo) divided by y. Rem panics for -// y == 0 (division by zero) but, unlike Div, it doesn't panic on a -// quotient overflow. -func Rem(hi, lo, y uint) uint { - if UintSize == 32 { - return uint(Rem32(uint32(hi), uint32(lo), uint32(y))) - } - return uint(Rem64(uint64(hi), uint64(lo), uint64(y))) -} - -// Rem32 returns the remainder of (hi, lo) divided by y. Rem32 panics -// for y == 0 (division by zero) but, unlike [Div32], it doesn't panic -// on a quotient overflow. -func Rem32(hi, lo, y uint32) uint32 { - return uint32((uint64(hi)<<32 | uint64(lo)) % uint64(y)) -} - -// Rem64 returns the remainder of (hi, lo) divided by y. Rem64 panics -// for y == 0 (division by zero) but, unlike [Div64], it doesn't panic -// on a quotient overflow. -func Rem64(hi, lo, y uint64) uint64 { - // We scale down hi so that hi < y, then use Div64 to compute the - // rem with the guarantee that it won't panic on quotient overflow. - // Given that - // hi ≡ hi%y (mod y) - // we have - // hi<<64 + lo ≡ (hi%y)<<64 + lo (mod y) - _, rem := Div64(hi%y, lo, y) - return rem -} \ No newline at end of file diff --git a/u256/bits_errors.gno b/u256/bits_errors.gno deleted file mode 100644 index 30b8ae33..00000000 --- a/u256/bits_errors.gno +++ /dev/null @@ -1,17 +0,0 @@ -// Copyright 2019 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build !compiler_bootstrap - -package u256 - -import ( - "errors" -) - -//go:linkname overflowError runtime.overflowError -var overflowError error = errors.New("u256: integer overflow") - -//go:linkname divideError runtime.divideError -var divideError error = errors.New("u256: integer divide by zero") \ No newline at end of file diff --git a/u256/bits_table.gno b/u256/bits_table.gno deleted file mode 100644 index 4d7c5397..00000000 --- a/u256/bits_table.gno +++ /dev/null @@ -1,79 +0,0 @@ -// Copyright 2017 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// Code generated by go run make_tables.go. DO NOT EDIT. - -package u256 - -const ntz8tab = "" + - "\x08\x00\x01\x00\x02\x00\x01\x00\x03\x00\x01\x00\x02\x00\x01\x00" + - "\x04\x00\x01\x00\x02\x00\x01\x00\x03\x00\x01\x00\x02\x00\x01\x00" + - "\x05\x00\x01\x00\x02\x00\x01\x00\x03\x00\x01\x00\x02\x00\x01\x00" + - "\x04\x00\x01\x00\x02\x00\x01\x00\x03\x00\x01\x00\x02\x00\x01\x00" + - "\x06\x00\x01\x00\x02\x00\x01\x00\x03\x00\x01\x00\x02\x00\x01\x00" + - "\x04\x00\x01\x00\x02\x00\x01\x00\x03\x00\x01\x00\x02\x00\x01\x00" + - "\x05\x00\x01\x00\x02\x00\x01\x00\x03\x00\x01\x00\x02\x00\x01\x00" + - "\x04\x00\x01\x00\x02\x00\x01\x00\x03\x00\x01\x00\x02\x00\x01\x00" + - "\x07\x00\x01\x00\x02\x00\x01\x00\x03\x00\x01\x00\x02\x00\x01\x00" + - "\x04\x00\x01\x00\x02\x00\x01\x00\x03\x00\x01\x00\x02\x00\x01\x00" + - "\x05\x00\x01\x00\x02\x00\x01\x00\x03\x00\x01\x00\x02\x00\x01\x00" + - "\x04\x00\x01\x00\x02\x00\x01\x00\x03\x00\x01\x00\x02\x00\x01\x00" + - "\x06\x00\x01\x00\x02\x00\x01\x00\x03\x00\x01\x00\x02\x00\x01\x00" + - "\x04\x00\x01\x00\x02\x00\x01\x00\x03\x00\x01\x00\x02\x00\x01\x00" + - "\x05\x00\x01\x00\x02\x00\x01\x00\x03\x00\x01\x00\x02\x00\x01\x00" + - "\x04\x00\x01\x00\x02\x00\x01\x00\x03\x00\x01\x00\x02\x00\x01\x00" - -const pop8tab = "" + - "\x00\x01\x01\x02\x01\x02\x02\x03\x01\x02\x02\x03\x02\x03\x03\x04" + - "\x01\x02\x02\x03\x02\x03\x03\x04\x02\x03\x03\x04\x03\x04\x04\x05" + - "\x01\x02\x02\x03\x02\x03\x03\x04\x02\x03\x03\x04\x03\x04\x04\x05" + - "\x02\x03\x03\x04\x03\x04\x04\x05\x03\x04\x04\x05\x04\x05\x05\x06" + - "\x01\x02\x02\x03\x02\x03\x03\x04\x02\x03\x03\x04\x03\x04\x04\x05" + - "\x02\x03\x03\x04\x03\x04\x04\x05\x03\x04\x04\x05\x04\x05\x05\x06" + - "\x02\x03\x03\x04\x03\x04\x04\x05\x03\x04\x04\x05\x04\x05\x05\x06" + - "\x03\x04\x04\x05\x04\x05\x05\x06\x04\x05\x05\x06\x05\x06\x06\x07" + - "\x01\x02\x02\x03\x02\x03\x03\x04\x02\x03\x03\x04\x03\x04\x04\x05" + - "\x02\x03\x03\x04\x03\x04\x04\x05\x03\x04\x04\x05\x04\x05\x05\x06" + - "\x02\x03\x03\x04\x03\x04\x04\x05\x03\x04\x04\x05\x04\x05\x05\x06" + - "\x03\x04\x04\x05\x04\x05\x05\x06\x04\x05\x05\x06\x05\x06\x06\x07" + - "\x02\x03\x03\x04\x03\x04\x04\x05\x03\x04\x04\x05\x04\x05\x05\x06" + - "\x03\x04\x04\x05\x04\x05\x05\x06\x04\x05\x05\x06\x05\x06\x06\x07" + - "\x03\x04\x04\x05\x04\x05\x05\x06\x04\x05\x05\x06\x05\x06\x06\x07" + - "\x04\x05\x05\x06\x05\x06\x06\x07\x05\x06\x06\x07\x06\x07\x07\x08" - -const rev8tab = "" + - "\x00\x80\x40\xc0\x20\xa0\x60\xe0\x10\x90\x50\xd0\x30\xb0\x70\xf0" + - "\x08\x88\x48\xc8\x28\xa8\x68\xe8\x18\x98\x58\xd8\x38\xb8\x78\xf8" + - "\x04\x84\x44\xc4\x24\xa4\x64\xe4\x14\x94\x54\xd4\x34\xb4\x74\xf4" + - "\x0c\x8c\x4c\xcc\x2c\xac\x6c\xec\x1c\x9c\x5c\xdc\x3c\xbc\x7c\xfc" + - "\x02\x82\x42\xc2\x22\xa2\x62\xe2\x12\x92\x52\xd2\x32\xb2\x72\xf2" + - "\x0a\x8a\x4a\xca\x2a\xaa\x6a\xea\x1a\x9a\x5a\xda\x3a\xba\x7a\xfa" + - "\x06\x86\x46\xc6\x26\xa6\x66\xe6\x16\x96\x56\xd6\x36\xb6\x76\xf6" + - "\x0e\x8e\x4e\xce\x2e\xae\x6e\xee\x1e\x9e\x5e\xde\x3e\xbe\x7e\xfe" + - "\x01\x81\x41\xc1\x21\xa1\x61\xe1\x11\x91\x51\xd1\x31\xb1\x71\xf1" + - "\x09\x89\x49\xc9\x29\xa9\x69\xe9\x19\x99\x59\xd9\x39\xb9\x79\xf9" + - "\x05\x85\x45\xc5\x25\xa5\x65\xe5\x15\x95\x55\xd5\x35\xb5\x75\xf5" + - "\x0d\x8d\x4d\xcd\x2d\xad\x6d\xed\x1d\x9d\x5d\xdd\x3d\xbd\x7d\xfd" + - "\x03\x83\x43\xc3\x23\xa3\x63\xe3\x13\x93\x53\xd3\x33\xb3\x73\xf3" + - "\x0b\x8b\x4b\xcb\x2b\xab\x6b\xeb\x1b\x9b\x5b\xdb\x3b\xbb\x7b\xfb" + - "\x07\x87\x47\xc7\x27\xa7\x67\xe7\x17\x97\x57\xd7\x37\xb7\x77\xf7" + - "\x0f\x8f\x4f\xcf\x2f\xaf\x6f\xef\x1f\x9f\x5f\xdf\x3f\xbf\x7f\xff" - -const len8tab = "" + - "\x00\x01\x02\x02\x03\x03\x03\x03\x04\x04\x04\x04\x04\x04\x04\x04" + - "\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05" + - "\x06\x06\x06\x06\x06\x06\x06\x06\x06\x06\x06\x06\x06\x06\x06\x06" + - "\x06\x06\x06\x06\x06\x06\x06\x06\x06\x06\x06\x06\x06\x06\x06\x06" + - "\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07" + - "\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07" + - "\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07" + - "\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07" + - "\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08" + - "\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08" + - "\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08" + - "\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08" + - "\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08" + - "\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08" + - "\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08" + - "\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08" \ No newline at end of file diff --git a/u256/gno.mod b/u256/gno.mod deleted file mode 100644 index 749a02f5..00000000 --- a/u256/gno.mod +++ /dev/null @@ -1 +0,0 @@ -module gno.land/p/u256 \ No newline at end of file diff --git a/u256/i256.gno b/u256/i256.gno deleted file mode 100644 index 3db2f8cf..00000000 --- a/u256/i256.gno +++ /dev/null @@ -1,253 +0,0 @@ -package u256 - -// signed integer wrapper - -type Int struct { - v Uint -} - -func NewInt(v int64) *Int { - if v >= 0 { - return &Int{v: *NewUint(uint64(v))} - } - return &Int{ - v: Uint{ - arr: [4]uint64{ - uint64(v), // bit preserving cast, little endian - 0xffffffffffffffff, - 0xffffffffffffffff, - 0xffffffffffffffff, - }, - }, - } -} - -func IntFromBigint(v bigint) *Int { - if v > MaxUint256/2-1 { - panic("I256 IntFromBigint overflow") - } - if v < -MaxUint256/2 { - panic("I256 IntFromBigint underflow") - } - - if v >= 0 { - return &Int{v: *FromBigint(v)} - } else { - var tmp Int - tmp.v = *FromBigint(-v) - tmp.Neg() - return &tmp - } - - panic("I256 IntFromBigint not implemented") -} - -func (x *Int) Bigint() bigint { - if x.Signum() < 0 { - return -x.Neg().v.Bigint() - } - return x.v.Bigint() - -} - -func (x *Int) IsNeg() bool { - return x.Signum() < 0 -} - -func (x *Int) Add(y *Int, z *Int) *Int { - x.v.Add(&y.v, &z.v) - - ys := y.Signum() - zs := z.Signum() - - if ys > 0 && zs > 0 && x.Signum() < 0 { - panic("I256 Add overflow") - } - - if ys < 0 && zs < 0 && x.Signum() > 0 { - panic("I256 Add underflow") - } - - return x -} - -func (x *Int) Sub(y *Int, z *Int) *Int { - x.v.UnsafeSub(&y.v, &z.v) - - ys := y.Signum() - zs := z.Signum() - - if ys > 0 && zs < 0 && x.Signum() < 0 { - panic("I256 Sub overflow") - } - - if ys < 0 && zs > 0 && x.Signum() > 0 { - panic("I256 Sub underflow") - } - - return x -} - -func (x *Int) Mul(y *Int, z *Int) *Int { - x.v.Mul(&y.v, &z.v) - - ys := y.Signum() - zs := z.Signum() - - if ys > 0 && zs > 0 && x.Signum() < 0 { - panic("I256 Mul overflow #1") - } - - if ys < 0 && zs < 0 && x.Signum() < 0 { - panic("I256 Mul overflow #2") - } - - if ys > 0 && zs < 0 && x.Signum() > 0 { - panic("I256 Mul underflow #1") - } - - if ys < 0 && zs > 0 && x.Signum() > 0 { - panic("I256 Mul underflow #2") - } - - return x -} - -func (x *Int) Lsh(y *Int, n uint) *Int { - x.v.Lsh(&y.v, n) - return x -} - -func (x *Int) Rsh(y *Int, n uint) *Int { - x.v.Rsh(&y.v, n) - return x -} - -func (x *Int) Eq(y *Int) bool { - return x.v.Eq(&y.v) -} - -func (x *Int) IsZero() bool { - return x.v.IsZero() -} - -func (x *Int) Signum() int { - if x.v.arr[3] == 0 && x.v.arr[2] == 0 && x.v.arr[1] == 0 && x.v.arr[0] == 0 { - return 0 - } - if x.v.arr[3] < 0x8000000000000000 { - return 1 - } - return -1 -} - -func (x *Int) Gt(y *Int) bool { - xs := x.Signum() - ys := y.Signum() - - if xs != ys { - return xs > ys - } - if xs == 0 { - return false - } - if xs > 0 { - return x.v.Gt(&y.v) - } - return y.v.Gt(&x.v) -} - -func (x *Int) Lte(y *Int) bool { - return !x.Gt(y) -} - -func (x *Int) Gte(y *Int) bool { - xs := x.Signum() - ys := y.Signum() - - if xs != ys { - return xs > ys - } - if xs == 0 { - return true - } - if xs > 0 { - return x.v.Gte(&y.v) - } - return y.v.Gte(&x.v) -} - -func (x *Int) Int64() int64 { - // TODO: overflow check - if x.v.arr[3] < 0x8000000000000000 { - return int64(x.v.arr[0]) - } - // TODO: check if this is correct - return -int64(^x.v.arr[0] + 1) -} - -func (x *Int) Abs() *Uint { - if x.Signum() > 0 { - return &x.v - } - x1 := &Int{v: x.v} // so that we don't modify x - return &x1.Neg().v -} - -func (x *Int) Neg() *Int { - if x.Signum() == 0 { - return x - } - - // twos complement - x.v.Not(&x.v) - x.v.Add(&x.v, &Uint{arr: [4]uint64{1, 0, 0, 0}}) - return x -} - -func (x *Int) Dec() string { - if x.Signum() < 0 { - return "-" + x.Abs().Dec() - } - return x.Abs().Dec() -} - -func (x *Int) Uint() *Uint { - if x.Signum() < 0 { - // panic("I256 Uint negative") - return &x.Neg().v // r3v4_xxx: safe ?? - } - return &x.v -} - -func (z *Int) Or(x, y *Int) *Int { - z.v.Or(&x.v, &y.v) - return z -} - -func (z *Int) NilToZero() *Int { - if z == nil { - z = NewInt(0) - } - - return z -} - -// Clone creates a new Int identical to z -func (z *Int) Clone() *Int { - var x Int - - x.Sub(z, NewInt(0)) - return &x -} - -// // Clone creates a new Int identical to z -// func (z *Uint) Clone() *Uint { -// var x Uint -// x.arr[0] = z.arr[0] -// x.arr[1] = z.arr[1] -// x.arr[2] = z.arr[2] -// x.arr[3] = z.arr[3] - -// return &x -// } diff --git a/u256/runtest.gno b/u256/runtest.gno deleted file mode 100644 index 96e32847..00000000 --- a/u256/runtest.gno +++ /dev/null @@ -1,6 +0,0 @@ -package u256 - -func Hello() uint64 { - x := NewUint(1) - return x.Uint64() -} diff --git a/u256/strconv.gno b/u256/strconv.gno deleted file mode 100644 index e4485762..00000000 --- a/u256/strconv.gno +++ /dev/null @@ -1,203 +0,0 @@ -// Copyright 2009 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package u256 - -const fastSmalls = true // enable fast path for small integers - -// FormatUint returns the string representation of i in the given base, -// for 2 <= base <= 36. The result uses the lower-case letters 'a' to 'z' -// for digit values >= 10. -func FormatUint(i uint64, base int) string { - if fastSmalls && i < nSmalls && base == 10 { - return small(int(i)) - } - _, s := formatBits(nil, i, base, false, false) - return s -} - -// FormatInt returns the string representation of i in the given base, -// for 2 <= base <= 36. The result uses the lower-case letters 'a' to 'z' -// for digit values >= 10. -func FormatInt(i int64, base int) string { - if fastSmalls && 0 <= i && i < nSmalls && base == 10 { - return small(int(i)) - } - _, s := formatBits(nil, uint64(i), base, i < 0, false) - return s -} - -// Itoa is equivalent to FormatInt(int64(i), 10). -func Itoa(i int) string { - return FormatInt(int64(i), 10) -} - -// AppendInt appends the string form of the integer i, -// as generated by FormatInt, to dst and returns the extended buffer. -func AppendInt(dst []byte, i int64, base int) []byte { - if fastSmalls && 0 <= i && i < nSmalls && base == 10 { - return append(dst, small(int(i))...) - } - dst, _ = formatBits(dst, uint64(i), base, i < 0, true) - return dst -} - -// AppendUint appends the string form of the unsigned integer i, -// as generated by FormatUint, to dst and returns the extended buffer. -func AppendUint(dst []byte, i uint64, base int) []byte { - if fastSmalls && i < nSmalls && base == 10 { - return append(dst, small(int(i))...) - } - dst, _ = formatBits(dst, i, base, false, true) - return dst -} - -// small returns the string for an i with 0 <= i < nSmalls. -func small(i int) string { - if i < 10 { - return digits[i : i+1] - } - return smallsString[i*2 : i*2+2] -} - -const nSmalls = 100 - -const smallsString = "00010203040506070809" + - "10111213141516171819" + - "20212223242526272829" + - "30313233343536373839" + - "40414243444546474849" + - "50515253545556575859" + - "60616263646566676869" + - "70717273747576777879" + - "80818283848586878889" + - "90919293949596979899" - -const host32bit = ^uint(0)>>32 == 0 - -const digits = "0123456789abcdefghijklmnopqrstuvwxyz" - -// formatBits computes the string representation of u in the given base. -// If neg is set, u is treated as negative int64 value. If append_ is -// set, the string is appended to dst and the resulting byte slice is -// returned as the first result value; otherwise the string is returned -// as the second result value. -func formatBits(dst []byte, u uint64, base int, neg, append_ bool) (d []byte, s string) { - if base < 2 || base > len(digits) { - panic("strconv: illegal AppendInt/FormatInt base") - } - // 2 <= base && base <= len(digits) - - var a [64 + 1]byte // +1 for sign of 64bit value in base 2 - i := len(a) - - if neg { - u = -u - } - - // convert bits - // We use uint values where we can because those will - // fit into a single register even on a 32bit machine. - if base == 10 { - // common case: use constants for / because - // the compiler can optimize it into a multiply+shift - - if host32bit { - // convert the lower digits using 32bit operations - for u >= 1e9 { - // Avoid using r = a%b in addition to q = a/b - // since 64bit division and modulo operations - // are calculated by runtime functions on 32bit machines. - q := u / 1e9 - us := uint(u - q*1e9) // u % 1e9 fits into a uint - for j := 4; j > 0; j-- { - is := us % 100 * 2 - us /= 100 - i -= 2 - a[i+1] = smallsString[is+1] - a[i+0] = smallsString[is+0] - } - - // us < 10, since it contains the last digit - // from the initial 9-digit us. - i-- - a[i] = smallsString[us*2+1] - - u = q - } - // u < 1e9 - } - - // u guaranteed to fit into a uint - us := uint(u) - for us >= 100 { - is := us % 100 * 2 - us /= 100 - i -= 2 - a[i+1] = smallsString[is+1] - a[i+0] = smallsString[is+0] - } - - // us < 100 - is := us * 2 - i-- - a[i] = smallsString[is+1] - if us >= 10 { - i-- - a[i] = smallsString[is] - } - - } else if isPowerOfTwo(base) { - // Use shifts and masks instead of / and %. - // Base is a power of 2 and 2 <= base <= len(digits) where len(digits) is 36. - // The largest power of 2 below or equal to 36 is 32, which is 1 << 5; - // i.e., the largest possible shift count is 5. By &-ind that value with - // the constant 7 we tell the compiler that the shift count is always - // less than 8 which is smaller than any register width. This allows - // the compiler to generate better code for the shift operation. - shift := uint(TrailingZeros(uint(base))) & 7 - b := uint64(base) - m := uint(base) - 1 // == 1<= b { - i-- - a[i] = digits[uint(u)&m] - u >>= shift - } - // u < base - i-- - a[i] = digits[uint(u)] - } else { - // general case - b := uint64(base) - for u >= b { - i-- - // Avoid using r = a%b in addition to q = a/b - // since 64bit division and modulo operations - // are calculated by runtime functions on 32bit machines. - q := u / b - a[i] = digits[uint(u-q*b)] - u = q - } - // u < base - i-- - a[i] = digits[uint(u)] - } - - // add sign, if any - if neg { - i-- - a[i] = '-' - } - - if append_ { - d = append(dst, a[i:]...) - return - } - s = string(a[i:]) - return -} - -func isPowerOfTwo(x int) bool { - return x&(x-1) == 0 -} diff --git a/u256/u256.gno b/u256/u256.gno deleted file mode 100644 index 21cc9714..00000000 --- a/u256/u256.gno +++ /dev/null @@ -1,1241 +0,0 @@ -// Ported from https://github.com/holiman/uint256/ - -package u256 - -import ( - "errors" -) - -const MaxUint64 = 1<<64 - 1 - -// TODO: remove -const MaxUint256 bigint = 115792089237316195423570985008687907853269984665640564039457584007913129639935 - -func Zero() *Uint { - return NewUint(0) -} - -func One() *Uint { - return NewUint(1) -} - -func (x *Uint) Min(y *Uint) *Uint { - if x.Lt(y) { - return x - } - return y -} - -// Uint is represented as an array of 4 uint64, in little-endian order, -// so that Uint[3] is the most significant, and Uint[0] is the least significant -type Uint struct { - arr [4]uint64 -} - -func (x *Uint) Int() *Int { - // panic if x > MaxInt64 - if x.arr[3] > 0x7fffffffffffffff { - panic("U256 Int overflow") - } - - return &Int{v: *x} -} - -// TODO: to be removed -func FromBigint(x bigint) *Uint { - if x > MaxUint256 { - panic("U256 FromBigint overflow") - } - - if x < 0 { - panic("U256 FromBigint underflow") - } - - var z Uint - z.arr[0] = uint64(x % (1 << 64)) - z.arr[1] = uint64((x >> 64) % (1 << 64)) - z.arr[2] = uint64((x >> 128) % (1 << 64)) - z.arr[3] = uint64((x >> 192) % (1 << 64)) - - return &z -} - -func (x *Uint) Bigint() bigint { - return (bigint(x.arr[0]) + - bigint(x.arr[1])*(1<<64) + - bigint(x.arr[2])*(1<<128) + - bigint(x.arr[3])*(1<<192)) -} - -// NewUint returns a new initialized Uint. -func NewUint(val uint64) *Uint { - z := &Uint{arr: [4]uint64{val, 0, 0, 0}} - return z -} - -// Uint64 returns the lower 64-bits of z -func (z *Uint) Uint64() uint64 { - return z.arr[0] -} - -func (z *Uint) Int32() int32 { - x := z.arr[0] - if x > 0x7fffffff { - panic("U256 Int32 overflow") - } - return int32(x) -} - -// SetUint64 sets z to the value x -func (z *Uint) SetUint64(x uint64) *Uint { - z.arr[3], z.arr[2], z.arr[1], z.arr[0] = 0, 0, 0, x - return z -} - -// IsUint64 reports whether z can be represented as a uint64. -func (z *Uint) IsUint64() bool { - return (z.arr[1] | z.arr[2] | z.arr[3]) == 0 -} - -// IsZero returns true if z == 0 -func (z *Uint) IsZero() bool { - return (z.arr[0] | z.arr[1] | z.arr[2] | z.arr[3]) == 0 -} - -// Clear sets z to 0 -func (z *Uint) Clear() *Uint { - z.arr[3], z.arr[2], z.arr[1], z.arr[0] = 0, 0, 0, 0 - return z -} - -// SetAllOne sets all the bits of z to 1 -func (z *Uint) SetAllOne() *Uint { - z.arr[3], z.arr[2], z.arr[1], z.arr[0] = MaxUint64, MaxUint64, MaxUint64, MaxUint64 - return z -} - -// Not sets z = ^x and returns z. -func (z *Uint) Not(x *Uint) *Uint { - z.arr[3], z.arr[2], z.arr[1], z.arr[0] = ^x.arr[3], ^x.arr[2], ^x.arr[1], ^x.arr[0] - return z -} - -// Gt returns true if z > x -func (z *Uint) Gt(x *Uint) bool { - return x.Lt(z) -} - -func (z *Uint) Gte(x *Uint) bool { - return !z.Lt(x) -} - -func (z *Uint) Lte(x *Uint) bool { - return !x.Gt(z) -} - -// Lt returns true if z < x -func (z *Uint) Lt(x *Uint) bool { - // z < x <=> z - x < 0 i.e. when subtraction overflows. - _, carry := Sub64(z.arr[0], x.arr[0], 0) - _, carry = Sub64(z.arr[1], x.arr[1], carry) - _, carry = Sub64(z.arr[2], x.arr[2], carry) - _, carry = Sub64(z.arr[3], x.arr[3], carry) - return carry != 0 -} - -// Eq returns true if z == x -func (z *Uint) Eq(x *Uint) bool { - return (z.arr[0] == x.arr[0]) && (z.arr[1] == x.arr[1]) && (z.arr[2] == x.arr[2]) && (z.arr[3] == x.arr[3]) -} - -// Cmp compares z and x and returns: -// -// -1 if z < x -// 0 if z == x -// +1 if z > x -func (z *Uint) Cmp(x *Uint) (r int) { - // z < x <=> z - x < 0 i.e. when subtraction overflows. - d0, carry := Sub64(z.arr[0], x.arr[0], 0) - d1, carry := Sub64(z.arr[1], x.arr[1], carry) - d2, carry := Sub64(z.arr[2], x.arr[2], carry) - d3, carry := Sub64(z.arr[3], x.arr[3], carry) - if carry == 1 { - return -1 - } - if d0|d1|d2|d3 == 0 { - return 0 - } - return 1 -} - -// Set sets z to x and returns z. -func (z *Uint) Set(x *Uint) *Uint { - *z = *x - - return z -} - -// SetOne sets z to 1 -func (z *Uint) SetOne() *Uint { - z.arr[3], z.arr[2], z.arr[1], z.arr[0] = 0, 0, 0, 1 - return z -} - -func (z *Uint) AddInt(x *Uint, y *Int) *Uint { - if y.IsNeg() { - return z.Sub(x, y.Abs()) - } - return z.Add(x, y.Uint()) -} - -// Add sets z to the sum x+y -func (z *Uint) Add(x, y *Uint) *Uint { - var carry uint64 - z.arr[0], carry = Add64(x.arr[0], y.arr[0], 0) - z.arr[1], carry = Add64(x.arr[1], y.arr[1], carry) - z.arr[2], carry = Add64(x.arr[2], y.arr[2], carry) - z.arr[3], _ = Add64(x.arr[3], y.arr[3], carry) - // Different from the original implementation! - // We panic on overflow - if carry != 0 { - panic("U256 Add overflow") - } - return z -} - -// AddOverflow sets z to the sum x+y, and returns z and whether overflow occurred -func (z *Uint) AddOverflow(x, y *Uint) (*Uint, bool) { - var carry uint64 - z.arr[0], carry = Add64(x.arr[0], y.arr[0], 0) - z.arr[1], carry = Add64(x.arr[1], y.arr[1], carry) - z.arr[2], carry = Add64(x.arr[2], y.arr[2], carry) - z.arr[3], carry = Add64(x.arr[3], y.arr[3], carry) - return z, carry != 0 -} - -// SubOverflow sets z to the difference x-y and returns z and true if the operation underflowed -func (z *Uint) SubOverflow(x, y *Uint) (*Uint, bool) { - var carry uint64 - z.arr[0], carry = Sub64(x.arr[0], y.arr[0], 0) - z.arr[1], carry = Sub64(x.arr[1], y.arr[1], carry) - z.arr[2], carry = Sub64(x.arr[2], y.arr[2], carry) - z.arr[3], carry = Sub64(x.arr[3], y.arr[3], carry) - return z, carry != 0 -} - -// Sub sets z to the difference x-y -func (z *Uint) Sub(x, y *Uint) *Uint { - var carry uint64 - z.arr[0], carry = Sub64(x.arr[0], y.arr[0], 0) - z.arr[1], carry = Sub64(x.arr[1], y.arr[1], carry) - z.arr[2], carry = Sub64(x.arr[2], y.arr[2], carry) - z.arr[3], _ = Sub64(x.arr[3], y.arr[3], carry) - - // Different from the original implementation! - // We panic on underflow - // r3v4 -> mconcat : why do we panic? - if carry != 0 { - panic("U256 Sub underflow") - } - return z -} - -// Sub sets z to the difference x-y -func (z *Uint) UnsafeSub(x, y *Uint) *Uint { - var carry uint64 - z.arr[0], carry = Sub64(x.arr[0], y.arr[0], 0) - z.arr[1], carry = Sub64(x.arr[1], y.arr[1], carry) - z.arr[2], carry = Sub64(x.arr[2], y.arr[2], carry) - z.arr[3], _ = Sub64(x.arr[3], y.arr[3], carry) - - return z -} - -// commented out for possible overflow -// Mul sets z to the product x*y -func (z *Uint) Mul(x, y *Uint) *Uint { - var ( - res Uint - carry uint64 - res1, res2, res3 uint64 - ) - - carry, res.arr[0] = Mul64(x.arr[0], y.arr[0]) - carry, res1 = umulHop(carry, x.arr[1], y.arr[0]) - carry, res2 = umulHop(carry, x.arr[2], y.arr[0]) - res3 = x.arr[3]*y.arr[0] + carry - - carry, res.arr[1] = umulHop(res1, x.arr[0], y.arr[1]) - carry, res2 = umulStep(res2, x.arr[1], y.arr[1], carry) - res3 = res3 + x.arr[2]*y.arr[1] + carry - - carry, res.arr[2] = umulHop(res2, x.arr[0], y.arr[2]) - res3 = res3 + x.arr[1]*y.arr[2] + carry - - res.arr[3] = res3 + x.arr[0]*y.arr[3] - - return z.Set(&res) -} - -// MulOverflow sets z to the product x*y, and returns z and whether overflow occurred -func (z *Uint) MulOverflow(x, y *Uint) (*Uint, bool) { - p := umul(x, y) - copy(z.arr[:], p[:4]) - return z, (p[4] | p[5] | p[6] | p[7]) != 0 -} - -// umulStep computes (hi * 2^64 + lo) = z + (x * y) + carry. -func umulStep(z, x, y, carry uint64) (hi, lo uint64) { - hi, lo = Mul64(x, y) - lo, carry = Add64(lo, carry, 0) - hi, _ = Add64(hi, 0, carry) - lo, carry = Add64(lo, z, 0) - hi, _ = Add64(hi, 0, carry) - return hi, lo -} - -// umulHop computes (hi * 2^64 + lo) = z + (x * y) -func umulHop(z, x, y uint64) (hi, lo uint64) { - hi, lo = Mul64(x, y) - lo, carry := Add64(lo, z, 0) - hi, _ = Add64(hi, 0, carry) - return hi, lo -} - -// umul computes full 256 x 256 -> 512 multiplication. -func umul(x, y *Uint) [8]uint64 { - var ( - res [8]uint64 - carry, carry4, carry5, carry6 uint64 - res1, res2, res3, res4, res5 uint64 - ) - - carry, res[0] = Mul64(x.arr[0], y.arr[0]) - carry, res1 = umulHop(carry, x.arr[1], y.arr[0]) - carry, res2 = umulHop(carry, x.arr[2], y.arr[0]) - carry4, res3 = umulHop(carry, x.arr[3], y.arr[0]) - - carry, res[1] = umulHop(res1, x.arr[0], y.arr[1]) - carry, res2 = umulStep(res2, x.arr[1], y.arr[1], carry) - carry, res3 = umulStep(res3, x.arr[2], y.arr[1], carry) - carry5, res4 = umulStep(carry4, x.arr[3], y.arr[1], carry) - - carry, res[2] = umulHop(res2, x.arr[0], y.arr[2]) - carry, res3 = umulStep(res3, x.arr[1], y.arr[2], carry) - carry, res4 = umulStep(res4, x.arr[2], y.arr[2], carry) - carry6, res5 = umulStep(carry5, x.arr[3], y.arr[2], carry) - - carry, res[3] = umulHop(res3, x.arr[0], y.arr[3]) - carry, res[4] = umulStep(res4, x.arr[1], y.arr[3], carry) - carry, res[5] = umulStep(res5, x.arr[2], y.arr[3], carry) - res[7], res[6] = umulStep(carry6, x.arr[3], y.arr[3], carry) - - return res -} - -// commented out for possible overflow -// Div sets z to the quotient x/y for returns z. -// If y == 0, z is set to 0 -func (z *Uint) Div(x, y *Uint) *Uint { - if y.IsZero() || y.Gt(x) { - return z.Clear() - } - if x.Eq(y) { - return z.SetOne() - } - // Shortcut some cases - if x.IsUint64() { - return z.SetUint64(x.Uint64() / y.Uint64()) - } - - // At this point, we know - // x/y ; x > y > 0 - - var quot Uint - udivrem(quot.arr[:], x.arr[:], y) - return z.Set(") -} - -// udivrem divides u by d and produces both quotient and remainder. -// The quotient is stored in provided quot - len(u)-len(d)+1 words. -// It loosely follows the Knuth's division algorithm (sometimes referenced as "schoolbook" division) using 64-bit words. -// See Knuth, Volume 2, section 4.3.1, Algorithm D. -func udivrem(quot, u []uint64, d *Uint) (rem Uint) { - var dLen int - for i := len(d.arr) - 1; i >= 0; i-- { - if d.arr[i] != 0 { - dLen = i + 1 - break - } - } - - shift := uint(LeadingZeros64(d.arr[dLen-1])) - - var dnStorage Uint - dn := dnStorage.arr[:dLen] - for i := dLen - 1; i > 0; i-- { - dn[i] = (d.arr[i] << shift) | (d.arr[i-1] >> (64 - shift)) - } - dn[0] = d.arr[0] << shift - - var uLen int - for i := len(u) - 1; i >= 0; i-- { - if u[i] != 0 { - uLen = i + 1 - break - } - } - - if uLen < dLen { - copy(rem.arr[:], u) - return rem - } - - var unStorage [9]uint64 - un := unStorage[:uLen+1] - un[uLen] = u[uLen-1] >> (64 - shift) - for i := uLen - 1; i > 0; i-- { - un[i] = (u[i] << shift) | (u[i-1] >> (64 - shift)) - } - un[0] = u[0] << shift - - // TODO: Skip the highest word of numerator if not significant. - - if dLen == 1 { - r := udivremBy1(quot, un, dn[0]) - rem.SetUint64(r >> shift) - return rem - } - - udivremKnuth(quot, un, dn) - - for i := 0; i < dLen-1; i++ { - rem.arr[i] = (un[i] >> shift) | (un[i+1] << (64 - shift)) - } - rem.arr[dLen-1] = un[dLen-1] >> shift - - return rem -} - -// udivremBy1 divides u by single normalized word d and produces both quotient and remainder. -// The quotient is stored in provided quot. -func udivremBy1(quot, u []uint64, d uint64) (rem uint64) { - reciprocal := reciprocal2by1(d) - rem = u[len(u)-1] // Set the top word as remainder. - for j := len(u) - 2; j >= 0; j-- { - quot[j], rem = udivrem2by1(rem, u[j], d, reciprocal) - } - return rem -} - -// udivremKnuth implements the division of u by normalized multiple word d from the Knuth's division algorithm. -// The quotient is stored in provided quot - len(u)-len(d) words. -// Updates u to contain the remainder - len(d) words. -func udivremKnuth(quot, u, d []uint64) { - dh := d[len(d)-1] - dl := d[len(d)-2] - reciprocal := reciprocal2by1(dh) - - for j := len(u) - len(d) - 1; j >= 0; j-- { - u2 := u[j+len(d)] - u1 := u[j+len(d)-1] - u0 := u[j+len(d)-2] - - var qhat, rhat uint64 - if u2 >= dh { // Division overflows. - qhat = ^uint64(0) - // TODO: Add "qhat one to big" adjustment (not needed for correctness, but helps avoiding "add back" case). - } else { - qhat, rhat = udivrem2by1(u2, u1, dh, reciprocal) - ph, pl := Mul64(qhat, dl) - if ph > rhat || (ph == rhat && pl > u0) { - qhat-- - // TODO: Add "qhat one to big" adjustment (not needed for correctness, but helps avoiding "add back" case). - } - } - - // Multiply and subtract. - borrow := subMulTo(u[j:], d, qhat) - u[j+len(d)] = u2 - borrow - if u2 < borrow { // Too much subtracted, add back. - qhat-- - u[j+len(d)] += addTo(u[j:], d) - } - - quot[j] = qhat // Store quotient digit. - } -} - -// isBitSet returns true if bit n-th is set, where n = 0 is LSB. -// The n must be <= 255. -func (z *Uint) isBitSet(n uint) bool { - return (z.arr[n/64] & (1 << (n % 64))) != 0 -} - -// addTo computes x += y. -// Requires len(x) >= len(y). -func addTo(x, y []uint64) uint64 { - var carry uint64 - for i := 0; i < len(y); i++ { - x[i], carry = Add64(x[i], y[i], carry) - } - return carry -} - -// subMulTo computes x -= y * multiplier. -// Requires len(x) >= len(y). -func subMulTo(x, y []uint64, multiplier uint64) uint64 { - var borrow uint64 - for i := 0; i < len(y); i++ { - s, carry1 := Sub64(x[i], borrow, 0) - ph, pl := Mul64(y[i], multiplier) - t, carry2 := Sub64(s, pl, 0) - x[i] = t - borrow = ph + carry1 + carry2 - } - return borrow -} - -// reciprocal2by1 computes <^d, ^0> / d. -func reciprocal2by1(d uint64) uint64 { - reciprocal, _ := Div64(^d, ^uint64(0), d) - return reciprocal -} - -// udivrem2by1 divides / d and produces both quotient and remainder. -// It uses the provided d's reciprocal. -// Implementation ported from https://github.com/chfast/intx and is based on -// "Improved division by invariant integers", Algorithm 4. -func udivrem2by1(uh, ul, d, reciprocal uint64) (quot, rem uint64) { - qh, ql := Mul64(reciprocal, uh) - ql, carry := Add64(ql, ul, 0) - qh, _ = Add64(qh, uh, carry) - qh++ - - r := ul - qh*d - - if r > ql { - qh-- - r += d - } - - if r >= d { - qh++ - r -= d - } - - return qh, r -} - -// Lsh sets z = x << n and returns z. -func (z *Uint) Lsh(x *Uint, n uint) *Uint { - // n % 64 == 0 - if n&0x3f == 0 { - switch n { - case 0: - return z.Set(x) - case 64: - return z.lsh64(x) - case 128: - return z.lsh128(x) - case 192: - return z.lsh192(x) - default: - return z.Clear() - } - } - var ( - a, b uint64 - ) - // Big swaps first - switch { - case n > 192: - if n > 256 { - return z.Clear() - } - z.lsh192(x) - n -= 192 - goto sh192 - case n > 128: - z.lsh128(x) - n -= 128 - goto sh128 - case n > 64: - z.lsh64(x) - n -= 64 - goto sh64 - default: - z.Set(x) - } - - // remaining shifts - a = z.arr[0] >> (64 - n) - z.arr[0] = z.arr[0] << n - -sh64: - b = z.arr[1] >> (64 - n) - z.arr[1] = (z.arr[1] << n) | a - -sh128: - a = z.arr[2] >> (64 - n) - z.arr[2] = (z.arr[2] << n) | b - -sh192: - z.arr[3] = (z.arr[3] << n) | a - - return z -} - -// Rsh sets z = x >> n and returns z. -func (z *Uint) Rsh(x *Uint, n uint) *Uint { - // n % 64 == 0 - if n&0x3f == 0 { - switch n { - case 0: - return z.Set(x) - case 64: - return z.rsh64(x) - case 128: - return z.rsh128(x) - case 192: - return z.rsh192(x) - default: - return z.Clear() - } - } - var ( - a, b uint64 - ) - // Big swaps first - switch { - case n > 192: - if n > 256 { - return z.Clear() - } - z.rsh192(x) - n -= 192 - goto sh192 - case n > 128: - z.rsh128(x) - n -= 128 - goto sh128 - case n > 64: - z.rsh64(x) - n -= 64 - goto sh64 - default: - z.Set(x) - } - - // remaining shifts - a = z.arr[3] << (64 - n) - z.arr[3] = z.arr[3] >> n - -sh64: - b = z.arr[2] << (64 - n) - z.arr[2] = (z.arr[2] >> n) | a - -sh128: - a = z.arr[1] << (64 - n) - z.arr[1] = (z.arr[1] >> n) | b - -sh192: - z.arr[0] = (z.arr[0] >> n) | a - - return z -} - -// SRsh (Signed/Arithmetic right shift) -// considers z to be a signed integer, during right-shift -// and sets z = x >> n and returns z. -func (z *Uint) SRsh(x *Uint, n uint) *Uint { - // If the MSB is 0, SRsh is same as Rsh. - if !x.isBitSet(255) { - return z.Rsh(x, n) - } - if n%64 == 0 { - switch n { - case 0: - return z.Set(x) - case 64: - return z.srsh64(x) - case 128: - return z.srsh128(x) - case 192: - return z.srsh192(x) - default: - return z.SetAllOne() - } - } - var ( - a uint64 = MaxUint64 << (64 - n%64) - ) - // Big swaps first - switch { - case n > 192: - if n > 256 { - return z.SetAllOne() - } - z.srsh192(x) - n -= 192 - goto sh192 - case n > 128: - z.srsh128(x) - n -= 128 - goto sh128 - case n > 64: - z.srsh64(x) - n -= 64 - goto sh64 - default: - z.Set(x) - } - - // remaining shifts - z.arr[3], a = (z.arr[3]>>n)|a, z.arr[3]<<(64-n) - -sh64: - z.arr[2], a = (z.arr[2]>>n)|a, z.arr[2]<<(64-n) - -sh128: - z.arr[1], a = (z.arr[1]>>n)|a, z.arr[1]<<(64-n) - -sh192: - z.arr[0] = (z.arr[0] >> n) | a - - return z -} - -func (z *Uint) lsh64(x *Uint) *Uint { - z.arr[3], z.arr[2], z.arr[1], z.arr[0] = x.arr[2], x.arr[1], x.arr[0], 0 - return z -} -func (z *Uint) lsh128(x *Uint) *Uint { - z.arr[3], z.arr[2], z.arr[1], z.arr[0] = x.arr[1], x.arr[0], 0, 0 - return z -} -func (z *Uint) lsh192(x *Uint) *Uint { - z.arr[3], z.arr[2], z.arr[1], z.arr[0] = x.arr[0], 0, 0, 0 - return z -} -func (z *Uint) rsh64(x *Uint) *Uint { - z.arr[3], z.arr[2], z.arr[1], z.arr[0] = 0, x.arr[3], x.arr[2], x.arr[1] - return z -} -func (z *Uint) rsh128(x *Uint) *Uint { - z.arr[3], z.arr[2], z.arr[1], z.arr[0] = 0, 0, x.arr[3], x.arr[2] - return z -} -func (z *Uint) rsh192(x *Uint) *Uint { - z.arr[3], z.arr[2], z.arr[1], z.arr[0] = 0, 0, 0, x.arr[3] - return z -} -func (z *Uint) srsh64(x *Uint) *Uint { - z.arr[3], z.arr[2], z.arr[1], z.arr[0] = MaxUint64, x.arr[3], x.arr[2], x.arr[1] - return z -} -func (z *Uint) srsh128(x *Uint) *Uint { - z.arr[3], z.arr[2], z.arr[1], z.arr[0] = MaxUint64, MaxUint64, x.arr[3], x.arr[2] - return z -} -func (z *Uint) srsh192(x *Uint) *Uint { - z.arr[3], z.arr[2], z.arr[1], z.arr[0] = MaxUint64, MaxUint64, MaxUint64, x.arr[3] - return z -} - -// Or sets z = x | y and returns z. -func (z *Uint) Or(x, y *Uint) *Uint { - z.arr[0] = x.arr[0] | y.arr[0] - z.arr[1] = x.arr[1] | y.arr[1] - z.arr[2] = x.arr[2] | y.arr[2] - z.arr[3] = x.arr[3] | y.arr[3] - return z -} - -// And sets z = x & y and returns z. -func (z *Uint) And(x, y *Uint) *Uint { - z.arr[0] = x.arr[0] & y.arr[0] - z.arr[1] = x.arr[1] & y.arr[1] - z.arr[2] = x.arr[2] & y.arr[2] - z.arr[3] = x.arr[3] & y.arr[3] - return z -} - -// Xor sets z = x ^ y and returns z. -func (z *Uint) Xor(x, y *Uint) *Uint { - z.arr[0] = x.arr[0] ^ y.arr[0] - z.arr[1] = x.arr[1] ^ y.arr[1] - z.arr[2] = x.arr[2] ^ y.arr[2] - z.arr[3] = x.arr[3] ^ y.arr[3] - return z -} - -// MarshalJSON implements json.Marshaler. -// MarshalJSON marshals using the 'decimal string' representation. This is _not_ compatible -// with big.Uint: big.Uint marshals into JSON 'native' numeric format. -// -// The JSON native format is, on some platforms, (e.g. javascript), limited to 53-bit large -// integer space. Thus, U256 uses string-format, which is not compatible with -// big.int (big.Uint refuses to unmarshal a string representation). -func (z *Uint) MarshalJSON() ([]byte, error) { - return []byte(`"` + z.Dec() + `"`), nil -} - -// UnmarshalJSON implements json.Unmarshaler. UnmarshalJSON accepts either -// - Quoted string: either hexadecimal OR decimal -// - Not quoted string: only decimal -func (z *Uint) UnmarshalJSON(input []byte) error { - if len(input) < 2 || input[0] != '"' || input[len(input)-1] != '"' { - // if not quoted, it must be decimal - return z.fromDecimal(string(input)) - } - return z.UnmarshalText(input[1 : len(input)-1]) -} - -// MarshalText implements encoding.TextMarshaler -// MarshalText marshals using the decimal representation (compatible with big.Uint) -func (z *Uint) MarshalText() ([]byte, error) { - return []byte(z.Dec()), nil -} - -// UnmarshalText implements encoding.TextUnmarshaler. This method -// can unmarshal either hexadecimal or decimal. -// - For hexadecimal, the input _must_ be prefixed with 0x or 0X -func (z *Uint) UnmarshalText(input []byte) error { - if len(input) >= 2 && input[0] == '0' && (input[1] == 'x' || input[1] == 'X') { - return z.fromHex(string(input)) - } - return z.fromDecimal(string(input)) -} - -const ( - hextable = "0123456789abcdef" - bintable = "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x00\x01\x02\x03\x04\x05\x06\a\b\t\xff\xff\xff\xff\xff\xff\xff\n\v\f\r\x0e\x0f\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\n\v\f\r\x0e\x0f\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff" - badNibble = 0xff -) - -// fromHex is the internal implementation of parsing a hex-string. -func (z *Uint) fromHex(hex string) error { - if err := checkNumberS(hex); err != nil { - return err - } - if len(hex) > 66 { - return ErrBig256Range - } - z.Clear() - end := len(hex) - for i := 0; i < 4; i++ { - start := end - 16 - if start < 2 { - start = 2 - } - for ri := start; ri < end; ri++ { - nib := bintable[hex[ri]] - if nib == badNibble { - return ErrSyntax - } - z.arr[i] = z.arr[i] << 4 - z.arr[i] += uint64(nib) - } - end = start - } - return nil -} - -// FromDecimal is a convenience-constructor to create an Uint from a -// decimal (base 10) string. Numbers larger than 256 bits are not accepted. -func FromDecimal(decimal string) *Uint { - var z Uint - if err := z.SetFromDecimal(decimal); err != nil { - panic(err.Error()) - } - return &z -} - -const twoPow256Sub1 = "115792089237316195423570985008687907853269984665640564039457584007913129639935" - -// SetFromDecimal sets z from the given string, interpreted as a decimal number. -// OBS! This method is _not_ strictly identical to the (*big.Uint).SetString(..., 10) method. -// Notable differences: -// - This method does not accept underscore input, e.g. "100_000", -// - This method does not accept negative zero as valid, e.g "-0", -// - (this method does not accept any negative input as valid)) -func (z *Uint) SetFromDecimal(s string) (err error) { - // Remove max one leading + - if len(s) > 0 && s[0] == '+' { - s = s[1:] - } - // Remove any number of leading zeroes - if len(s) > 0 && s[0] == '0' { - var i int - var c rune - for i, c = range s { - if c != '0' { - break - } - } - s = s[i:] - } - if len(s) < len(twoPow256Sub1) { - return z.fromDecimal(s) - } - if len(s) == len(twoPow256Sub1) { - if s > twoPow256Sub1 { - return ErrBig256Range - } - return z.fromDecimal(s) - } - return ErrBig256Range -} - -var ( - ErrEmptyString = errors.New("empty hex string") - ErrSyntax = errors.New("invalid hex string") - ErrMissingPrefix = errors.New("hex string without 0x prefix") - ErrEmptyNumber = errors.New("hex string \"0x\"") - ErrLeadingZero = errors.New("hex number with leading zero digits") - ErrBig256Range = errors.New("hex number > 256 bits") - ErrBadBufferLength = errors.New("bad ssz buffer length") - ErrBadEncodedLength = errors.New("bad ssz encoded length") -) - -func checkNumberS(input string) error { - l := len(input) - if l == 0 { - return ErrEmptyString - } - if l < 2 || input[0] != '0' || - (input[1] != 'x' && input[1] != 'X') { - return ErrMissingPrefix - } - if l == 2 { - return ErrEmptyNumber - } - if len(input) > 3 && input[2] == '0' { - return ErrLeadingZero - } - return nil -} - -// multipliers holds the values that are needed for fromDecimal -var multipliers = [5]*Uint{ - nil, // represents first round, no multiplication needed - &Uint{[4]uint64{10000000000000000000, 0, 0, 0}}, // 10 ^ 19 - &Uint{[4]uint64{687399551400673280, 5421010862427522170, 0, 0}}, // 10 ^ 38 - &Uint{[4]uint64{5332261958806667264, 17004971331911604867, 2938735877055718769, 0}}, // 10 ^ 57 - &Uint{[4]uint64{0, 8607968719199866880, 532749306367912313, 1593091911132452277}}, // 10 ^ 76 -} - -// fromDecimal is a helper function to only ever be called via SetFromDecimal -// this function takes a string and chunks it up, calling ParseUint on it up to 5 times -// these chunks are then multiplied by the proper power of 10, then added together. -func (z *Uint) fromDecimal(bs string) error { - // first clear the input - z.Clear() - // the maximum value of uint64 is 18446744073709551615, which is 20 characters - // one less means that a string of 19 9's is always within the uint64 limit - var ( - num uint64 - err error - remaining = len(bs) - ) - if remaining == 0 { - return errors.New("EOF") - } - // We proceed in steps of 19 characters (nibbles), from least significant to most significant. - // This means that the first (up to) 19 characters do not need to be multiplied. - // In the second iteration, our slice of 19 characters needs to be multipleied - // by a factor of 10^19. Et cetera. - for i, mult := range multipliers { - if remaining <= 0 { - return nil // Done - } else if remaining > 19 { - num, err = parseUint(bs[remaining-19:remaining], 10, 64) - } else { - // Final round - num, err = parseUint(bs, 10, 64) - } - if err != nil { - return err - } - // add that number to our running total - if i == 0 { - z.SetUint64(num) - } else { - base := NewUint(num) - z.Add(z, base.Mul(base, mult)) - } - // Chop off another 19 characters - if remaining > 19 { - bs = bs[0 : remaining-19] - } - remaining -= 19 - } - return nil -} - -// lower(c) is a lower-case letter if and only if -// c is either that lower-case letter or the equivalent upper-case letter. -// Instead of writing c == 'x' || c == 'X' one can write lower(c) == 'x'. -// Note that lower of non-letters can produce other non-letters. -func lower(c byte) byte { - return c | ('x' - 'X') -} - -// ParseUint is like ParseUint but for unsigned numbers. -// -// A sign prefix is not permitted. -func parseUint(s string, base int, bitSize int) (uint64, error) { - const fnParseUint = "ParseUint" - - if s == "" { - return 0, errors.New("syntax error: ParseUint empty string") - } - - base0 := base == 0 - - s0 := s - switch { - case 2 <= base && base <= 36: - // valid base; nothing to do - - case base == 0: - // Look for octal, hex prefix. - base = 10 - if s[0] == '0' { - switch { - case len(s) >= 3 && lower(s[1]) == 'b': - base = 2 - s = s[2:] - case len(s) >= 3 && lower(s[1]) == 'o': - base = 8 - s = s[2:] - case len(s) >= 3 && lower(s[1]) == 'x': - base = 16 - s = s[2:] - default: - base = 8 - s = s[1:] - } - } - - default: - return 0, errors.New("invalid base") - } - - if bitSize == 0 { - bitSize = UintSize - } else if bitSize < 0 || bitSize > 64 { - return 0, errors.New("invalid bit size") - } - - // Cutoff is the smallest number such that cutoff*base > maxUint64. - // Use compile-time constants for common cases. - var cutoff uint64 - switch base { - case 10: - cutoff = MaxUint64/10 + 1 - case 16: - cutoff = MaxUint64/16 + 1 - default: - cutoff = MaxUint64/uint64(base) + 1 - } - - maxVal := uint64(1)<= byte(base) { - return 0, errors.New("syntax error") - } - - if n >= cutoff { - // n*base overflows - return maxVal, errors.New("range error") - } - n *= uint64(base) - - n1 := n + uint64(d) - if n1 < n || n1 > maxVal { - // n+d overflows - return maxVal, errors.New("range error") - } - n = n1 - } - - if underscores && !underscoreOK(s0) { - return 0, errors.New("syntax error") - } - - return n, nil -} - -// underscoreOK reports whether the underscores in s are allowed. -// Checking them in this one function lets all the parsers skip over them simply. -// Underscore must appear only between digits or between a base prefix and a digit. -func underscoreOK(s string) bool { - // saw tracks the last character (class) we saw: - // ^ for beginning of number, - // 0 for a digit or base prefix, - // _ for an underscore, - // ! for none of the above. - saw := '^' - i := 0 - - // Optional sign. - if len(s) >= 1 && (s[0] == '-' || s[0] == '+') { - s = s[1:] - } - - // Optional base prefix. - hex := false - if len(s) >= 2 && s[0] == '0' && (lower(s[1]) == 'b' || lower(s[1]) == 'o' || lower(s[1]) == 'x') { - i = 2 - saw = '0' // base prefix counts as a digit for "underscore as digit separator" - hex = lower(s[1]) == 'x' - } - - // Number proper. - for ; i < len(s); i++ { - // Digits are always okay. - if '0' <= s[i] && s[i] <= '9' || hex && 'a' <= lower(s[i]) && lower(s[i]) <= 'f' { - saw = '0' - continue - } - // Underscore must follow digit. - if s[i] == '_' { - if saw != '0' { - return false - } - saw = '_' - continue - } - // Underscore must also be followed by digit. - if saw == '_' { - return false - } - // Saw non-digit, non-underscore. - saw = '!' - } - return saw != '_' -} - -// Dec returns the decimal representation of z. -func (z *Uint) Dec() string { // toString() - if z.IsZero() { - return "0" - } - if z.IsUint64() { - return FormatUint(z.Uint64(), 10) - } - - // The max uint64 value being 18446744073709551615, the largest - // power-of-ten below that is 10000000000000000000. - // When we do a DivMod using that number, the remainder that we - // get back is the lower part of the output. - // - // The ascii-output of remainder will never exceed 19 bytes (since it will be - // below 10000000000000000000). - // - // Algorithm example using 100 as divisor - // - // 12345 % 100 = 45 (rem) - // 12345 / 100 = 123 (quo) - // -> output '45', continue iterate on 123 - var ( - // out is 98 bytes long: 78 (max size of a string without leading zeroes, - // plus slack so we can copy 19 bytes every iteration). - // We init it with zeroes, because when strconv appends the ascii representations, - // it will omit leading zeroes. - out = []byte("00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000") - divisor = NewUint(10000000000000000000) // 20 digits - y = new(Uint).Set(z) // copy to avoid modifying z - pos = len(out) // position to write to - buf = make([]byte, 0, 19) // buffer to write uint64:s to - ) - for { - // Obtain Q and R for divisor - var quot Uint - rem := udivrem(quot.arr[:], y.arr[:], divisor) - y.Set(") // Set Q for next loop - // Convert the R to ascii representation - buf = AppendUint(buf[:0], rem.Uint64(), 10) - // Copy in the ascii digits - copy(out[pos-len(buf):], buf) - if y.IsZero() { - break - } - // Move 19 digits left - pos -= 19 - } - // skip leading zeroes by only using the 'used size' of buf - return string(out[pos-len(buf):]) -} - -// Mod sets z to the modulus x%y for y != 0 and returns z. -// If y == 0, z is set to 0 (OBS: differs from the big.Uint) -func (z *Uint) Mod(x, y *Uint) *Uint { - if x.IsZero() || y.IsZero() { - return z.Clear() - } - switch x.Cmp(y) { - case -1: - // x < y - copy(z.arr[:], x.arr[:]) - return z - case 0: - // x == y - return z.Clear() // They are equal - } - - // At this point: - // x != 0 - // y != 0 - // x > y - - // Shortcut trivial case - if x.IsUint64() { - return z.SetUint64(x.Uint64() % y.Uint64()) - } - - var quot Uint - *z = udivrem(quot.arr[:], x.arr[:], y) - return z -} - -// Clone creates a new Int identical to z -func (z *Uint) Clone() *Uint { - var x Uint - x.arr[0] = z.arr[0] - x.arr[1] = z.arr[1] - x.arr[2] = z.arr[2] - x.arr[3] = z.arr[3] - - return &x -} - -func (z *Uint) IsNil() bool { - return z == nil -} - -func (z *Uint) NilToZero() *Uint { - if z == nil { - z = NewUint(0) - } - - return z -} diff --git a/u256/u256_test.gno b/u256/u256_test.gno deleted file mode 100644 index 8590221d..00000000 --- a/u256/u256_test.gno +++ /dev/null @@ -1,18 +0,0 @@ -package u256 - -import ( - "testing" -) - -func TestFuncs(t *testing.T) { - x := NewUint(0) - y := NewUint(1) - - // println(x.Dec()) - - var m256 bigint = 115792089237316195423570985008687907853269984665640564039457584007913129639935 - - z := FromBigint(m256) - - println(z.Dec()) -}