Skip to content

Commit

Permalink
Merge branch 'feat/manual-migrate-tokens' into feat/automcatic-migrat…
Browse files Browse the repository at this point in the history
…e-tokens
  • Loading branch information
Foivos committed Jan 9, 2025
2 parents 3c63b22 + 123c9c1 commit 70a0796
Show file tree
Hide file tree
Showing 3 changed files with 68 additions and 22 deletions.
15 changes: 1 addition & 14 deletions contracts/InterchainTokenService.sol
Original file line number Diff line number Diff line change
Expand Up @@ -645,20 +645,7 @@ contract InterchainTokenService is
}

/**
* @notice Allows the owner to migrate legacy tokens that cannot be migrated automatically.
* @param tokenId the tokenId of the registered token.
* @param data the data to pass to migrate the token.
*/
function migrateLegacyToken(bytes32 tokenId, bytes calldata data) external onlyOwner {
address tokenAddress = registeredTokenAddress(tokenId);
(bool success, bytes memory returnData) = tokenAddress.call(data);
if (!success) {
revert TokenMigrateFailed(returnData);
}
}

/**
* @notice Allows the owner to migrate legacy tokens that cannot be migrated automatically.
* @notice Allows the owner to migrate minter of native interchain tokens from ITS to the corresponding token manager.
* @param tokenId the tokenId of the registered token.
*/
function migrateInterchainToken(bytes32 tokenId) external onlyOwner {
Expand Down
8 changes: 0 additions & 8 deletions contracts/interfaces/IInterchainTokenService.sol
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,6 @@ interface IInterchainTokenService is
error EmptyParams();
error EmptyDestinationAddress();
error NotSupported();
error TokenMigrateFailed(bytes returnData);

event InterchainTransfer(
bytes32 indexed tokenId,
Expand Down Expand Up @@ -276,13 +275,6 @@ interface IInterchainTokenService is
*/
function setPauseStatus(bool paused) external;

/**
* @notice Allows the owner to migrate legacy tokens that cannot be migrated automatically.
* @param tokenId the tokenId of the registered token.
* @param data the data to pass to migrate the token.
*/
function migrateLegacyToken(bytes32 tokenId, bytes calldata data) external;

/**
* @notice Allows the owner to migrate legacy tokens that cannot be migrated automatically.
* @param tokenId the tokenId of the registered token.
Expand Down
67 changes: 67 additions & 0 deletions test/InterchainTokenService.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ const {
ITS_HUB_CHAIN_NAME,
ITS_HUB_ROUTING_IDENTIFIER,
ITS_HUB_ADDRESS,
MINTER_ROLE,
} = require('./constants');

const reportGas = gasReporter('Interchain Token Service');
Expand Down Expand Up @@ -3235,6 +3236,72 @@ describe('Interchain Token Service', () => {
});
});

describe('Interchain Token Migration', () => {
it('Should migrate a token succesfully', async () => {
const salt = getRandomBytes32();
const name = 'migrated token';
const symbol = 'MT';
const decimals = 53;
const tokenId = await service.interchainTokenId(wallet.address, salt);
const tokenManagerAddress = await service.tokenManagerAddress(tokenId);

await interchainTokenDeployer.deployInterchainToken(salt, tokenId, service.address, name, symbol, decimals).then((tx) => tx.wait);
const tokenAddress = await interchainTokenDeployer.deployedAddress(salt);
const token = await getContractAt('InterchainToken', tokenAddress, wallet);

const params = defaultAbiCoder.encode(['bytes', 'address'], [wallet.address, tokenAddress]);

await service.deployTokenManager(salt, '', MINT_BURN, params, 0).then((tx) => tx.wait);

await expect(service.migrateInterchainToken(tokenId))
.to.emit(token, 'RolesRemoved')
.withArgs(service.address, 1 << MINTER_ROLE)
.to.emit(token, 'RolesAdded')
.withArgs(tokenManagerAddress, 1 << MINTER_ROLE);
});

it('Should not be able to migrate a token twice', async () => {
const salt = getRandomBytes32();
const name = 'migrated token';
const symbol = 'MT';
const decimals = 53;
const tokenId = await service.interchainTokenId(wallet.address, salt);
const tokenManagerAddress = await service.tokenManagerAddress(tokenId);

await interchainTokenDeployer.deployInterchainToken(salt, tokenId, service.address, name, symbol, decimals).then((tx) => tx.wait);
const tokenAddress = await interchainTokenDeployer.deployedAddress(salt);
const token = await getContractAt('InterchainToken', tokenAddress, wallet);

const params = defaultAbiCoder.encode(['bytes', 'address'], [wallet.address, tokenAddress]);

await service.deployTokenManager(salt, '', MINT_BURN, params, 0).then((tx) => tx.wait);

await expect(service.migrateInterchainToken(tokenId))
.to.emit(token, 'RolesRemoved')
.withArgs(service.address, 1 << MINTER_ROLE)
.to.emit(token, 'RolesAdded')
.withArgs(tokenManagerAddress, 1 << MINTER_ROLE);

await expectRevert((gasOptions) => service.migrateInterchainToken(tokenId, { gasOptions} ), token, 'MissingRole', [service.address, MINTER_ROLE]);
});

it('Should not be able to migrate a token deployed after this upgrade', async () => {
const salt = getRandomBytes32();
const name = 'migrated token';
const symbol = 'MT';
const decimals = 53;
const tokenId = await service.interchainTokenId(wallet.address, salt);
const tokenManagerAddress = await service.tokenManagerAddress(tokenId);


await service.deployInterchainToken(salt, '', name, symbol, decimals, AddressZero, 0).then((tx) => tx.wait);
const tokenAddress = await service.interchainTokenAddress(tokenId);
const token = await getContractAt('InterchainToken', tokenAddress, wallet);

await expectRevert((gasOptions) => service.migrateInterchainToken(tokenId, { gasOptions} ), token, 'MissingRole', [service.address, MINTER_ROLE]);
});
})

describe('Bytecode checks [ @skip-on-coverage ]', () => {
it('Should preserve the same proxy bytecode for each EVM', async () => {
const proxyFactory = await ethers.getContractFactory('InterchainProxy', wallet);
Expand Down

0 comments on commit 70a0796

Please sign in to comment.