Skip to content

Commit 8c6cd21

Browse files
authored
feat: match across zero address output tokens (#29)
* Implement across token matching * Add hub pool address to config * Gnerate a keypair to allow for read only calls * Update ci lint configuration to v2 * Lint * Rename zero address to zero hash
1 parent 664d249 commit 8c6cd21

File tree

17 files changed

+264
-35
lines changed

17 files changed

+264
-35
lines changed

.golangci.yml

Lines changed: 22 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,8 @@
1-
# Refer to golangci-lint's example config file for more options and information:
2-
# https://github.com/golangci/golangci-lint/blob/master/.golangci.reference.yml
3-
1+
version: "2"
42
run:
5-
timeout: 5m
63
modules-download-mode: readonly
7-
exclude-dirs:
8-
- vendor
9-
- third_party
10-
114
linters:
125
enable:
13-
- errcheck
14-
- gosimple
15-
- goimports
16-
- govet
17-
- staticcheck
18-
- unused
19-
- ineffassign
206
- bodyclose
217
- gocognit
228
- godox
@@ -26,7 +12,26 @@ linters:
2612
- reassign
2713
- wastedassign
2814
- whitespace
29-
15+
exclusions:
16+
generated: lax
17+
presets:
18+
- comments
19+
- common-false-positives
20+
- legacy
21+
- std-error-handling
22+
paths:
23+
- third_party$
24+
- builtin$
25+
- examples$
3026
issues:
3127
max-issues-per-linter: 0
32-
max-same-issues: 0
28+
max-same-issues: 0
29+
formatters:
30+
enable:
31+
- goimports
32+
exclusions:
33+
generated: lax
34+
paths:
35+
- third_party$
36+
- builtin$
37+
- examples$

api/handlers/util.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ func (b *BigInt) UnmarshalJSON(data []byte) error {
1818
}
1919

2020
s := strings.Trim(string(data), "\"")
21-
_, ok := b.Int.SetString(s, 10)
21+
_, ok := b.SetString(s, 10)
2222
if !ok {
2323
return fmt.Errorf("failed to parse big.Int from %s", s)
2424
}

app/app.go

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import (
2222
"github.com/sprintertech/sprinter-signing/api/handlers"
2323
"github.com/sprintertech/sprinter-signing/cache"
2424
"github.com/sprintertech/sprinter-signing/chains/evm"
25+
"github.com/sprintertech/sprinter-signing/chains/evm/calls/contracts"
2526
"github.com/sprintertech/sprinter-signing/chains/evm/calls/events"
2627
evmListener "github.com/sprintertech/sprinter-signing/chains/evm/listener"
2728
evmMessage "github.com/sprintertech/sprinter-signing/chains/evm/message"
@@ -38,6 +39,7 @@ import (
3839
coreEvm "github.com/sygmaprotocol/sygma-core/chains/evm"
3940
evmClient "github.com/sygmaprotocol/sygma-core/chains/evm/client"
4041
coreListener "github.com/sygmaprotocol/sygma-core/chains/evm/listener"
42+
"github.com/sygmaprotocol/sygma-core/crypto/secp256k1"
4143

4244
"github.com/sygmaprotocol/sygma-core/observability"
4345
"github.com/sygmaprotocol/sygma-core/relayer"
@@ -139,6 +141,7 @@ func Run() error {
139141
confirmationsPerChain := make(map[uint64]map[uint64]uint64)
140142
domains := make(map[uint64]relayer.RelayedChain)
141143

144+
var hubPoolContract evmMessage.TokenMatcher
142145
acrossPools := make(map[uint64]common.Address)
143146
for _, chainConfig := range configuration.ChainConfigs {
144147
switch chainConfig["type"] {
@@ -151,6 +154,15 @@ func Run() error {
151154
poolAddress := common.HexToAddress(config.AcrossPool)
152155
acrossPools[*config.GeneralChainConfig.Id] = poolAddress
153156
}
157+
158+
if config.HubPool != "" {
159+
kp, _ := secp256k1.GenerateKeypair()
160+
client, err := evmClient.NewEVMClient(config.GeneralChainConfig.Endpoint, kp)
161+
panicOnError(err)
162+
163+
hubPoolAddress := common.HexToAddress(config.HubPool)
164+
hubPoolContract = contracts.NewHubPoolContract(client, hubPoolAddress, config.Tokens)
165+
}
154166
}
155167
default:
156168
panic(fmt.Errorf("type '%s' not recognized", chainConfig["type"]))
@@ -182,6 +194,7 @@ func Run() error {
182194
communication,
183195
keyshareStore,
184196
priceAPI,
197+
hubPoolContract,
185198
sigChn,
186199
config.Tokens,
187200
config.ConfirmationsByValue,

chains/evm/calls/consts/across.go

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,35 @@ import (
66
"github.com/ethereum/go-ethereum/accounts/abi"
77
)
88

9+
var HubPoolABI, _ = abi.JSON(strings.NewReader(`
10+
[
11+
{
12+
"inputs": [
13+
{
14+
"internalType": "uint256",
15+
"name": "destinationChainId",
16+
"type": "uint256"
17+
},
18+
{
19+
"internalType": "address",
20+
"name": "l1Token",
21+
"type": "address"
22+
}
23+
],
24+
"name": "poolRebalanceRoute",
25+
"outputs": [
26+
{
27+
"internalType": "address",
28+
"name": "destinationToken",
29+
"type": "address"
30+
}
31+
],
32+
"stateMutability": "view",
33+
"type": "function"
34+
}
35+
]
36+
`))
37+
938
var SpokePoolABI, _ = abi.JSON(strings.NewReader(`
1039
[
1140
{
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
// The Licensed Work is (c) 2022 Sygma
2+
// SPDX-License-Identifier: LGPL-3.0-only
3+
4+
package contracts
5+
6+
import (
7+
"fmt"
8+
"math/big"
9+
10+
"github.com/ethereum/go-ethereum/accounts/abi"
11+
"github.com/ethereum/go-ethereum/common"
12+
"github.com/sprintertech/sprinter-signing/chains/evm"
13+
"github.com/sprintertech/sprinter-signing/chains/evm/calls/consts"
14+
"github.com/sygmaprotocol/sygma-core/chains/evm/client"
15+
"github.com/sygmaprotocol/sygma-core/chains/evm/contracts"
16+
)
17+
18+
type HubPoolContract struct {
19+
contracts.Contract
20+
client client.Client
21+
tokens map[string]evm.TokenConfig
22+
}
23+
24+
func NewHubPoolContract(
25+
client client.Client,
26+
address common.Address,
27+
l1Tokens map[string]evm.TokenConfig,
28+
) *HubPoolContract {
29+
return &HubPoolContract{
30+
Contract: contracts.NewContract(address, consts.HubPoolABI, nil, client, nil),
31+
client: client,
32+
tokens: l1Tokens,
33+
}
34+
}
35+
36+
func (c *HubPoolContract) DestinationToken(destinationChainId *big.Int, symbol string) (common.Address, error) {
37+
tokenConfig, ok := c.tokens[symbol]
38+
if !ok {
39+
return common.Address{}, fmt.Errorf("no hub pool token configured for symbol %s", symbol)
40+
}
41+
42+
res, err := c.CallContract("poolRebalanceRoute", destinationChainId, tokenConfig.Address)
43+
if err != nil {
44+
return common.Address{}, err
45+
}
46+
47+
out := *abi.ConvertType(res[0], new(common.Address)).(*common.Address)
48+
if out.Hex() == (common.Address{}).Hex() {
49+
return common.Address{}, fmt.Errorf("rebalance route not configured for %s", symbol)
50+
}
51+
52+
return out, nil
53+
}

chains/evm/config.go

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ type EVMConfig struct {
2525
GeneralChainConfig chain.GeneralChainConfig
2626
Admin string
2727
AcrossPool string
28+
HubPool string
2829
LiqudityPool string
2930
Tokens map[string]TokenConfig
3031
// usd bucket -> confirmations
@@ -38,6 +39,7 @@ type RawEVMConfig struct {
3839
Admin string `mapstructure:"admin"`
3940
LiqudityPool string `mapstructure:"liquidityPool"`
4041
AcrossPool string `mapstructure:"acrossPool"`
42+
HubPool string `mapstructure:"hubPool"`
4143
Tokens map[string]interface{} `mapstructure:"tokens"`
4244
ConfirmationsByValue map[string]interface{} `mapstructure:"confirmationsByValue"`
4345
BlockInterval int64 `mapstructure:"blockInterval" default:"5"`
@@ -105,12 +107,13 @@ func NewEVMConfig(chainConfig map[string]interface{}) (*EVMConfig, error) {
105107
confirmations[usd] = confirmation
106108
}
107109

108-
c.GeneralChainConfig.ParseFlags()
110+
c.ParseFlags()
109111
config := &EVMConfig{
110112
GeneralChainConfig: c.GeneralChainConfig,
111113
Admin: c.Admin,
112114
LiqudityPool: c.LiqudityPool,
113115
AcrossPool: c.AcrossPool,
116+
HubPool: c.HubPool,
114117
// nolint:gosec
115118
BlockRetryInterval: time.Duration(c.BlockRetryInterval) * time.Second,
116119
BlockInterval: big.NewInt(c.BlockInterval),

chains/evm/config_test.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,7 @@ func (s *NewEVMConfigTestSuite) Test_ValidConfigWithCustomTxParams() {
109109
"admin": "adminAddress",
110110
"liquidityPool": "pool",
111111
"acrossPool": "acrossPool",
112+
"hubPool": "hubPool",
112113
"maxGasPrice": 1000,
113114
"gasMultiplier": 1000,
114115
"gasIncreasePercentage": 20,
@@ -158,6 +159,7 @@ func (s *NewEVMConfigTestSuite) Test_ValidConfigWithCustomTxParams() {
158159
Admin: "adminAddress",
159160
LiqudityPool: "pool",
160161
AcrossPool: "acrossPool",
162+
HubPool: "hubPool",
161163
ConfirmationsByValue: expectedBlockConfirmations,
162164
Tokens: expectedTokens,
163165
})

chains/evm/message/across.go

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ import (
3131
const (
3232
AcrossMessage = "AcrossMessage"
3333

34+
ZERO_HASH = "0000000000000000000000000000000000000000000000000000000000000000"
3435
DOMAIN_NAME = "LiquidityPool"
3536
VERSION = "1.0.0"
3637
PROTOCOL_ID = 1
@@ -72,13 +73,18 @@ type TokenPricer interface {
7273
TokenPrice(symbol string) (float64, error)
7374
}
7475

76+
type TokenMatcher interface {
77+
DestinationToken(destinationChainId *big.Int, symbol string) (common.Address, error)
78+
}
79+
7580
type AcrossMessageHandler struct {
7681
client EventFilterer
7782
chainID uint64
7883

7984
tokens map[string]evm.TokenConfig
8085
confirmations map[uint64]uint64
8186
blocktime time.Duration
87+
tokenMatcher TokenMatcher
8288
tokenPricer TokenPricer
8389
pools map[uint64]common.Address
8490

@@ -87,7 +93,7 @@ type AcrossMessageHandler struct {
8793
comm comm.Communication
8894
fetcher signing.SaveDataFetcher
8995

90-
sigChn chan interface{}
96+
sigChn chan any
9197
}
9298

9399
func NewAcrossMessageHandler(
@@ -99,7 +105,8 @@ func NewAcrossMessageHandler(
99105
comm comm.Communication,
100106
fetcher signing.SaveDataFetcher,
101107
tokenPricer TokenPricer,
102-
sigChn chan interface{},
108+
tokenMatcher TokenMatcher,
109+
sigChn chan any,
103110
tokens map[string]evm.TokenConfig,
104111
confirmations map[uint64]uint64,
105112
blocktime time.Duration,
@@ -117,6 +124,7 @@ func NewAcrossMessageHandler(
117124
confirmations: confirmations,
118125
blocktime: blocktime,
119126
tokenPricer: tokenPricer,
127+
tokenMatcher: tokenMatcher,
120128
}
121129
}
122130

@@ -237,6 +245,15 @@ func (h *AcrossMessageHandler) minimalConfirmations(d *events.AcrossDeposit) (ui
237245
return 0, err
238246
}
239247

248+
if common.Bytes2Hex(d.OutputToken[:]) == ZERO_HASH {
249+
address, err := h.tokenMatcher.DestinationToken(d.DestinationChainId, symbol)
250+
if err != nil {
251+
return 0, err
252+
}
253+
254+
d.OutputToken = common.BytesToHash(address.Bytes())
255+
}
256+
240257
price, err := h.tokenPricer.TokenPrice(symbol)
241258
if err != nil {
242259
return 0, err

0 commit comments

Comments
 (0)