# GC withdrawal contract
## Background
From [Spec Gnosis Chain withdrawals #1](https://github.com/gnosischain/specs/pull/1)
- During block processing, state transition must call `WITHDRAWAL_CONTRACT` function
```solidity
function withdrawals(uint64[] amounts, address[] addresses)
```
- If transaction reverts, the block is invalid. So if a specific state (i.e. not enough funds) causes a revert in all cases, the network halts
## Deposit flow
1. Bridge GNO from mainnet to Gnosis Chain
2. Swap GNO for mGNO
3. Deposit mGNO to deposit contract
Contract deployments
- GBC deposit contract on xDai Mainnet ([ref](https://github.com/gnosischain/configs/blob/3a571e1c3e753757ccbde13fdbef51eb6930ba23/mainnet/config.yaml#L59)): [`0x0B98057eA310F4d31F2a452B414647007d1645d9`](https://gnosisscan.io/address/0x0b98057ea310f4d31f2a452b414647007d1645d9). Contract source at: [gnosischain/deposit-contract](https://github.com/gnosischain/deposit-contract/blob/c7217fccac3049901f78547f4024127fa1dcdcd4/contracts/SBCDepositContract.sol#L52)
- mGNO contract on Gnosis [`0x722fc4DAABFEaff81b97894fC623f91814a1BF68`](https://gnosisscan.io/address/0x722fc4DAABFEaff81b97894fC623f91814a1BF68)
- SBC wrapper proxy mGNO [`0x647507A70Ff598F386CB96ae5046486389368C66`](https://blockscout.com/xdai/mainnet/address/0x647507A70Ff598F386CB96ae5046486389368C66/contracts#address-tabs)
- GNO token on xDAI [`0x9C58BAcC331c9aa871AFD802DB6379a98e80CEdb`](https://blockscout.com/xdai/mainnet/token/0x9C58BAcC331c9aa871AFD802DB6379a98e80CEdb/token-transfers)
## Withdrawal flow
If the system transaction reverts due to lack of funds the chain halts. If the system is temporarily insolvent, which transaction should revert and when? To ensure the contract never reverts:
- Allow the contract to mint some token, so it never runs out of funds
- Queue the withdrawal action for latter processing with chosen mechanism
- Add indirection, require the user to claim funds with a transaction that can safely revert
- (unsafe) always pre-fund with maximum possible withdrawn value. This in potentially impossible since the deposit flow is unbounded given long enough timescales
### Flow A: auto-transfer + queue
- System transaction:
- Execution client calls withdrawal contract
- Withdrawal contract calls checks for mGNO solvency:
- If solvent:
- Clear max of X pending withdrawals from queued state, then
- `transfer` on mGNO contract to target address, or
- (optional) withdrawal contract unwraps mGNO to GNO and transfers GNO to target address
- If insolvent:
- Add block's withdrawals to pending withdrawals contract state
Withdrawal contract must be pre-funded but lack of funds do not halt the chain. After a period of insolvency, queue is cleared automatically during block processing. No input is required by users in any case.
### Flow B: user initiated claim
- System transaction:
- Execution client calls withdrawal contract
- Withdrawal contract adds allowance to target address for withdrawal amount
- User transaction
- User calls `claim` on withdrawal contract
- (optional) withdrawal contract unwraps mGNO to GNO and transfers to user
If the system is not properly funded the second transaction will revert, but the chain will not halt. Requires an action on the user to obtain the funds. Allows the user to choose to claim mGNO or GNO.
### Flow C: mGNO mint
- System transaction:
- Execution client calls withdrawal contract
- Withdrawal contract mints mGNO to target address
- 2.1. User unwraps mGNO to GNO (reverts if wrapper contract insolvent)
## Source of funds
_Numbers from Jan 26 2023_
- SBC wrapper proxy mGNO: holds wrapped GNO (145,337 GNO ~ 15,382,523 USD)
- Deposit contract: holds staked mGNO (3,646,880 mGNO ~ 113,965 GNO). BTW: where is the rest of mGNO from the wrapper?
- GNO on xDAI: current supply = 363,927.033 GNO
### Reward payout solvency estimation
Withdrawal contract should have access to the deposit contract such that the principal of the stake is always available.
Staking rewards must be supplied externally. This section estimates their upper bound:
- Deposit inflows are technically unbounded in the Gnosis Chain. The practical upper bound is the entire supply of GNO.
- TODO: APY estimation for Gnosis Beacon Chain
# Withdrawal contract
- System transaction that unwraps automatically to GNO
- There should be an admin variable to switch to not unwrap
- In the case the transfer fails, store withdrawable amount in a map. That value is claimable by the withdrawee, but can triggered by anyone
- The WITHDRAWAL_CONTRACT = DEPOSIT_CONTRACT, to prevent need of allowances
- WITHDRAWAL_CONTRACT may never became insolvent, as its a ponzi new deposit inflows pay for outflows, deposit contract balance may not
- There must exist a way to topup the contract without triggering a deposit