# Testing xDai upgrade
### Contracts that will be upgraded
- [xDai] HomeBridgeErcToNative
- [Mainnet] ForeignBridgeErcToNative
- [Mainnet] BridgeValidators (`isValidatorDuty` is needed)
- (not considered)[xDai] BridgeValidators - actually not required but could be done for consistency
### Preparation of new contracts
1. Get implementation of current contracts on home and foreign:
* Proxys
* Bridge
* Validators
2. Generate flat contracts for last versions of contracts.
3. Compare current contracts and last version:
* Proxy: to check if new implementations (bridge and validators) are still compatible to the deployed proxy.
* Validators: Compare `initialize` methods to find which parameters need to be initialized in a method to be called as part of the upgrade. (we changed how we store the validators).
* Bridge: Compare `initialize` methods and previous `upgradeTo*` methods to find which parameters need to be initialized to work with the new code.
4. Prepare migration methods if needed to be call as part of `upgradeToAndCall` for:
* HomeBridgeErcToNative
* ForeignBridgeErcToNative
* BridgeValidators
5. Include the new methods in the flat contracts of last version.
* BridgeValidators: added migration method to create list of validators. Gist: https://gist.github.com/patitonar/fe4888e786e9b6cdbfaeedaf8fe99b78
```javascript
function upgradeToV230() public {
bytes32 upgradeStorage = 0x2e8a0420c66b3c19df2ac1cd4ffadb5637da547c6fd49388c7fe28dc8c13a8dd; // keccak256(abi.encodePacked('isUpgradedToV230'))
require(!boolStorage[upgradeStorage]);
address validator1 = 0x9ad83402C19Af24F76afa1930a2B2EEC2F47A8C5;
address validator2 = 0x4D1c96B9A49C4469A0b720a22b74b034EDdFe051;
address validator3 = 0x491FC792e78CDadd7D31446Bb7bDDef876a69AD6;
address validator4 = 0xc073C8E5ED9Aa11CF6776C69b3e13b259Ba9F506;
setNextValidator(F_ADDR, validator1);
setNextValidator(validator1, validator2);
setNextValidator(validator2, validator3);
setNextValidator(validator3, validator4);
setNextValidator(validator4, F_ADDR);
boolStorage[upgradeStorage] = true;
}
```
* HomeBridgeErcToNative: no migration method required. Gist: https://gist.github.com/patitonar/a19287408dfa878d7be1dca95835625f
* ForeignBridgeErcToNative: added migration method https://gist.github.com/patitonar/c0b77a59eceb76aad05e010c40569d47
```javascript
function upgradeToV250() public {
bytes32 upgradeStorage = 0x221181d03d3c423368b412861518cd98276a115f4c2d9594ab6697d90fc99c19; // keccak256(abi.encodePacked('isUpgradedToV250'))
require(!boolStorage[upgradeStorage]);
uintStorage[DAILY_LIMIT] = 100000 ether;
emit DailyLimitChanged(100000 ether);
uintStorage[MIN_PER_TX] = 5000000000000000;
_setBridgeContractOnOtherSide(0x7301CFA0e1756B71869E93d4e4Dca5c7d0eb0AA6);
boolStorage[upgradeStorage] = true;
}
```
### Testing strategy
I see two approaches on how to test the upgrade:
1. Recreate current state of contracts in Sokol and Kovan. This is how we did it so far in previous upgrade tests. Steps:
* Deploy block reward mock and send some sPoa in Sokol.
* Deploy current Proxy contract for validators contract (Sokol and Kovan).
* Deploy current validators contract implementation and initialize it (Sokol and Kovan).
* Deploy current Proxy contract for bridge contract (Sokol and Kovan).
* Deploy current bridge contract implementation and initialize it (Sokol and Kovan).
* Mint Sai and Dai using makerDAO tools in Kovan.
Also, it will be needed to replace hardcoded addresses in the last version of the contract for migration, sai, and saiTop contracts with addresses in Kovan provided by makerDAO.
2. Use `ganache-cli` to fork xDai and Mainnet on local nodes using `--fork` parameter and impersonate any EOA or contracts address (such as multisigwallets) using `--unlock` parameter. The advantages of this is that we do not need to spend time recreating the current state in testnets (and we can easily start over agaian) and we will be sure no human error or assumption is introduced when recreating the current state since we will be using the real contracts. The only extra step required will be to add a new validator and change required signatures to 1 in both sides in order process the transfer using the oracle. Also look for some accounts that has SAI and/or DAI tokens.
Example of how to run `ganache-cli` unlocking owner account of the bridge contract:
```
ganache-cli --fork https://mainnet.infura.io/v3/INFURA_KEY --unlock "0xff1a8EDA5eAcdB6aAf729905492bdc6376DBe2dd"
ganache-cli --fork https://dai.poa.network --unlock "0x0d3726e5a9f37234d6b55216fc971d30f150a60f"
```
You can read more about this in https://github.com/trufflesuite/ganache-cli
I found about this testing upgrade strategy in https://blog.openzeppelin.com/testing-real-world-contract-upgrades/
### Testing steps
0. Start with the current state of the contracts and start the last version of oracle, monitor and ui
* make sure no errors are present in all components
* check all workers are running in oracle
* check ui display information about contracts, authorities and statistics
1. Transfer tokens in both directions.
2. Get current state of foreign BridgeValidators
* isInitialized
* validatorCount
* requiredSignatures
* deployedAtBlock
* owner
* isValidator (for each validator)
3. Upgrade BridgeValidators in foreign
* Deploy new implementation contract
* call `upgradeToAndCall` from proxy calling the migration method.
* check variables from step 2
* reload ui page and check authorities information is correct
* check isValidatorDuty call works
* check validatorList call works
* Transfer tokens in both directions
4. Get current state of HomeBridgeErcToNative
* totalBurntCoins
* isInitialized
* requiredBlockConfirmations
* blockRewardContract
* validatorContract
* owner
* deployedAtBlock
* upgradeabilityAdmin
* minPerTx
* maxPerTx
* dailyLimit
* executionMaxPerTx
* executionDailyLimit
* gasPrice
5. Upgrade HomeBridgeErcToNative in home
* Deploy new implementation contract
* call `upgradeTo` from proxy
* check variables from step 4
* reload ui page and check contract information is correct
* Transfer tokens in both directions
* Test sending a zero transfer from Foreign to home
* Test calling relayTokens in home specifying an alternative receiver
* restart oracle to reprocess previous blocks and check no previous transfer is re-processed
* check monitor results
6. Get current state of ForeignBridgeErcToNative
* isInitialized
* requiredBlockConfirmations
* validatorContract
* owner
* deployedAtBlock
* upgradeabilityAdmin
* maxPerTx
* executionMaxPerTx
* executionDailyLimit
* gasPrice
7. Upgrade ForeignBridgeErcToNative in foreign
* Deploy new implementation contract
* call `upgradeToAndCall` from proxy calling the migration method.
* check variables from step 6
* check dailyLimit
* check minPerTx
* check bridgeOnOtherSide
* reload ui page and check contract information is correct
* Transfer tokens in both directions
* Check half-duplex-token watcher didn't process the transfer
* Test calling relayTokens to specify an alternative receiver
* restart oracle to reprocess previous blocks and check no previous transfer is re-processed
* check monitor results
8. Call `migrateToMCD`
* Check oracle watchers start automatically listening to the new token address
* Transfer tokens from home to foreign
* Check DAI is transferred to user
* Transfer small amount of SAI to bridge
* Check it is minted in xDai
* Transfer DAI to bridge
* Check it is minted in xDai
* Transfer a big amount of SAI to bridge that will cause balance to be above the threshold
* Check xDai is minted and `swapTokens` is called by the oracle worker
* Call `relayTokens` using SAI
* Check correct amount of xDai is minted to the correct receiver
* Call `relayTokens` using DAI
* Check correct amount of xDai is minted to the correct receiver
* check monitor results
9. Test Emergency Shutdown. This is only possible if strategy 2 (fork mainnet) is used and if we are able to find an address that can invoke the method to trigger the Emergency Shutdown.
* Call `cage()` from SaiTop contract https://etherscan.io/address/0x9b0ccf7C8994E19F39b2B4CF708e0A7DF65fA8a3#code
* Transfer SAI to the bridge
* Check it not processed by the oracle
* Check monitor results
10. Test claimTokens method
11. Test fixAssetsAboveLimits