Skip to content
Open
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
Original file line number Diff line number Diff line change
Expand Up @@ -289,6 +289,7 @@ void _remove(BigInteger _id, NetworkAddress _user, BigInteger _value, @Optional
require(_value.compareTo(userBalance) <= 0, TAG + ": Insufficient balance");

Address quoteToken = poolQuote.get(_id.intValue());
require(!baseToken.equals(quoteToken), TAG + ": Invalid same-token pool, removal blocked");
DictDB<Address, BigInteger> totalTokensInPool = poolTotal.at(_id.intValue());
BigInteger totalBase = totalTokensInPool.get(baseToken);
BigInteger totalQuote = totalTokensInPool.get(quoteToken);
Expand Down Expand Up @@ -350,7 +351,7 @@ public void addInternal(NetworkAddress _from, Address _baseToken, Address _quote
// If none is found (return 0), we create a new pool.
Integer id = poolId.at(_baseToken).getOrDefault(_quoteToken, 0);

require(_baseToken != _quoteToken, TAG + ": Pool must contain two token contracts");
require(!_baseToken.equals(_quoteToken), TAG + ": Pool must contain two token contracts");
// Check base/quote balances are valid
require(_baseValue.compareTo(BigInteger.ZERO) > 0,
TAG + ": Cannot send 0 or negative base token");
Expand Down
39 changes: 39 additions & 0 deletions recovery/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
# Incident recovery — governance execute batch

`governance-execute.json` is a Governance `execute(transactions)` batch (ArbitraryCallManager
format: `[{address, method, parameters:[{type,value}], value}]`) that contains the protocol
while the DEX same-token fix in this PR is deployed. It targets contracts owned by Balanced
Governance (`cx44250a…`), so the calls pass their `onlyOwner`/`onlyGovernance` checks. All 58
actions are admin/config setters and run fine while the protocol is under global shutdown.

## What it does (58 actions)

- **Block cross-chain transfers** — `setSpokeLimit(net, 0)` on **bnUSD** (12 chains) and **BALN**
(10 chains). `HubTokenImpl.crossTransfer` has no `checkStatus`, so bridging works even during
the shutdown; zeroing the spoke limits is what actually stops it. (`removeChain` only edits the
`connectedChains` list, not `spokeContracts`/`spokeLimits`, so it does **not** block bridging.)
- **Loans lockdown** — `setRedemptionExemption(token, true)` ×18 disables redemption for every
collateral, which neutralizes the `redeemCollateral` decimals bug **config-side (no Loans
redeploy)**; `setDebtCeiling(symbol, 0)` ×18 blocks new borrows. `repay` / `withdraw` /
`liquidate` remain available (verified decimals-safe in the deployed v1.3.0).

## Sequence

1. Execute this batch (works under the current global shutdown).
2. Deploy the DEX **v1.1.9** upgrade (this PR).
3. `enable()` on Governance to lift the shutdown — migration + repayment resume; redeem, borrow,
and bridging stay blocked by the settings above.

## Not covered here — owned by OMM, not Balanced Governance

- **sICX cross-chain block** (`setSpokeLimit(net, 0)` on sICX) and the **Staking exchange-rate
fix** (it divides by native `totalSupply` instead of `xTotalSupply`, so bridged sICX inflates
the rate). sICX and the staking manager are owned by a separate account — these must be done by
OMM.

## Notes

- **Redemption stays disabled** until a corrected Loans is shipped (fix `redeemCollateral` to use
`10^tokenDecimals` instead of hardcoded `EXA`, matching `_liquidate`/`removeCollateral`). The
exemptions are load-bearing — **do not clear them before that fix**, or the decimals bug
re-arms (10^(18−d)× over-payout on sub-18-decimal collateral such as SUI/SOL/XLM).
Loading
Loading