-
Notifications
You must be signed in to change notification settings - Fork 29
feat(v11): add elys xrp withdrawal #147
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
AdriaCarrera
merged 10 commits into
xrplevm:main
from
aluque-peersyst:feat/add-elys-icb-blocked-xrp-withdrawal
Jun 23, 2026
Merged
Changes from all commits
Commits
Show all changes
10 commits
Select commit
Hold shift + click to select a range
a27f281
feat(v11): add elys xrp withdrawal
aluque-peersyst e11fcf5
fix(v11): guard elys escrow withdrawal against total-escrow underflow
aluque-peersyst d91d002
feat(v11): withdraw full Elys escrow per network
aluque-peersyst 7c393a5
refactor(v11): withdraw Elys escrow via UnescrowCoin
aluque-peersyst ffa64c6
Merge main into feat/add-elys-icb-blocked-xrp-withdrawal
aluque-peersyst dd1ad24
test(poa): align AddValidator should_pass mock with delegator-form un…
aluque-peersyst bf9b17b
Merge origin/main into feat/add-elys-icb-blocked-xrp-withdrawal
aluque-peersyst c454506
Merge origin/feat/add-elys-icb-blocked-xrp-withdrawal
aluque-peersyst 928a00b
feat(v11): added correct unescrow values for devnet, testnet, and mai…
aluque-peersyst 0eb371d
refactor(v11): define coin by chain instead of amount
aluque-peersyst File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,5 +1,59 @@ | ||
| package v11 | ||
|
|
||
| import ( | ||
| sdkmath "cosmossdk.io/math" | ||
| sdk "github.com/cosmos/cosmos-sdk/types" | ||
| ) | ||
|
|
||
| const ( | ||
| UpgradeName = "v11.0.0" | ||
| UpgradeName = "v11.0.0" | ||
| EVMCoinDenom = "axrp" | ||
|
|
||
| // mainnet | ||
| MainnetChainID = "xrplevm_1440000-1" | ||
| ElysChannelID = "channel-1" | ||
| WithdrawalAddress = "ethm1m2pp8zjwk3ystxyxvw5h3mrhhhnzcr2ltjntz9" | ||
|
|
||
| // testnet | ||
| TestnetChainID = "xrplevm_1449000-1" | ||
| TestnetElysChannelID = "channel-17" | ||
| TestnetWithdrawalAddress = "ethm16gt28px9q0fp48eatecp7j032lm5vaxs2t29pa" | ||
|
|
||
| // devnet | ||
| DevnetChainID = "xrplevm_1449900-1" | ||
| DevnetElysChannelID = "channel-4" | ||
| DevnetWithdrawalAddress = "ethm16gt28px9q0fp48eatecp7j032lm5vaxs2t29pa" | ||
| ) | ||
|
|
||
| var devnetAmount, _ = sdkmath.NewIntFromString("2000000000000000000") | ||
| var testnetAmount, _ = sdkmath.NewIntFromString("2000000000000000000") | ||
| var mainnetElysAmount, _ = sdkmath.NewIntFromString("6955539034646993768414") | ||
|
|
||
| // ElysRecovery holds, for a single network, the Elys transfer channel whose | ||
| // escrow holds the stranded XRP, the address that should receive it, and the | ||
| // coin (denom + amount of XRP in axrp base units) to unescrow. | ||
| type ElysRecovery struct { | ||
| ChannelID string | ||
| WithdrawalAddress string | ||
| Coin sdk.Coin | ||
| } | ||
|
|
||
| // ElysRecoveryByNetwork maps each network's Cosmos chain ID to its Elys recovery | ||
| // parameters. The v11 handler selects the entry matching ctx.ChainID(). | ||
| var ElysRecoveryByNetwork = map[string]ElysRecovery{ | ||
| MainnetChainID: { | ||
| ChannelID: ElysChannelID, | ||
| WithdrawalAddress: WithdrawalAddress, | ||
| Coin: sdk.NewCoin(EVMCoinDenom, mainnetElysAmount), | ||
| }, | ||
| TestnetChainID: { | ||
| ChannelID: TestnetElysChannelID, | ||
| WithdrawalAddress: TestnetWithdrawalAddress, | ||
| Coin: sdk.NewCoin(EVMCoinDenom, testnetAmount), | ||
| }, | ||
| DevnetChainID: { | ||
| ChannelID: DevnetElysChannelID, | ||
| WithdrawalAddress: DevnetWithdrawalAddress, | ||
| Coin: sdk.NewCoin(EVMCoinDenom, devnetAmount), | ||
| }, | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🩺 Stability & Availability | 🟠 Major
🧩 Analysis chain
🌐 Web query:
In cosmos/ibc-go v10.4.0, does TransferKeeper.UnescrowCoin return an error or panic when the coin amount exceeds the escrow account balance or the TotalEscrowForDenom counter?💡 Result:
In ibc-go v10.4.0, the TransferKeeper.UnescrowCoin function does not explicitly check if the coin amount exceeds the escrow account balance or the TotalEscrowForDenom counter; instead, it relies on the underlying BankKeeper and Cosmos SDK arithmetic to handle these operations, which leads to different outcomes [1][2]. 1. Escrow Account Balance: The function calls k.BankKeeper.SendCoins to move tokens from the escrow address to the receiver [1][2]. If the escrow account has insufficient balance to cover the requested amount, the BankKeeper.SendCoins method will return an error [1]. In this case, UnescrowCoin wraps and returns that error, rather than panicking [1][2]. 2. TotalEscrowForDenom Counter: After sending the coins, the function calls currentTotalEscrow.Sub(coin) [1][2]. If the coin amount exceeds the current total escrow stored in the state, the Cosmos SDK's Int.Sub method (or similar Sub operation on the Coin type) will typically panic if it results in a negative amount [3]. While the code tracks escrow, it assumes the operation is valid based on the successful bank transfer; if the escrow state becomes inconsistent (e.g., if more tokens are unescrowed than were ever escrowed due to a malicious counterparty), this subtraction operation will trigger a panic [1][2]. The documentation explicitly notes that if a negative amount is ever attempted to be stored, the keeper function will panic [3]. Therefore, while the function handles bank-level insufficient funds via error propagation, an inconsistency between the actual escrowed tokens and the tracked TotalEscrowForDenom state will lead to a panic during the subtraction step [1][3].
Citations:
🏁 Script executed:
Repository: xrplevm/node
Length of output: 3734
🏁 Script executed:
Repository: xrplevm/node
Length of output: 2047
🏁 Script executed:
Repository: xrplevm/node
Length of output: 150
🏁 Script executed:
Repository: xrplevm/node
Length of output: 150
🏁 Script executed:
# Look at the constants file to see ElysRecoveryByNetwork and related values cat -n app/upgrades/v11/constants.goRepository: xrplevm/node
Length of output: 2372
🏁 Script executed:
Repository: xrplevm/node
Length of output: 150
🌐 Web query:
cosmos/evm GetEVMCoinDenom what denom does it return💡 Result:
In the Cosmos EVM module, the function
GetEVMCoinDenom()returns the base denomination (a string) used as the native EVM token for the chain [1][2]. This value represents the specific token denomination from the bank module that is used for EVM state transitions, gas consumption, and other native EVM operations [3][4]. By default, this is typically set to "uatom" [5][3], but it is a configurable parameter that must match the chain's native staking and minting denominations [3][6]. It is important to distinguish this from other denominations used in the module: - GetEVMCoinDenom: Returns the base denomination (e.g., "uatom") [1][2]. - GetEVMCoinExtendedDenom: Returns the extended denomination used for 18-decimal representation if configured [2]. - GetEVMCoinDisplayDenom: Returns the human-readable display denomination (e.g., "atom") [2].Citations:
🏁 Script executed:
Repository: xrplevm/node
Length of output: 353
Remove unused
bankKeeperparameter or apply balance safety cap beforeUnescrowCoin.The function passes
bankKeeperbut never invokesGetBalanceto cap the withdrawal. With a hardcodedrecoveryCfg.Amount, the code relies on that value exactly matching the on-chain stranded balance:recoveryCfg.Amountexceeds the escrow account's balance for the denom,UnescrowCoinreturns an error and the upgrade halts.recoveryCfg.Amountexceeds the trackedTotalEscrowForDenom, the subtraction panics during the upgrade.recoveryCfg.Amountis less than the actual stranded balance, funds remain stranded.For mainnet,
mainnetElysAmountis hardcoded to"6955539034646993768414"with a comment claiming it is the "exact XRP stranded." Confirm this value precisely matches the on-chain Elys channel escrow balance at upgrade height. If the hardcoded amount is intentional, remove the now-deadbankKeeperparameter and its interface wiring. Otherwise, re-introducebankKeeper.GetBalanceto safely cap the amount.Also verify that
evmtypes.GetEVMCoinDenom()returns the exact denomination held in the Elys channel escrow account, otherwiseUnescrowCoinwill operate on the wrong denom.🤖 Prompt for AI Agents