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
4 changes: 2 additions & 2 deletions apps/solana/rpc.go
Original file line number Diff line number Diff line change
Expand Up @@ -223,13 +223,13 @@ func (c *Client) RPCGetTransaction(ctx context.Context, signature string) (*rpc.

func (c *Client) RPCGetMinimumBalanceForRentExemption(ctx context.Context, dataSize uint64) (uint64, error) {
for {
r, err := c.rpcClient.GetMinimumBalanceForRentExemption(ctx, dataSize, rpc.CommitmentProcessed)
r, err := c.rpcClient.GetMinimumBalanceForRentExemption(ctx, dataSize, rpc.CommitmentConfirmed)
if mtg.CheckRetryableError(err) {
time.Sleep(time.Millisecond * 300)
continue
}
if err != nil {
return 0, fmt.Errorf("solana.RPCGetMultipleAccounts() => %v", err)
return 0, fmt.Errorf("solana.GetMinimumBalanceForRentExemption(%d) => %w", dataSize, err)
}
return r, nil
}
Expand Down
42 changes: 21 additions & 21 deletions solana/solana.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,10 +32,21 @@ const (
SolanaBlockDelay = 1
SolanaTxRetry = 10
SolanaMinimumHeight = 442271000

// SOL cleanup uses the historical 165-byte rent minimum as a fixed protocol
// dust threshold, not as a quote for current Solana rent. Observers and
// validators must make the same selection during replay and rent changes.
// Changing this value requires a coordinated protocol upgrade.
solanaCleanupDustLamports uint64 = 2_039_280
)

var errInvalidAddressLookup = errors.New("invalid address lookup")

func isSOLCleanupDust(assetID string, lamports decimal.Decimal) bool {
return assetID == solanaApp.SolanaChainBase &&
lamports.Cmp(decimal.NewFromUint64(solanaCleanupDustLamports)) <= 0
Comment on lines +45 to +47
}

func (node *Node) addressLookupTableLoop(ctx context.Context) {
for {
time.Sleep(time.Minute)
Expand Down Expand Up @@ -390,7 +401,8 @@ func (node *Node) CreateMintTransaction(ctx context.Context, asset string) (stri
})
}

rent, err := node.RPCGetMinimumBalanceForRentExemption(ctx, solanaApp.MintSize)
// Account funding must use current rent rather than the node's cached quote.
rent, err := node.solana.RPCGetMinimumBalanceForRentExemption(ctx, solanaApp.MintSize)
if err != nil {
panic(err)
}
Expand All @@ -412,7 +424,8 @@ func (node *Node) CreateNonceAccount(ctx context.Context, index int) (string, st
return "", "", err
}
if acc == nil {
rent, err := node.RPCGetMinimumBalanceForRentExemption(ctx, solanaApp.NonceAccountSize)
// Account funding must use current rent rather than the node's cached quote.
rent, err := node.solana.RPCGetMinimumBalanceForRentExemption(ctx, solanaApp.NonceAccountSize)
if err != nil {
panic(err)
}
Expand Down Expand Up @@ -548,10 +561,6 @@ func (node *Node) CreatePostProcessTransaction(ctx context.Context, call *store.
}
}

rent, err := node.RPCGetMinimumBalanceForRentExemption(ctx, solanaApp.NormalAccountSize)
if err != nil {
panic(err)
}
var transfers []*solanaApp.TokenTransfer
for _, asset := range assets {
dust := decimal.RequireFromString("0.00000001")
Expand All @@ -563,12 +572,9 @@ func (node *Node) CreatePostProcessTransaction(ctx context.Context, call *store.
if !amount.BigInt().IsUint64() {
continue
}
if asset.AssetId == solanaApp.SolanaChainBase {
limit := decimal.NewFromUint64(rent)
if amount.Cmp(limit) < 1 {
logger.Printf("skip SOL transfer in post-process: %v", asset)
continue
}
if isSOLCleanupDust(asset.AssetId, amount) {
logger.Printf("skip SOL transfer in post-process: %v", asset)
continue
}
transfers = append(transfers, &solanaApp.TokenTransfer{
SolanaAsset: asset.Solana,
Expand Down Expand Up @@ -642,21 +648,15 @@ func (node *Node) buildRefundWithdrawalTransfers(ctx context.Context, prepare, c
assets[a.Address] = a
}

rent, err := node.RPCGetMinimumBalanceForRentExemption(ctx, solanaApp.NormalAccountSize)
if err != nil {
panic(err)
}
var transfers []*solanaApp.TokenTransfer
for _, asset := range assets {
amount := asset.Amount.Mul(decimal.New(1, int32(asset.Decimal)))
if !amount.BigInt().IsUint64() {
continue
}
if asset.AssetId == solanaApp.SolanaChainBase {
if amount.Cmp(decimal.NewFromUint64(rent)) < 1 {
logger.Printf("skip SOL transfer in refund-withdrawal: %v", asset)
continue
}
if isSOLCleanupDust(asset.AssetId, amount) {
logger.Printf("skip SOL transfer in refund-withdrawal: %v", asset)
continue
}
transfers = append(transfers, &solanaApp.TokenTransfer{
SolanaAsset: asset.Solana,
Expand Down
Loading