POA Forum

Migration to MCD for xDai bridge

This documents describes proposals for changes in the TokenBridge contracts, oracle and monitor to start supporting Multi-Collateral Dai (MCD) by the xDai bridge.

The proposals are divided on several sections:

  • Phase 1: Minimal valuable changes
  • Phase 2: Two tokens support

Phase 1: Minimal valuable changes

The changes covered in this section assume that after some moment of time the bridge contracts on the side of the Ethereum Mainnet must swap all Single-Collateral Dai (SCD) to MCD.

Bridge contracts modification

Ethereum Mainnet side

As per the documentation clarifying migration to MCD provided by MakerDAO, the accounts owning SCD must perform two consequent actions:

  • call approve() on the SCD token with the parameters <migration contract address>, <SCD token contract address>.balanceOf(this) (or curBalance)
  • call swapSaiToDai() on the migration contract with the parameter curBalance.

Although these actions could lead to the bridge balance evolution:

  • -curBalance of SCD
  • +curBalance of MCD
    it is not enough for the bridge migration to MCD.

It is necessary also to change the token address in the bridge contract on the Ethereum Mainnet side as so the correct contract was used to unlock tokens when a withdrawal happens. It can be achieved by invoking setErc20token() on the bridge contract. This method is not available for external calls. So, the changing the token address must be performed from a method belonging to the bridge contract.

Bearing in mind facts considered above, the bridge implementation contract must be changed to have a new method migrateToMCD. This method must be permissible to be invoked by the bridge administrators. The method must forbid multiple invocation:

function migrateToMCD(address _migrationContract, address _mcdContract) external onlyOwner {
    bytes32 storageAddress = keccak256(abi.encodePacked("migrationToMcdCompleted"));
    
    require(!boolStorage[storageAddress]);
    require(AddressUtils.isContract(_migrationContract));
    require(AddressUtils.isContract(_mcdContract));

    uint256 curBalance = erc20token().balanceOf(address(this));
    require(erc20token().approve(_migrationContract, curBalance));
    //It is important to note that this action will cause appearing of `Transfer`
    //event as part of the tokens minting
    ScdMcdMigration(_migrationContract).swapSaiToDai(curBalance);
    address saiContract = erc20token();
    setErc20token(_mcdContract);
    require(erc20token().balanceOf(address(this)) == curBalance);

    emit TokensSwapped(saiContract, erc20token(), curBalance);
    boolStorage[storageAddress] = true;
}

xDai chain side

The bridge contract on the xDai chain side has no reference to the token contract so no changes is needed on this side.

Oracle modification

Although the new token address will be picked up automatically after the service restart, the TokenBridge oracle functionality must be updated as well to handle a special case when the Transfer event must not be recognized as a deposit request.

This event will be raised by the method mint() that is executed as part of processing the swap SCD to MCD.

The bridge migration process is organized as so there is no explicit unlock of SCD tokens whereas the new Transfer event appears when MCD tokens are being assigned to the bridge contract account. If no special handling of this event is introduced, the balance of the bridge on the Mainnet Ethereum side will be doubled.

The first property of the migration transaction that can be taken into account in order to filer the event out is the from field logged with the event - it is address(0). But in general such transfers are unusual but legitimate. That is why another property of the transaction must be used. The example of the method migrateMCD presented above uses the new event SaiSwappedToDai. Since the event will be logged together with Transfer event this fact could be used to skip the migration transaction.

So, the oracle watcher responsible for tracking deposit requests in erc20-to-native mode must be updated in the following manner:

const existsSaiSwappedToDaiEvent = receipt.logs.some(
  e => e.topics[0] === userSaiSwappedToDaiHash
)

if (from === "0x0" && existsSaiSwappedToDaiEvent) {
  logger.info(
    `Transfer event discarded because swap SCD to MCD is detected in transaction ${
      transfer.transactionHash
    }`
  )
  return
}

UI modification

No changes required. The new token address and its attributes (name and symbol) will be picked up automatically after the service restart.

Monitor

The case described in the section Oracle modification is also applicable for the TokenBridge monitor otherwise the Transfer event appearing as part of the migration transaction will be considered by the monitor as a deposit request and will lead to report about the bridge imbalance.

In order to avoid accounting the migration transaction in the list of monitoring transactions it is necessary to extend the filter in event.js to skip Transfer events where the field from is 0x0 and the same transaction does not contain the SaiSwappedToDai event.

Upgrade procedure

The new releases containing the changes related to the Phase 1 of the migration have been prepared:

  • TokenBridge contracts - 3.2.0
  • TokenBridge node - 1.1.1

The following steps should be done as part of the procedure to migrate the xDai bridge from SCD tokens to MCD in the phase 1:

  1. Discover if any MCD transfer to the bridge contract happened, write down the block where the first such transfer happened.
  2. The bridge administrators must initiate and complete signing on the xDai chain for the invocation of the setMaxPerTx method with 0 value. Starting from this point the oracles will relay only deposit requests for SCD tokens.
  3. Deploy new implementation of the bridge contract on the Mainnet Ethereum.
  4. The bridge upgradability administrators must initiate and complete signing on the Mainnet Ethereum for the invocation of the upgradeTo (or upgradeAndCall if the feature “Relative daily limits” is included in the new implementation) method. At this point users must be still able to deposit SCD tokens’.
  5. Stop all oracles on every validator node. Starting from this point users will be able initiate SCD transfers to the bridge contracts, but they will not be relayed.
  6. Deploy new implementation of the bridge contract on the xDai chain if it is necessary to include security fixes and enhancements (e.g. the feature “Relative daily limits”).
  7. If the step 6 is applicable, the bridge upgradability administrators must initiate and complete signing on the xDai chain for the invocation of the upgradeTo (or upgradeAndCall) method.
  8. Upgrade oracles on every validator node.
  9. Run the oracles on the validators nodes. Starting from this point the oracles will handle all deposit requests postponed after the step 5.
  10. The bridge administrators must initiate and complete signing on the Ethereum Mainnet chain for the invocation of the migrateToMCD method with addresses of the migration and MCD contracts. Make sure that no oracles are restarted after step 9 since they still serve deposit requests for SCD.
  11. Stop all oracles on every validator node.
  12. Compare the last block numbers observed by every oracle to find a minimal one. Reset the last observed block to the comparison result. If there is any transaction found on the step 1 use the block number that includes this transaction.
  13. Run the oracles on the validators nodes. Starting from this point the oracles will handle all existing deposit requests for MCD tokens.
  14. The bridge administrators must initiate and complete signing on the xDai chain for the invocation of the setMaxPerTx method with an initial value. Starting from this point the oracles handle all withdrawal requests and unlock MCD tokens.
  15. If there is any not relayed transfer request for SCD token in the Ethereum Mainnet after the step 11, the the bridge upgradability administrators must initiate and complete signing for claimTokens to refund SCD tokens to the initial owners.

Warning

Since the bridge oracles will stop watching for transactions to deposit SCD tokens on the xDai bridge these tokens will be locked on the bridge account forever.

The bridge upgradibility administrator could periodically revisit the balance of SCD tokens owned by the bridge contract and initiate refund the tokens by using the claimTokens method.

Another way is to implement separate watcher for SCD tokens operations but it will be described in the section dedicated for the phase 2.

Phase 2: Two tokens support

As per the migration plans provided by MakerDAO both SCD and MCD tokens will exist until the Emergency Shutdown (ES) is performed for SCD. It means that during some period of time the price of both tokens will be equal and users will be able to operates with both token contracts. For the xDai bridge this period of time means that users would like to deposit either SCD or MCD to the xDai chain. There is no any risk for such kind of deposits if the bridge will have opportunity to swap new deposited SCD tokens to MCD before SCD ES.

The phase 2 of MCD token support introduction assumes that the xDai bridge functionality will be changed as so any deposit of either SCD or MCD will cause the mint action of the corresponding amount xDai coins in the xDai chain whereas withdrawal of tokens from the xDai chain will lead to unlocking the corresponding amount of MCD tokens.

The overall idea of supporting deposits for both tokens is the following:

  1. The TokenBridge oracle will watch for Transfer event emitted by SCD and MCD token contracts.
  2. If the event was raised by the MCD token contract the deposit confirmed in the same manner as now.
  3. If the event was raised by the SCD token contract, the oracle checks if SCD ES had happened to this moment. No deposit of SCD will be transferred to the xDai chain after ES.
  4. If SCD ES did not take place, the oracle will relay the deposit to the xDai chain.
  5. Then the oracle invokes the method swapTokens from the bridge contract on the Ethereum Mainnet.
  6. The bridge contract will call swapSaiToDai of the MakerDAO migration contract to swap to MCD tokens entire SCD balance owned by the bridge contract.

In case if tokens are being deposited by using the alternative transfer feature with calling relayTokens the tokens swap will be handled by this method rather than by the oracle.

In order to eliminate the possibility of drying out a validator account by deposit requests with small token values, a threshold for a minimum balance of SCD tokens will be introduced. The oracle will not call swapTokens if the current SCD balance of the bridge account is below this threshold. But in order to reduce the time between SCD deposit and its swap to MCD the call of swapTokens will be done every time when validators confirmations are executed for a withdrawal operation.

Bridge contracts modification

Ethereum Mainnet side

In order to support scenarios described above the following changes are needed to be introduced in the TokenBridge contracts:

  • a new method to check the status of SCD ES
  • a new method to choose the validator to call swapTokens for an appeared deposit
  • a new method to store address of the SCD token contract
  • new methods to set and check the minimal SCD balance threshold
  • the new swapTokens method to swap tokens as per request
  • in the relayTokens logic to swap tokens
  • in the executeSignatures logic to swap tokens
  • in the claimTokens logic to forbit claim the SCD tokens till SCD ES.

Checking status of SCD ES

MakerDAO provides a contract top that manages the global settlement. The public integer caged is set up to a time stamp of the block where SCD ES happens.

The address of the contract in the Ethereum Mainnet is 0x9b0ccf7c8994e19f39b2b4cf708e0a7df65fa8a3. The variable caged is zero before ES.

It means that the next method introduced in the bridge contract will return true if the SCD ES has not been applied to the moment of the time stamp provided as the method parameter.

function isTokenSwapAllowed(uint256 _ts) public view returns(bool) {
    uint256 es_ts = ISaiTop(0x9b0ccf7C8994E19F39b2B4CF708e0A7DF65fA8a3).caged();
    if ((es_ts > 0) && (_ts > es_ts)) {
        return false;
    }
    return true;
}

This method is for contracts/upgradeable_contracts/erc20_to_native/ForeignBridgeErcToNative.sol.

Validator selection

The idea to select the validator to trigger swap for the corresponding deposit of SCD is the following:

  • the validator’s node calls the method isValidatorDuty defined below
  • this method uses the latest block number and the number of the validator in the validatators list to determine if this validator is on duty to perform some actions
  • if the node receives true from the method isValidatorDuty it proceeds with the actions to swap SCD tokens
function isValidatorDuty(address _validator) external view returns(bool) {
    uint256 counter = 0;
    address next = getNextValidator(F_ADDR);
    require(next != address(0));

    while (next != F_ADDR) {
        if (next == _validator) {
            return (block.number % validatorCount() == counter);
        }
        
        next = getNextValidator(next);
        counter++;

        require(next != address(0));
    }

    return false;
}

The method should be incorporated into the validators contract.

Since it will be more than one way to swap SCD tokens during the bridge operations it is safe if the validator is not chosen accidentally by this approach. The balance of SCD tokens could be swapped later when another deposit request is handled or during execution of a withdrawal request.

Storing SCD token address

The current version of the bridge contract on the foreign side stores the bridgeable token contract address and provides it through the public method erc20token(). This method is invoked by the oracle, UI and monitor as so these TokenBridge components could interact with the token contract without necessity to point out its address in the corresponding component configuration.

After the Phase 2 migration the ability to get both SCD and MCD tokens contract addresses from the bridge contract is required.

The new method halfduplexErc20token() will returns the address of SCD contract.

function halfduplexErc20token() public pure returns(ERC20Basic) {
    return(ERC20Basic(0x89d24A6b4CcB1B6fAA2625fE562bDD9a23260359));
}

This method will be located in contracts/upgradeable_contracts/erc20_to_native/ForeignBridgeErcToNative.sol.

Minimal SCD balance threshold

Since the new bridge parameter is introduced, new setter and getter methods must be provided in contracts/upgradeable_contracts/erc20_to_native/ForeignBridgeErcToNative.sol:

function setMinHDTokenBalance(uint256 _minBalance) external onlyOwner {
    uintStorage[MIN_HDTOKEN_BALANCE] = _minBalance;
}

function minHDTokenBalance() external view returns(uint256) {
    return uintStorage[MIN_HDTOKEN_BALANCE];
}

Also it makes sense to provide a method that will check if the SCD token balance is above the threshold as atomic operation:

function isHDTokenBalanceAboveMinBalance() public view returns(bool) {
    if (halfduplexErc20token().balanceOf(address(this)) > uintStorage[MIN_HDTOKEN_BALANCE]) {
        return true;
    }
    return false;
}

Swap tokens operation

The main method that is introduced by the Phase 2 migration allows anyone to swap SCD tokens owned by the bridge contract to MCD. The method will be available until SCD ES is executed. As it was described above the bridge validators are responsible for calling this method as soon as new deposit request of SCD tokens detected.

function swapTokens() public {
    require(isTokenSwapAllowed(now));

    address migrationContract = 0xc73e0383F3Aff3215E6f04B0331D58CeCf0Ab849; //as per https://changelog.makerdao.com/releases/mainnet/1.0.0/contracts.json

    uint256 curHDTokenBalance = halfduplexErc20token().balanceOf(address(this));
    require(curHDTokenBalance > 0);

    uint256 curFDTokenBalance = erc20token().balanceOf(address(this));

    require(halfduplexErc20token().approve(migrationContract, curHDTokenBalance));
    IScdMcdMigration(migrationContract).swapSaiToDai(curHDTokenBalance);

    require(erc20token().balanceOf(address(this)) - curFDTokenBalance == curHDTokenBalance);

    emit TokensSwapped(halfduplexErc20token(), erc20token(), curHDTokenBalance);
}

The migration contract is explicitly specified in the contract since it is assumed that the changes prepared for the Phase 2 are specific for particular pair of tokens.

Interop with alternative receiver feature

Since the scenario to use the alternative receiver feature directly involves the bridge contract to deposit the tokens it allows to swap SCD tokens to MCD in the same transaction.

The current implementation of the feature assumes that only one token contract exists for the bridge operations. Support of two tokens will require extension of existing interfaces as so the contract that deposits tokens by specifying an alternative receiver will need to specify the specific token contract address. But in order to make behavior compatible with other bridge modes four ways to relay tokens will be supported:

  1. relayTokens(address _receiver, uint256 _amount)
  2. relayTokens(address _from, address _receiver, uint256 _amount)
  3. relayTokens(address _receiver, uint256 _amount, address _token)
  4. relayTokens(address _from, address _receiver, uint256 _amount, address _token)

If the token contract address is not specified (the cases 1 and 2) or if it is zero (for the cases 3 and 4), the MCD token contract is used.

Bearing in mind described above, the following changes for the method defined in contracts/upgradeable_contracts/erc20_to_native/ForeignBridgeErcToNative.sol are suggested:

function _relayTokens(address _sender, address _receiver, uint256 _amount, address _token) internal {
    require(_receiver != bridgeContractOnOtherSide());
    require(_receiver != address(0));
    require(_receiver != address(this));
    require(_amount > 0);
    ERC20Basic tokenToOperate = ERC20Basic(_token);
    ERC20Basic FDToken = erc20token();
    ERC20Basic HDToken = halfduplexErc20token();
    require(tokenToOperate == FDToken || 
            tokenToOperate == ERC20Basic(0x0) || 
            tokenToOperate == HDToken);
            
    require(withinLimit(_amount));
    setTotalSpentPerDay(getCurrentDay(), totalSpentPerDay(getCurrentDay()).add(_amount));

    if (tokenToOperate == ERC20Basic(0x0)) {
        tokenToOperate = FDToken;
    }
    
    tokenToOperate.transferFrom(_sender, address(this), _amount);
    emit UserRequestForAffirmation(_receiver, _amount);
    if (tokenToOperate == HDToken) {
        swapTokens();
    }
}

Implicit tokens swap

The current bridge architecture allows to implement the implicit token swap operation which will handle non-zero balance of the SCD tokens. This balance could appear if a SCD deposit occurred with value less or equal the minimal balance threshold. Another reason of non-zero balance is the case when the bridge validator skips his duty to call the swapTokens() method.

The implicit token swap is integrated in the flow when the method executeSignatures is being executed:

function onExecuteMessage(
    address _recipient,
    uint256 _amount,
    bytes32 /*_txHash*/
) internal returns (bool) {
    setTotalExecutedPerDay(getCurrentDay(), totalExecutedPerDay(getCurrentDay()).add(_amount));
    uint256 amount = _amount.div(10**decimalShift());
    uint256 amount = _amount;
    bool res = erc20token().transfer(_recipient, amount);
    
    if (halfduplexErc20token().balanceOf(address(this)) > 0) {
        address(this).call(abi.encodeWithSelector(bytes4(keccak256(bytes("swapTokens()")))));
    }

    return res;
}

Limited ability to claim SCD tokens

The TokenBridge contracts provides ability for the bridge owners to claim tokens (native or ERC20) owned by the bridge contract if they were occasionally transferred to the contract. Any token except the bridgeable one could be claimed and sent to the initial originator.

As per considered design the SCD token is bridgeable until SCD ES is executed. So, the ability to claim SCD tokens must be restricted till the SCD ES execution as well.

For this, the method claimTokens of contracts/upgradeable_contracts/erc20_to_native/ForeignBridgeErcToNative.sol should be extended like this:

function claimTokens(address _token, address _to) public {
    require(_token != address(erc20token()));
    if (_token == address(halfduplexErc20token())) {
        // SCD is not claimable if the bridge accepts deposits of this token
        require(!isTokenSwapAllowed(now));
    }
    super.claimTokens(_token, _to);
}

xDai chain side

Since the only bridge operation that is possible with the SCD token is the deposit no changes are needed on the xDai chain side.

and other is TBD

2 Likes

Ok, I’ve read through the “Upgrade procedure” part, and I think we need to add as much detail to the description as possible, including smart contract addresses, method names, arguments, links to repositories+branches, config options, etc. If something can be prepared beforehand, we should consider doing it. Some questions from my side related to this:

  1. Discover if any MCD transfer to the bridge contract happened…

Which method of which contract should be called here?

  1. Deploy new implementation of the bridge contract…

Let’s add a link to the contract code. I guess we can’t deploy this one in advance because new token’s address is unknown?

  1. The bridge upgradability administrators…

I think in xDai bridge we have the same multisig contract to manage all bridge roles?

  1. Deploy new implementation of the bridge contract on the xDai chain if it is necessary to include security fixes and enhancements (e.g. the feature “Relative daily limits”).

Let’s also add a link to the contract code here, and deploy it beforehand if possible. Regarding security fixes - is there any reason not to include them?

  1. Ugrade oracles on every validator node.

Let’s add a link to the required branch/tag here.
Also, I’m not sure about upgrading existing code of oracles - validator nodes were deployed quite some time ago and different validators might run different versions. I also recall that we manually changed some settings along the way. So I doubt that update can be done with a simple git pull.... Is there any upgrade procedure (db changes?) or we can simply delete existing oracle code and download new one?

  1. The bridge administrators must initiate and complete signing on the Ethereum Mainnet chain for the invocation of the migrateToMCD method with addresses of the migration and MCD contracts. Make sure that no oracles are restarted after step 9 since they still serve deposit requests for SCD.

Should we wait for all queued deposits to complete first?
Please elaborate on which contract should be called with migrateToMCD and which arguments should be used. I’m assuming it’s the new foreign bridge’s migrateToMCD, but the description is too unspecific.
What will happen if some oracles crash at this time (and are restarted)?

  1. The bridge administrators must initiate … setMaxPerTx method with an initial value…

Not sure what is the “initial value”?

  1. If there is any not relayed transfer request for SCD token… administrators must initiate and complete signing for claimTokens to refund SCD tokens

Is it possible that new SCD tokens will be sent to the bridge after migration? I doubt that anyone will regularly do manual checks :slight_smile: we should probably add some kind of monitoring

2 Likes

Thanks Pavel for good questions I will answer one by one.

It could be few methods: transfer and transferFrom. But it is most efficient is to look for the Transfer events emitted by the MCD contract and filter those transactions where the field to in the event is the bridge contract address.

We don’t know the MCD contract address in advance. It will appear after official deployment by MakerDAO.

We will publish the code of the new implementation under the corresponding issue in the TokenBridge contracts repo.

It can be deployed as soon as the security audit for the new version of contracts completed (it is not started yet). We don’t need to point out neither the migration contract nor the MCD contract as part of the deployment since the migration contract address will be passed to the migration activation method as a parameter.

Yes, if it was not changed recently, it should be the same multisig for all admin roles.

  1. We will post the contract code in the issue #310 - the same as I mentioned above. It could be deployed beforehand.
  2. The main concern so far to include any additional code changes in the contracts is time required for the security audit. My current understanding is that entire delta since the release 2.3.3. So, yes, all improvements and security fixes should be included in the new TokenBridge contract implementations for both xDai and Ethereum Mainnet sides.

The changes are currently is under development. As soon as they are finished we will tag a new release candidate.

And yes, the upgrade procedure needs to be developed in advance since it will require upgrade from the old tokenbridge oracle to the new version in the monorepo. It is not trivial.

  1. It is not necessary to wait for queued deposits completion before calling the migration method. Until restart the oracles listen events on the SCD contract so they will continue handling the Transfer events.
  2. The method migrateToMCD will be defined in the new implementation of the bridge contract on the Ethereum Mainnet side. As you can see it requires only one parameter - the address of the migration contract. The address of the migration contract will be known only when MakerDAO deploys the corresponding contracts in the Mainnet. So far, the migration and MCD contracts are regularly being deployed on Kovan so the TokenBridge migration procedure can be tested there.
  3. Hopefully, it will be no deposit requests in the moment when an oracle is being restarted. Moreover it should be OK if only one validator will experience the restart - the rest of validators will confirm the transfer. Otherwise we need to make the oracle logic is more complex what I would like to avoid on this phase (phase 1). The oracle logic improvements have been planned for the phase 2 and hopefully (if we finish development) both phases will happen simultaneously.

It was assumed that this is a value configured before the step 2. It can be received from the bridge contract or on the TokenBridge UI:

Yes, it is possible. That’s why we will develop the phase 2 when the tokenbridge will be able to handle requests to transfer both SCD and MCD.

So it’s 100 000 xDai? Would validators also need to set Minimum Amount Per Transaction and Daily Quota?

Could you outline (roughly) what the upgrade procedure looks like? Can we just remove previous oracle and deploy new version without doing an upgrade?

No, as I mentioned at the beginning only the maximum amount per transaction should be used to manage ability of the bridge receive withdrawal requests.

I know for sure that redis DB data could be preserved. But I don’t know exactly if the new deployment scripts should be used since the system will be in the state created by the previous version of deployment scripts. So, you can try to remove the old git repo containing the oracle on the node and clone the monorepo. Next, make sure that the startup service script is contains correct paths and options to run the new version of the oracle workers. You talked above about manual customization of a constant we performed last time but it is not needed anymore since the constant value is already set up properly in the repository. Since the upgrade path is not trivial I would prefer to test the upgrade procedure in advance with the SCD and MCD contracts on Kovan.

Right, I think it won’t work.

BTW, will new version of oracle support current version of bridge contracts? If yes, we might update validator nodes in advance

Yes, we can update them in advance but will need to stop the oracles after migration (the step 11) anyway.

That’s great. Then I propose we do the update of oracle code when it’s ready, starting from our validator node. Does it sound reasonable to you? This way, during migration we can at least not spend time on figuring out all possible problems that our validators would have. @igorbarinov what do you think about this?

yes, it sounds reasonable

Hi @akolotov

I see both https://github.com/poanetwork/tokenbridge-contracts/issues/310 and https://github.com/poanetwork/tokenbridge/pull/224 are closed now, does it mean we can update the code of our oracle node or there are any other planned changes?

Could you update the “Upgrade procedure” part of the post with links to the repos and other details?

Correct. I have tagged the new release 1.0.0 that contains the changes for the TokenBridge. Both the oracle and monitor were impacted with the changes related to the MCD migration

Ok, I’ll try to do the upgrade.

Few more questions:
Can we stop all bridge operations, say in the morning of Nov 18 and enable them back after bridge migration is complete? Will it simplify the upgrade procedure? I doubt all validators would make it to be online at the same time.

And about the upgrade procedure:

  1. Deploy new implementation of the bridge contract on the xDai chain if it is necessary to include security fixes and enhancements (e.g. the feature “Relative daily limits”) .

Do we include them? How will deployment procedure differ?

  1. If the step 6 is applicable…

I don’t understand what you mean by applicable here. Is there any case when we don’t deploy new contract on xDai on step 6?

We can stop bridge operations on the side of the xDai chain only. The specific of the bridge in erc20-to-native mode does not allow to stop bridge operation on the Foreign side: anyone could call the transfer method of the ERC20 token contract with the bridge contract address as the receiver of tokens without any limitations.

The security audit of the contracts have just started. We will prepare the new implementation contract to be deployed as part of the migration procedure as soon as the review is finished.

For example, if the security auditors provide an analysis that such scope of the changes is too risky to deploy it in rush.