Can the same implementation contract name be used with `upgradeProxy`

Trey asked on Telegram

Is there any way to keep the original name. i.e. instead of the name of my contract being “Box”, then “BoxV2” then “BoxV3”, for each implementation contract to just be “Box”?

Trey pointed out that the documentation has the following:

Then, in a future migration, you can use the upgradeProxy function to upgrade the deployed instance to a new version. The new version can be a different contract (such as BoxV2 ), or you can just modify the existing Box contract and recompile it - the plugin will note it changed.

The initial version can be deployed with the following:

// migrations/2_deploy_box.js
const Box = artifacts.require('Box');
const { deployProxy } = require('@openzeppelin/truffle-upgrades');
module.exports = async function (deployer) {
  await deployProxy(Box, [42], { deployer, initializer: 'store' });

The Box contract can then be updated, and then upgraded with the following migration

// migrations/3_upgrade_box.js
const Box = artifacts.require('Box');
const { upgradeProxy } = require('@openzeppelin/truffle-upgrades');
module.exports = async function (deployer) {
    const existing = await Box.deployed();
    const instance = await upgradeProxy(existing.address, Box, { deployer });

This doesn’t allow for easy reproduction of the upgrade process.

I would recommend using versioned contract names for a project being used in production.