After upgrade using prepareUpgrade() with Gnosis Safe MyContract.address returns the imp. address

Thank you very much @Yoshiko, for your post.
Yes, I assume that existingContract.address gives me back the proxy address of MyContract.

I follow the tutorial

What I don't understand is, why MyContract.deployed() first returns the proxy address and after the upgrade the new implementation address.

Moreover, before using Gnosis Safe, I did the upgrade as follows:

const newContract = await upgradeProxy(existingContract.address, MyContract, { deployer });

That worked as expected. Querying the ProxyAdmin (on Etherscan) getProxyImplementation(proxyAddress) I get the correct implementation address.

Here the code of 1_DeployOrUpgrade.js:

const Migrations = artifacts.require("Migrations");
const { deployProxy, upgradeProxy } = require('@openzeppelin/truffle-upgrades');
const { admin } = require('@openzeppelin/truffle-upgrades');
const { prepareUpgrade } = require('@openzeppelin/truffle-upgrades');
const argv = require('minimist')(process.argv.slice(2), {string: ['operation']});


const MyContract = artifacts.require("MyContract");

module.exports = async function (deployer, network) {
  var operation = argv['operation'];
  await deployer.deploy(Migrations);
  switch(operation) {
    case 'deploy':
      const myContract = await deployProxy(MyContract, { deployer});
      const myContractProxyAddress = myContract.address;
      console.log('Deployed ', myContractProxyAddress);
      break;
    case 'upgrade':
      var gnosisSafe;
      switch(network) {
        case 'rinkeby':
          gnosisSafe = '0x97826de55402165A9c317E30e53CF65BE75226B9';
          await admin.transferProxyAdminOwnership(gnosisSafe);
          break;
        default:
          break;
      }
      if(MyContract.isDeployed() ) {
        const existingMyContract = await MyContract.deployed();
        //const newMyContract = await upgradeProxy(existingMyContract.address, MyContract, { deployer });
        const newMyContract = await prepareUpgrade(existingMyContract.address, MyContract, { deployer });
        console.log('Upgraded ', newMyContract.address);

      } else {
        console.log("Not upgraded. Not all required contracts are deployed: ");
        console.log("MyContract: ", MyContract.isDeployed());
      }
      break;
    default:
      console.log("Operation unknown.");
      break;
  }
};

In the MyContract.json under
"networks"."4"."address:" now is the address of the implementation contract, before it was the address of the proxy contract. I guess MyContract.deployed() reads the address from there.

Here the package versions:

├─┬ @openzeppelin/truffle-upgrades@1.5.0

│ ├── @openzeppelin/upgrades-core@1.5.1

│ ├── @truffle/contract@4.3.13

│ └── solidity-ast@0.4.19

I can reproduce this scenario on the dev network.