Skip to content

Commit

Permalink
Merge branch 'main' into chore/sync-its-pipeline
Browse files Browse the repository at this point in the history
  • Loading branch information
milapsheth authored Oct 25, 2024
2 parents a1bc822 + e77c622 commit c9f1ae8
Show file tree
Hide file tree
Showing 7 changed files with 56 additions and 41 deletions.
9 changes: 5 additions & 4 deletions contracts/InterchainTokenFactory.sol
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,7 @@ pragma solidity ^0.8.0;
import { AddressBytes } from '@axelar-network/axelar-gmp-sdk-solidity/contracts/libs/AddressBytes.sol';
import { Multicall } from '@axelar-network/axelar-gmp-sdk-solidity/contracts/utils/Multicall.sol';
import { Upgradable } from '@axelar-network/axelar-gmp-sdk-solidity/contracts/upgradable/Upgradable.sol';
import { IAxelarGateway } from '@axelar-network/axelar-gmp-sdk-solidity/contracts/interfaces/IAxelarGateway.sol';

import { IAxelarGatewayWithToken } from '@axelar-network/axelar-gmp-sdk-solidity/contracts/interfaces/IAxelarGatewayWithToken.sol';
import { IInterchainTokenService } from './interfaces/IInterchainTokenService.sol';
import { IInterchainTokenFactory } from './interfaces/IInterchainTokenFactory.sol';
import { ITokenManagerType } from './interfaces/ITokenManagerType.sol';
Expand All @@ -22,7 +21,7 @@ contract InterchainTokenFactory is IInterchainTokenFactory, ITokenManagerType, M

IInterchainTokenService public immutable interchainTokenService;
bytes32 public immutable chainNameHash;
IAxelarGateway public immutable gateway;
IAxelarGatewayWithToken public immutable gateway;

bytes32 private constant CONTRACT_ID = keccak256('interchain-token-factory');
bytes32 internal constant PREFIX_CANONICAL_TOKEN_SALT = keccak256('canonical-token-salt');
Expand All @@ -40,9 +39,11 @@ contract InterchainTokenFactory is IInterchainTokenFactory, ITokenManagerType, M
interchainTokenService = IInterchainTokenService(interchainTokenService_);

chainNameHash = interchainTokenService.chainNameHash();
gateway = interchainTokenService.gateway();
gateway = IAxelarGatewayWithToken(address(interchainTokenService.gateway()));
}

function _setup(bytes calldata data) internal override {}

/**
* @notice Getter for the contract id.
* @return bytes32 The contract id of this contract.
Expand Down
18 changes: 15 additions & 3 deletions contracts/InterchainTokenService.sol
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ pragma solidity ^0.8.0;
import { IERC20 } from '@axelar-network/axelar-gmp-sdk-solidity/contracts/interfaces/IERC20.sol';
import { IAxelarGasService } from '@axelar-network/axelar-gmp-sdk-solidity/contracts/interfaces/IAxelarGasService.sol';
import { IAxelarGateway } from '@axelar-network/axelar-gmp-sdk-solidity/contracts/interfaces/IAxelarGateway.sol';
import { IAxelarGatewayWithToken } from '@axelar-network/axelar-gmp-sdk-solidity/contracts/interfaces/IAxelarGatewayWithToken.sol';
import { ExpressExecutorTracker } from '@axelar-network/axelar-gmp-sdk-solidity/contracts/express/ExpressExecutorTracker.sol';
import { Upgradable } from '@axelar-network/axelar-gmp-sdk-solidity/contracts/upgradable/Upgradable.sol';
import { AddressBytes } from '@axelar-network/axelar-gmp-sdk-solidity/contracts/libs/AddressBytes.sol';
Expand All @@ -21,7 +22,6 @@ import { IInterchainTokenExpressExecutable } from './interfaces/IInterchainToken
import { ITokenManager } from './interfaces/ITokenManager.sol';
import { IGatewayCaller } from './interfaces/IGatewayCaller.sol';
import { Create3AddressFixed } from './utils/Create3AddressFixed.sol';

import { Operator } from './utils/Operator.sol';

/**
Expand All @@ -44,6 +44,14 @@ contract InterchainTokenService is
using AddressBytes for bytes;
using AddressBytes for address;

/**
* @dev There are two types of Axelar Gateways for cross-chain messaging:
* 1. Cross-chain messaging (GMP): The Axelar Gateway allows sending cross-chain messages.
* This is compatible across both Amplifier and consensus chains. IAxelarGateway interface exposes this functionality.
* 2. Cross-chain messaging with Gateway Token: The AxelarGateway on legacy consensus EVM connections supports this (via callContractWithToken)
* but not Amplifier chains. The gateway is cast to IAxelarGatewayWithToken when gateway tokens need to be handled.
* ITS deployments on Amplifier chains will revert when this functionality is used.
*/
IAxelarGateway public immutable gateway;
IAxelarGasService public immutable gasService;
address public immutable interchainTokenFactory;
Expand Down Expand Up @@ -717,7 +725,7 @@ contract InterchainTokenService is
// This is intentional, as using `uint256` instead of `bytes` improves gas efficiency without any functional difference.
(, bytes32 tokenId, , , uint256 amountInPayload) = abi.decode(payload, (uint256, bytes32, uint256, uint256, uint256));

if (validTokenAddress(tokenId) != gateway.tokenAddresses(tokenSymbol) || amount != amountInPayload)
if (validTokenAddress(tokenId) != gatewayWithToken().tokenAddresses(tokenSymbol) || amount != amountInPayload)
revert InvalidGatewayTokenTransfer(tokenId, payload, tokenSymbol, amount);
}

Expand Down Expand Up @@ -940,7 +948,7 @@ contract InterchainTokenService is
) internal {
bytes32 payloadHash = keccak256(payload);

if (!gateway.validateContractCallAndMint(commandId, sourceChain, sourceAddress, payloadHash, tokenSymbol, amount))
if (!gatewayWithToken().validateContractCallAndMint(commandId, sourceChain, sourceAddress, payloadHash, tokenSymbol, amount))
revert NotApprovedByGateway();

uint256 messageType;
Expand Down Expand Up @@ -1247,4 +1255,8 @@ contract InterchainTokenService is
emit ExpressExecutionFulfilled(commandId, sourceChain, sourceAddress, payloadHash, expressExecutor);
}
}

function gatewayWithToken() internal view returns (IAxelarGatewayWithToken) {
return IAxelarGatewayWithToken(address(gateway));
}
}
3 changes: 2 additions & 1 deletion contracts/utils/GatewayCaller.sol
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ pragma solidity ^0.8.0;

import { IAxelarGasService } from '@axelar-network/axelar-gmp-sdk-solidity/contracts/interfaces/IAxelarGasService.sol';
import { IAxelarGateway } from '@axelar-network/axelar-gmp-sdk-solidity/contracts/interfaces/IAxelarGateway.sol';
import { IAxelarGatewayWithToken } from '@axelar-network/axelar-gmp-sdk-solidity/contracts/interfaces/IAxelarGatewayWithToken.sol';
import { IGatewayCaller } from '../interfaces/IGatewayCaller.sol';

/**
Expand Down Expand Up @@ -117,6 +118,6 @@ contract GatewayCaller is IGatewayCaller {
}
}

gateway.callContractWithToken(destinationChain, destinationAddress, payload, symbol, amount);
IAxelarGatewayWithToken(address(gateway)).callContractWithToken(destinationChain, destinationAddress, payload, symbol, amount);
}
}
30 changes: 19 additions & 11 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,8 @@
"node": ">=18"
},
"dependencies": {
"@axelar-network/axelar-cgp-solidity": "6.2.1",
"@axelar-network/axelar-gmp-sdk-solidity": "5.6.4"
"@axelar-network/axelar-cgp-solidity": "6.4.0",
"@axelar-network/axelar-gmp-sdk-solidity": "6.0.1"
},
"devDependencies": {
"@axelar-network/axelar-chains-config": "^1.2.0",
Expand Down
6 changes: 6 additions & 0 deletions test/InterchainTokenService.js
Original file line number Diff line number Diff line change
Expand Up @@ -500,6 +500,12 @@ describe('Interchain Token Service', () => {
);
});

it('Should return the correct contract id', async () => {
const expectedContractid = keccak256(toUtf8Bytes('interchain-token-service'));
const contractId = await service.contractId();
expect(contractId).to.eq(expectedContractid);
});

it('Should return the token manager implementation', async () => {
const tokenManagerImplementation = await service.tokenManagerImplementation(getRandomInt(1000));
expect(tokenManagerImplementation).to.eq(tokenManager.address);
Expand Down
27 changes: 7 additions & 20 deletions test/InterchainTokenServiceUpgradeFlow.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ const Create3Deployer = getContractJSON('Create3Deployer');
const { MINT_BURN } = require('./constants');

describe('Interchain Token Service Upgrade Flow', () => {
let wallet, otherWallet, signer;
let wallet, otherWallet, operator;
let service, gateway, gasService;
let tokenManagerDeployer, interchainTokenDeployer, tokenManager, tokenHandler, gatewayCaller;
let interchainTokenFactoryAddress;
Expand All @@ -30,7 +30,7 @@ describe('Interchain Token Service Upgrade Flow', () => {
let buffer;

const governanceChain = 'Governance Chain';
const threshold = 2;
const minimumTimeDelay = isHardhat ? 10 * 60 * 60 : 15;
const deploymentKey = 'InterchainTokenService';
const chainName = 'Test';

Expand Down Expand Up @@ -58,8 +58,7 @@ describe('Interchain Token Service Upgrade Flow', () => {
}

before(async () => {
[wallet, otherWallet, signer] = await ethers.getSigners();
const signers = [wallet, otherWallet, signer];
[wallet, otherWallet, operator] = await ethers.getSigners();
governanceAddress = otherWallet.address;

buffer = isHardhat ? 10 * 60 * 60 : 10;
Expand All @@ -85,14 +84,7 @@ describe('Interchain Token Service Upgrade Flow', () => {
);

axelarServiceGovernance = await axelarServiceGovernanceFactory
.deploy(
gateway.address,
governanceChain,
governanceAddress,
buffer,
signers.map((signer) => signer.address),
threshold,
)
.deploy(gateway.address, governanceChain, governanceAddress, minimumTimeDelay, operator.address)
.then((d) => d.deployed());

service = await deployInterchainTokenService(
Expand Down Expand Up @@ -224,16 +216,11 @@ describe('Interchain Token Service Upgrade Flow', () => {
);

await expect(axelarServiceGovernance.execute(commandIdGateway, governanceChain, governanceAddress, payload))
.to.emit(axelarServiceGovernance, 'MultisigApproved')
.to.emit(axelarServiceGovernance, 'OperatorProposalApproved')
.withArgs(proposalHash, target, calldata, nativeValue);

await axelarServiceGovernance
.connect(wallet)
.executeMultisigProposal(target, calldata, nativeValue)
.then((tx) => tx.wait);

await expect(axelarServiceGovernance.connect(otherWallet).executeMultisigProposal(target, calldata, nativeValue))
.to.emit(axelarServiceGovernance, 'MultisigExecuted')
await expect(axelarServiceGovernance.connect(operator).executeOperatorProposal(target, calldata, nativeValue))
.to.emit(axelarServiceGovernance, 'OperatorProposalExecuted')
.withArgs(proposalHash, target, calldata, nativeValue)
.and.to.emit(service, 'Upgraded')
.withArgs(newServiceImplementation.address);
Expand Down

0 comments on commit c9f1ae8

Please sign in to comment.