defiweb / go-eth

A suite of tools for interacting with Ethereum-based blockchains.
MIT License
11 stars 2 forks source link

BUG: encode negative int16 wrong format #13

Open guotie opened 1 month ago

guotie commented 1 month ago

When I read a uniswap v3 pool liquidity with TickLens contract, I encounter error:

My Code:

func TestTickLens(t *testing.T) {
    // Uniswap V3 pool ETH/USDC on base mainnet
    poolAddr := "0xd0b53D9277642d899DF5C87A3966A349A798F224"
    poolTickLensABI := defiabi.MustParseJSON([]byte(`[{"inputs":[{"internalType":"address","name":"pool","type":"address"},{"internalType":"int16","name":"tickBitmapIndex","type":"int16"}],"name":"getPopulatedTicksInWord","outputs":[{"components":[{"internalType":"int24","name":"tick","type":"int24"},{"internalType":"int128","name":"liquidityNet","type":"int128"},{"internalType":"uint128","name":"liquidityGross","type":"uint128"}],"internalType":"struct ITickLens.PopulatedTick[]","name":"populatedTicks","type":"tuple[]"}],"stateMutability":"view","type":"function"}]`))

    calldata := poolTickLensABI.Methods["getPopulatedTicksInWord"].MustEncodeArgs(poolAddr, -100)
    queryAddr := "0x0CdeE061c75D43c82520eD998C23ac2991c9ac6d" // Uniswap V3 TickLens contract address on base mainnet

    uri := "https://mainnet.base.org"
    tr, err := transport.NewHTTP(transport.HTTPOptions{URL: uri})
    assert.Nil(t, err)

    // Create a JSON-RPC client.
    client, err := rpc.NewClient(rpc.WithTransport(tr))
    assert.Nil(t, err)

    // Prepare a call.
    call := types.NewCall().
        SetTo(types.MustAddressFromHex(queryAddr)).
        SetInput(calldata)

    // 351fb478
    // 000000000000000000000000d0b53d9277642d899df5c87a3966a349a798f224
    // 000000000000000000000000000000000000000000000000000000000000ff9c
    println(hex.EncodeToString(calldata))

    // Call method.
    b, _, err := client.Call(context.Background(), call, types.LatestBlockNumber)
    if err != nil {
        panic(err)
    }
    _ = b
}

returns:

panic: RPC error: -32000 execution reverted
guotie commented 1 month ago

I compare calldata with etherscan, the calldata should be

351fb478000000000000000000000000d0b53d9277642d899df5c87a3966a349a798f224ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff9c

and our calldata is :

351fb478000000000000000000000000d0b53d9277642d899df5c87a3966a349a798f224000000000000000000000000000000000000000000000000000000000000ff9c

we encode -100 to 000000000000000000000000000000000000000000000000000000000000ff9c, which cause failed.

If I use calldata 351fb478000000000000000000000000d0b53d9277642d899df5c87a3966a349a798f224ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff9c, then it success, so the problem is wrong encode negtive int16.

so, how to fix it?

guotie commented 1 month ago

the method protottype:

    function getPopulatedTicksInWord(address pool, int16 tickBitmapIndex)
        public
        view
        override
        returns (PopulatedTick[] memory populatedTicks)