Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,11 @@
* [3426](https://github.com/zeta-chain/node/pull/3426) - use protocol contracts V2 with Bitcoin deposits
* [3326](https://github.com/zeta-chain/node/pull/3326) - improve error messages for cctx status object
* [3418](https://github.com/zeta-chain/node/pull/3418) - orchestrator V2: TON observer-signer
* [3432](https://github.com/zeta-chain/node/pull/3432) - use protocol contracts V2 with Solana deposits
* [3438](https://github.com/zeta-chain/node/pull/3438) - orchestrator V2: SOl observer-signer. Drop V1.
* [3440](https://github.com/zeta-chain/node/pull/3440) - remove unused method `FilterSolanaInboundEvents`
* [3428](https://github.com/zeta-chain/node/pull/3428) - zetaclient: converge EVM clients.


### Fixes

* [3374](https://github.com/zeta-chain/node/pull/3374) - remove minimum rent exempt check for SPL token withdrawals
Expand Down
92 changes: 67 additions & 25 deletions pkg/contracts/solana/inbound.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package solana
import (
"fmt"

ethcommon "github.com/ethereum/go-ethereum/common"
"github.com/gagliardetto/solana-go"
"github.com/near/borsh-go"
)
Expand All @@ -12,12 +13,15 @@ const (
MaxSignaturesPerTicker = 100
)

// Deposit represents a deposit instruction from a Solana transaction to ZetaChain
type Deposit struct {
Sender string
Amount uint64
Memo []byte
Slot uint64
Asset string
Sender string
Receiver string
Amount uint64
Memo []byte
Slot uint64
Asset string
IsCrossChainCall bool
}

// ParseInboundAsDeposit tries to parse an instruction as a 'deposit' or 'deposit_and_call'.
Expand Down Expand Up @@ -63,12 +67,19 @@ func tryParseAsDeposit(
return nil, err
}

receiver, err := parseReceiver(inst.Receiver)
if err != nil {
return nil, err
}

return &Deposit{
Sender: sender,
Amount: inst.Amount,
Memo: inst.Receiver[:],
Slot: slot,
Asset: "", // no asset for gas token SOL
Sender: sender,
Receiver: receiver,
Amount: inst.Amount,
Memo: []byte{},
Slot: slot,
Asset: "", // no asset for gas token SOL
IsCrossChainCall: false,
}, nil
}

Expand All @@ -93,17 +104,24 @@ func tryParseAsDepositAndCall(
return nil, nil
}

receiver, err := parseReceiver(instDepositAndCall.Receiver)
if err != nil {
return nil, err
}

// get the sender address (skip if unable to parse signer address)
sender, err := getSignerDeposit(tx, &instruction)
if err != nil {
return nil, err
}
return &Deposit{
Sender: sender,
Amount: instDepositAndCall.Amount,
Memo: append(instDepositAndCall.Receiver[:], instDepositAndCall.Memo...),
Slot: slot,
Asset: "", // no asset for gas token SOL
Sender: sender,
Receiver: receiver,
Amount: instDepositAndCall.Amount,
Memo: instDepositAndCall.Memo,
Slot: slot,
Asset: "", // no asset for gas token SOL
IsCrossChainCall: true,
}, nil
}

Expand Down Expand Up @@ -150,12 +168,19 @@ func tryParseAsDepositSPL(
return nil, err
}

receiver, err := parseReceiver(inst.Receiver)
if err != nil {
return nil, err
}

return &Deposit{
Sender: sender,
Amount: inst.Amount,
Memo: inst.Receiver[:],
Slot: slot,
Asset: spl,
Sender: sender,
Receiver: receiver,
Amount: inst.Amount,
Memo: []byte{},
Slot: slot,
Asset: spl,
IsCrossChainCall: false,
}, nil
}

Expand All @@ -180,17 +205,24 @@ func tryParseAsDepositSPLAndCall(
return nil, nil
}

receiver, err := parseReceiver(instDepositAndCall.Receiver)
if err != nil {
return nil, err
}

// get the sender and spl addresses
sender, spl, err := getSignerAndSPLFromDepositSPLAccounts(tx, &instruction)
if err != nil {
return nil, err
}
return &Deposit{
Sender: sender,
Amount: instDepositAndCall.Amount,
Memo: append(instDepositAndCall.Receiver[:], instDepositAndCall.Memo...),
Slot: slot,
Asset: spl,
Sender: sender,
Receiver: receiver,
Amount: instDepositAndCall.Amount,
Memo: instDepositAndCall.Memo,
Slot: slot,
Asset: spl,
IsCrossChainCall: true,
}, nil
}

Expand Down Expand Up @@ -244,3 +276,13 @@ func getSignerAndSPLFromDepositSPLAccounts(

return signer, spl, nil
}

// parseReceiver parses the receiver bytes into a Ethereum address string
func parseReceiver(receiver [20]byte) (string, error) {
addr := ethcommon.BytesToAddress(receiver[:ethcommon.AddressLength])
if addr == (ethcommon.Address{}) {
return "", fmt.Errorf("invalid receiver address: %v", receiver)
}

return addr.Hex(), nil
}
76 changes: 28 additions & 48 deletions pkg/contracts/solana/inbound_test.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package solana

import (
"encoding/hex"
"encoding/json"
"fmt"
"os"
Expand Down Expand Up @@ -55,14 +54,15 @@ func Test_ParseInboundAsDeposit(t *testing.T) {
// solana e2e deployer account
sender := "37yGiHAnLvWZUNVwu9esp74YQFqxU1qHCbABkDvRddUQ"
// solana e2e user evm account
expectedMemo, err := hex.DecodeString("103fd9224f00ce3013e95629e52dfc31d805d68d")
require.NoError(t, err)
expectedDeposit := &Deposit{
Sender: sender,
Amount: 12000000,
Memo: expectedMemo,
Slot: txResult.Slot,
Asset: "",
Sender: sender,
Receiver: "0x103FD9224F00ce3013e95629e52DFc31D805D68d",
Amount: 12000000,
Memo: []byte{},
Slot: txResult.Slot,
Asset: "",
IsCrossChainCall: false,
}

t.Run("should parse inbound event deposit SOL", func(t *testing.T) {
Expand Down Expand Up @@ -159,36 +159,15 @@ func Test_ParseInboundAsDepositAndCall(t *testing.T) {
// expected result
// solana e2e deployer account
sender := "37yGiHAnLvWZUNVwu9esp74YQFqxU1qHCbABkDvRddUQ"
// example contract deployed during e2e test, read from tx result
expectedReceiver := []byte{
117,
160,
106,
140,
37,
135,
57,
218,
223,
226,
53,
45,
87,
151,
61,
239,
158,
231,
162,
186,
}
expectedMsg := []byte("hello lamports")
expectedDeposit := &Deposit{
Sender: sender,
Amount: 1200000,
Memo: append(expectedReceiver, expectedMsg...),
Slot: txResult.Slot,
Asset: "",
Sender: sender,
Receiver: "0x75A06a8C258739dADfe2352D57973deF9ee7A2ba",
Amount: 1200000,
Memo: expectedMsg,
Slot: txResult.Slot,
Asset: "",
IsCrossChainCall: true,
}

t.Run("should parse inbound event deposit SOL and call", func(t *testing.T) {
Expand Down Expand Up @@ -284,15 +263,15 @@ func Test_ParseInboundAsDepositSPL(t *testing.T) {
// expected result
// solana e2e deployer account
sender := "37yGiHAnLvWZUNVwu9esp74YQFqxU1qHCbABkDvRddUQ"
// solana e2e user evm account
expectedMemo, err := hex.DecodeString("103fd9224f00ce3013e95629e52dfc31d805d68d")
require.NoError(t, err)
expectedDeposit := &Deposit{
Sender: sender,
Amount: 12000000,
Memo: expectedMemo,
Slot: txResult.Slot,
Asset: "BTmtL9Dh2DcwhPntEbjo3rSWpmz1EhXsmohSC7CGSEWw", // SPL address
Sender: sender,
Receiver: "0x103FD9224F00ce3013e95629e52DFc31D805D68d",
Amount: 12000000,
Memo: []byte{},
Slot: txResult.Slot,
Asset: "BTmtL9Dh2DcwhPntEbjo3rSWpmz1EhXsmohSC7CGSEWw", // SPL address
IsCrossChainCall: false,
}

t.Run("should parse inbound event deposit SPL", func(t *testing.T) {
Expand Down Expand Up @@ -389,14 +368,15 @@ func Test_ParseInboundAsDepositAndCallSPL(t *testing.T) {
// solana e2e deployer account
sender := "37yGiHAnLvWZUNVwu9esp74YQFqxU1qHCbABkDvRddUQ"
// example contract deployed during e2e test, read from tx result
expectedReceiver := []byte{213, 254, 240, 66, 1, 154, 250, 238, 39, 131, 9, 45, 5, 2, 190, 192, 20, 31, 103, 209}
expectedMsg := []byte("hello spl tokens")
expectedDeposit := &Deposit{
Sender: sender,
Amount: 12000000,
Memo: append(expectedReceiver, expectedMsg...),
Slot: txResult.Slot,
Asset: "7d4ehzE4WNgithQZMyQFDhmHyN6rQNTEC7re1bsRN7TX", // SPL address
Sender: sender,
Receiver: "0xd5Fef042019aFAEe2783092d0502bEc0141f67D1",
Amount: 12000000,
Memo: expectedMsg,
Slot: txResult.Slot,
Asset: "7d4ehzE4WNgithQZMyQFDhmHyN6rQNTEC7re1bsRN7TX", // SPL address,
IsCrossChainCall: true,
}

t.Run("should parse inbound event deposit SPL", func(t *testing.T) {
Expand Down
45 changes: 45 additions & 0 deletions testutil/contracts/Reverter.abi
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,51 @@
"name": "Foo",
"type": "error"
},
{
"inputs": [
{
"components": [
{
"internalType": "bytes",
"name": "origin",
"type": "bytes"
},
{
"internalType": "address",
"name": "sender",
"type": "address"
},
{
"internalType": "uint256",
"name": "chainID",
"type": "uint256"
}
],
"internalType": "struct Reverter.zContext",
"name": "context",
"type": "tuple"
},
{
"internalType": "address",
"name": "zrc20",
"type": "address"
},
{
"internalType": "uint256",
"name": "amount",
"type": "uint256"
},
{
"internalType": "bytes",
"name": "message",
"type": "bytes"
}
],
"name": "onCall",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
Expand Down
2 changes: 1 addition & 1 deletion testutil/contracts/Reverter.bin
Original file line number Diff line number Diff line change
@@ -1 +1 @@
6080604052348015600f57600080fd5b5061027f8061001f6000396000f3fe608060405234801561001057600080fd5b506004361061002b5760003560e01c8063de43156e14610030575b600080fd5b61004a600480360381019061004591906101a5565b61004c565b005b6040517fbfb4ebcf00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600080fd5b600080fd5b600080fd5b6000606082840312156100a3576100a2610088565b5b81905092915050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60006100d7826100ac565b9050919050565b6100e7816100cc565b81146100f257600080fd5b50565b600081359050610104816100de565b92915050565b6000819050919050565b61011d8161010a565b811461012857600080fd5b50565b60008135905061013a81610114565b92915050565b600080fd5b600080fd5b600080fd5b60008083601f84011261016557610164610140565b5b8235905067ffffffffffffffff81111561018257610181610145565b5b60208301915083600182028301111561019e5761019d61014a565b5b9250929050565b6000806000806000608086880312156101c1576101c061007e565b5b600086013567ffffffffffffffff8111156101df576101de610083565b5b6101eb8882890161008d565b95505060206101fc888289016100f5565b945050604061020d8882890161012b565b935050606086013567ffffffffffffffff81111561022e5761022d610083565b5b61023a8882890161014f565b9250925050929550929590935056fea2646970667358221220bc9e93b2d3f5e1969fc6b9d1d00d7fb28bdcb33a4e9f24aeb392acacc895146464736f6c634300081a0033
6080604052348015600f57600080fd5b506102ba8061001f6000396000f3fe608060405234801561001057600080fd5b50600436106100365760003560e01c80635bcfd6161461003b578063de43156e14610057575b600080fd5b610055600480360381019061005091906101e0565b610073565b005b610071600480360381019061006c91906101e0565b6100a5565b005b6040517fbfb4ebcf00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6100b28585858585610073565b5050505050565b600080fd5b600080fd5b600080fd5b6000606082840312156100de576100dd6100c3565b5b81905092915050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000610112826100e7565b9050919050565b61012281610107565b811461012d57600080fd5b50565b60008135905061013f81610119565b92915050565b6000819050919050565b61015881610145565b811461016357600080fd5b50565b6000813590506101758161014f565b92915050565b600080fd5b600080fd5b600080fd5b60008083601f8401126101a05761019f61017b565b5b8235905067ffffffffffffffff8111156101bd576101bc610180565b5b6020830191508360018202830111156101d9576101d8610185565b5b9250929050565b6000806000806000608086880312156101fc576101fb6100b9565b5b600086013567ffffffffffffffff81111561021a576102196100be565b5b610226888289016100c8565b955050602061023788828901610130565b945050604061024888828901610166565b935050606086013567ffffffffffffffff811115610269576102686100be565b5b6102758882890161018a565b9250925050929550929590935056fea2646970667358221220a7ad1881a453cbf7569a6a918894fa032e56cd977fe96c70d0fb9cf9c97d6bc264736f6c634300081a0033
25 changes: 23 additions & 2 deletions testutil/contracts/Reverter.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading