Skip to content

Commit

Permalink
Merge pull request #200 from taikoxyz/avalon
Browse files Browse the repository at this point in the history
feat: avalon airdrop
  • Loading branch information
bennettyong authored Feb 5, 2025
2 parents b0853a1 + 66a6c46 commit fbc6860
Show file tree
Hide file tree
Showing 5 changed files with 160 additions and 2 deletions.
5 changes: 3 additions & 2 deletions adapters/adapters.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,8 @@ type Lock struct {
TxHash common.Hash
}

// Position is used for logx trading campaign
// Position is used for airdrop or trading campaign.
// For examples, see Avalon.
type Position struct {
User common.Address
TokenAmount *big.Int
Expand All @@ -70,7 +71,7 @@ type Position struct {
TxHash common.Hash
}

// Prdiction is used for prediction campaign.
// Prediction is used for prediction campaign.
// For examples, see Robinos.
type Prediction struct {
User common.Address
Expand Down
98 changes: 98 additions & 0 deletions adapters/projects/avalon/claim.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
package avalon

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

"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/erc20"
)

const (
// TODO: update
AvalonAirdropAddress string = "0x46f0a2e45bee8e9ebfdb278ce06caa6af294c349"
AvalonTokenAddress string = "0x46f0a2e45bee8e9ebfdb278ce06caa6af294c349"
AvalonTokenDecimal = 18

logTransferSignature string = "Transfer(address,address,uint256)"
)

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

func NewClaimIndexer(client *ethclient.Client, contract common.Address, addresses []common.Address) *ClaimIndexer {
return &ClaimIndexer{
client: client,
addresses: addresses,
contract: contract,
}
}

var _ adapters.LogIndexer[adapters.Position] = &ClaimIndexer{}

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

func (indexer *ClaimIndexer) Index(ctx context.Context, logs ...types.Log) ([]adapters.Position, error) {
var transferEvent struct {
Value *big.Int
}

var claims []adapters.Position

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

from := common.BytesToAddress(l.Topics[1].Bytes()[12:])
to := common.BytesToAddress(l.Topics[2].Bytes()[12:])

if from.Hex() != indexer.contract.Hex() {
continue
}

erc20ABI, err := abi.JSON(strings.NewReader(erc20.ABI))
if err != nil {
return nil, err
}

err = erc20ABI.UnpackIntoInterface(&transferEvent, "Transfer", l.Data)
if err != nil {
return nil, err
}

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

claim := &adapters.Position{
User: to,
TokenAmount: transferEvent.Value,
TokenDecimals: AvalonTokenDecimal,
Token: common.HexToAddress(AvalonTokenAddress),
BlockTime: block.Time(),
BlockNumber: block.NumberU64(),
TxHash: l.TxHash,
}

claims = append(claims, *claim)
}

return claims, nil
}

func (indexer *ClaimIndexer) isTransfer(l types.Log) bool {
return l.Topics[0].Hex() == crypto.Keccak256Hash([]byte(logTransferSignature)).Hex()
}
40 changes: 40 additions & 0 deletions adapters/projects/avalon/claim_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
package avalon_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/avalon"
)

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

ctx := context.Background()

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

indexer := avalon.NewClaimIndexer(client, common.HexToAddress(avalon.AvalonAirdropAddress), []common.Address{common.HexToAddress(avalon.AvalonTokenAddress)})

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

locks, err := indexer.Index(ctx, logs...)
assert.NoError(t, err)
assert.Len(t, locks, 1)
assert.Equal(t, common.HexToAddress("0xC3204E92B0e7731d75Ad667a93c8Da815BD9Ac61"), locks[0].User)
assert.Equal(t, big.NewInt(2000000000000000000), locks[0].TokenAmount)
assert.Equal(t, adapters.TaikoTokenDecimals, locks[0].TokenDecimals)
assert.Equal(t, common.HexToAddress(adapters.TaikoTokenAddress), locks[0].Token)
assert.Equal(t, uint64(1728390191), locks[0].BlockTime)
assert.Equal(t, uint64(blocknumber), locks[0].BlockNumber)
assert.Equal(t, common.HexToHash("0x95f528b52f0a75176543f516014bbba26e003f1c17c9b9413e936240e3f44650"), locks[0].TxHash)
}
4 changes: 4 additions & 0 deletions cmd/adapter.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ const (
RobinosPrediction adapter = "RobinosPrediction"
LoopringLock adapter = "LoopringLock"
PolarisLP adapter = "PolarisLP"
DoraHacksVoting adapter = "DoraHacksVoting"
AvalonClaim adapter = "AvalonClaim"
)

func adapterz() []adapter {
Expand All @@ -43,5 +45,7 @@ func adapterz() []adapter {
RobinosPrediction,
LoopringLock,
PolarisLP,
DoraHacksVoting,
AvalonClaim,
}
}
15 changes: 15 additions & 0 deletions cmd/cmd.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,10 @@ import (
"github.com/spf13/cobra"
"github.com/taikoxyz/trailblazer-adapters/adapters"
nftdeployed "github.com/taikoxyz/trailblazer-adapters/adapters/nft_deployed"
"github.com/taikoxyz/trailblazer-adapters/adapters/projects/avalon"
"github.com/taikoxyz/trailblazer-adapters/adapters/projects/conft"
"github.com/taikoxyz/trailblazer-adapters/adapters/projects/domains"
"github.com/taikoxyz/trailblazer-adapters/adapters/projects/dorahacks"
"github.com/taikoxyz/trailblazer-adapters/adapters/projects/drips"
"github.com/taikoxyz/trailblazer-adapters/adapters/projects/gaming"
"github.com/taikoxyz/trailblazer-adapters/adapters/projects/izumi"
Expand Down Expand Up @@ -201,6 +203,19 @@ func executeCommand(p prompt) error {
[]common.Address{common.HexToAddress(polaris.VaultAddress)},
)
return processLog(ctx, client, indexer, p.Blocknumber)
case DoraHacksVoting:
indexer := dorahacks.NewVotingIndexer(
client,
[]common.Address{common.HexToAddress(dorahacks.VotingAddress)},
)
return processLog(ctx, client, indexer, p.Blocknumber)
case AvalonClaim:
indexer := avalon.NewClaimIndexer(
client,
common.HexToAddress(avalon.AvalonAirdropAddress),
[]common.Address{common.HexToAddress(avalon.AvalonTokenAddress)},
)
return processLog(ctx, client, indexer, p.Blocknumber)

default:
return fmt.Errorf("adapter %s is not supported", p.Adapter)
Expand Down

0 comments on commit fbc6860

Please sign in to comment.