Skip to content

Commit

Permalink
Merge pull request #161 from polarisfinance/main
Browse files Browse the repository at this point in the history
Add Polaris Finance adapter
  • Loading branch information
myronrotter authored Nov 18, 2024
2 parents 6026394 + f49e318 commit 89047df
Show file tree
Hide file tree
Showing 6 changed files with 279 additions and 0 deletions.
197 changes: 197 additions & 0 deletions adapters/projects/polaris/lp_transfer.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,197 @@
package polaris

import (
"context"
"errors"
"math/big"
"strings"

"github.com/ethereum/go-ethereum"
"github.com/ethereum/go-ethereum/accounts/abi"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/ethclient"
"github.com/taikoxyz/trailblazer-adapters/adapters"
"github.com/taikoxyz/trailblazer-adapters/adapters/contracts/balancer_vault"
"github.com/taikoxyz/trailblazer-adapters/adapters/contracts/erc20"
)

const (
VaultAddress = "0x723F40720836a03f1F20441FbDa3D109fc99640F" // Replace with the actual vault contract address
logPoolBalanceChangedSig = "PoolBalanceChanged(bytes32,address,address[],int256[],uint256[])"
)

type LPTransferIndexer struct {
client *ethclient.Client
addresses []common.Address
}

func NewLPTransferIndexer(client *ethclient.Client, addresses []common.Address) *LPTransferIndexer {
return &LPTransferIndexer{
client: client,
addresses: addresses,
}
}

var _ adapters.LogIndexer[adapters.LPTransfer] = &LPTransferIndexer{}

func (indexer *LPTransferIndexer) Addresses() []common.Address {
return indexer.addresses
}

func (indexer *LPTransferIndexer) Index(ctx context.Context, logs ...types.Log) ([]adapters.LPTransfer, error) {
var transfers []adapters.LPTransfer

for _, l := range logs {
if !indexer.isPoolBalanceChanged(l) {
continue
}

transfer, err := indexer.processPoolBalanceChangedLog(ctx, l)
if err != nil {
return nil, errors.Join(err, errors.New("processing PoolBalanceChanged log"))
}

if transfer != nil {
transfers = append(transfers, *transfer)
}
}

return transfers, nil
}

func (indexer *LPTransferIndexer) processPoolBalanceChangedLog(ctx context.Context, l types.Log) (*adapters.LPTransfer, error) {
event, err := indexer.parsePoolBalanceChangedEvent(l)
if err != nil {
return nil, errors.Join(err, errors.New("parsing PoolBalanceChanged event"))
}

// Check if both deltas are positive
if len(event.Deltas) != 2 {
// Assuming we are only interested in events with exactly two tokens
return nil, nil // Skip this event
}

if event.Deltas[0].Sign() <= 0 || event.Deltas[1].Sign() <= 0 {
// One or both deltas are not positive, skip this event
return nil, nil
}

block, err := indexer.client.BlockByNumber(ctx, big.NewInt(int64(l.BlockNumber)))
if err != nil {
return nil, errors.Join(err, errors.New("fetching block"))
}

// Fetch token decimals for both tokens
token0Decimals, err := indexer.fetchTokenDecimals(ctx, event.Tokens[0], block.Number())
if err != nil {
return nil, errors.Join(err, errors.New("fetching token0 decimals"))
}

token1Decimals, err := indexer.fetchTokenDecimals(ctx, event.Tokens[1], block.Number())
if err != nil {
return nil, errors.Join(err, errors.New("fetching token1 decimals"))
}

// Create an LPTransfer record with the vault address as the recipient
vaultAddress := common.HexToAddress(VaultAddress)

transfer := adapters.LPTransfer{
From: event.LiquidityProvider,
To: vaultAddress,
Token0Amount: event.Deltas[0],
Token0Decimals: token0Decimals,
Token0: event.Tokens[0],
Token1Amount: event.Deltas[1],
Token1Decimals: token1Decimals,
Token1: event.Tokens[1],
Time: block.Time(),
BlockNumber: block.NumberU64(),
TxHash: l.TxHash,
}

return &transfer, nil
}

type PoolBalanceChangedEvent struct {
PoolId [32]byte
LiquidityProvider common.Address
Tokens []common.Address
Deltas []*big.Int
ProtocolFeeAmounts []*big.Int
}

func (indexer *LPTransferIndexer) parsePoolBalanceChangedEvent(l types.Log) (*PoolBalanceChangedEvent, error) {
if len(l.Topics) != 3 {
return nil, errors.New("incorrect number of topics")
}

// The PoolBalanceChanged event is indexed on PoolId and LiquidityProvider
var poolId [32]byte
copy(poolId[:], l.Topics[1].Bytes())

liquidityProvider := common.BytesToAddress(l.Topics[2].Bytes()[12:])

vaultABI, err := abi.JSON(strings.NewReader(balancer_vault.BalancerVaultABI))
if err != nil {
return nil, errors.Join(err, errors.New("parsing ABI"))
}

var eventData struct {
Tokens []common.Address
Deltas []*big.Int
ProtocolFeeAmounts []*big.Int
}

// Unpack the event data
err = vaultABI.UnpackIntoInterface(&eventData, "PoolBalanceChanged", l.Data)
if err != nil {
return nil, errors.Join(err, errors.New("unpacking event data"))
}

event := &PoolBalanceChangedEvent{
PoolId: poolId,
LiquidityProvider: liquidityProvider,
Tokens: eventData.Tokens,
Deltas: eventData.Deltas,
ProtocolFeeAmounts: eventData.ProtocolFeeAmounts,
}

return event, nil
}

func (indexer *LPTransferIndexer) fetchTokenDecimals(ctx context.Context, token common.Address, blockNumber *big.Int) (uint8, error) {
erc20ABI, err := abi.JSON(strings.NewReader(erc20.Erc20ABI))
if err != nil {
return 0, errors.Join(err, errors.New("parsing ERC20 ABI"))
}

data, err := erc20ABI.Pack("decimals")
if err != nil {
return 0, errors.Join(err, errors.New("packing decimals call"))
}

callMsg := ethereum.CallMsg{
To: &token,
Data: data,
}

result, err := indexer.client.CallContract(ctx, callMsg, blockNumber)
if err != nil {
return 0, errors.Join(err, errors.New("calling decimals method"))
}

var decimals uint8
err = erc20ABI.UnpackIntoInterface(&decimals, "decimals", result)
if err != nil {
return 0, errors.Join(err, errors.New("unpacking decimals result"))
}

return decimals, nil
}

func (indexer *LPTransferIndexer) isPoolBalanceChanged(l types.Log) bool {
eventSignatureHash := crypto.Keccak256Hash([]byte(logPoolBalanceChangedSig))
return l.Topics[0].Hex() == eventSignatureHash.Hex()
}
64 changes: 64 additions & 0 deletions adapters/projects/polaris/lp_transfer_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
package polaris_test

import (
"context"
"math/big"
"testing"

"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/ethclient"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/taikoxyz/trailblazer-adapters/adapters"
"github.com/taikoxyz/trailblazer-adapters/adapters/projects/polaris"
)

func TestLPTransferIndexer(t *testing.T) {
taikoRPC := "https://rpc.taiko.xyz"
blocknumber := int64(408155)

ctx := context.Background()

client, err := ethclient.Dial(taikoRPC)
require.NoError(t, err)

indexer := polaris.NewLPTransferIndexer(client, []common.Address{common.HexToAddress(polaris.VaultAddress)})

logs, err := adapters.GetLogs(ctx, client, indexer.Addresses(), blocknumber)
require.NoError(t, err)

transfers, err := indexer.Index(ctx, logs...)
assert.NoError(t, err)
txHash := common.HexToHash("0x53cadfc76c846db7bc14bcdca5b97fb52ba3cae7e4f641e339d9964a27da8cc1")
user := common.HexToAddress("0xb535d4D9126c58d8dA8fE5775088aF77DE37F5D7")
time := 1727179415
expectedTransfers := []adapters.LPTransfer{
{
From: user,
To: common.HexToAddress(polaris.VaultAddress),
Token0Amount: big.NewInt(223714285714285710),
Token0Decimals: uint8(18),
Token0: common.HexToAddress("0x7824693029834D294A92c54138e81e94d8D0Fd06"),
Token1Amount: big.NewInt(300000000000000000),
Token1Decimals: uint8(18),
Token1: common.HexToAddress("0xA9d23408b9bA935c230493c40C73824Df71A0975"),
Time: uint64(time),
BlockNumber: uint64(blocknumber),
TxHash: txHash,
},
}

for i, transfer := range transfers {
assert.Equal(t, expectedTransfers[i].From, transfer.From)
assert.Equal(t, expectedTransfers[i].To, transfer.To)
assert.Equal(t, expectedTransfers[i].Token0Amount, transfer.Token0Amount)
assert.Equal(t, expectedTransfers[i].Token0Decimals, transfer.Token0Decimals)
assert.Equal(t, expectedTransfers[i].Token0, transfer.Token0)
assert.Equal(t, expectedTransfers[i].Token1Amount, transfer.Token1Amount)
assert.Equal(t, expectedTransfers[i].Token1Decimals, transfer.Token1Decimals)
assert.Equal(t, expectedTransfers[i].Token1, transfer.Token1)
assert.Equal(t, expectedTransfers[i].Time, transfer.Time)
assert.Equal(t, expectedTransfers[i].BlockNumber, transfer.BlockNumber)
assert.Equal(t, expectedTransfers[i].TxHash, transfer.TxHash)
}
}
2 changes: 2 additions & 0 deletions cmd/adapter.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ const (
SymmetricLock adapter = "SymmetricLock"
RobinosPrediction adapter = "RobinosPrediction"
LoopringLock adapter = "LoopringLock"
PolarisLP adapter = "PolarisLP"
)

func adapterz() []adapter {
Expand All @@ -41,5 +42,6 @@ func adapterz() []adapter {
SymmetricLock,
RobinosPrediction,
LoopringLock,
PolarisLP,
}
}
7 changes: 7 additions & 0 deletions cmd/cmd.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import (
"github.com/taikoxyz/trailblazer-adapters/adapters/projects/nfts2me"
"github.com/taikoxyz/trailblazer-adapters/adapters/projects/okx"
"github.com/taikoxyz/trailblazer-adapters/adapters/projects/omnihub"
"github.com/taikoxyz/trailblazer-adapters/adapters/projects/polaris"
"github.com/taikoxyz/trailblazer-adapters/adapters/projects/ritsu"
"github.com/taikoxyz/trailblazer-adapters/adapters/projects/robinos"
"github.com/taikoxyz/trailblazer-adapters/adapters/projects/symmetric"
Expand Down Expand Up @@ -194,6 +195,12 @@ func executeCommand(p prompt) error {
[]common.Address{common.HexToAddress(loopring.LockAddress)},
)
return processLog(ctx, client, indexer, p.Blocknumber)
case PolarisLP:
indexer := polaris.NewLPTransferIndexer(
client,
[]common.Address{common.HexToAddress(polaris.VaultAddress)},
)
return processLog(ctx, client, indexer, p.Blocknumber)

default:
return fmt.Errorf("adapter %s is not supported", p.Adapter)
Expand Down
Binary file added img/polaris.jpeg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
9 changes: 9 additions & 0 deletions whitelist/protocols.json
Original file line number Diff line number Diff line change
Expand Up @@ -1053,5 +1053,14 @@
"0xb961661F5Ca019e232661Bd26686288a6E21d928",
"0x64Eaf7cDE96277ed9253b8268DFC85eB2EB0D147"
]
},
{
"name": "Polaris Finance",
"slug": "polaris-finance",
"twitter": "@polarisfinance_",
"logo": "polaris.jpeg",
"contracts": [
"0x723F40720836a03f1F20441FbDa3D109fc99640F"
]
}
]

0 comments on commit 89047df

Please sign in to comment.