Skip to content

Commit

Permalink
refactor(ITS): inheriting InterchainAddressValidator (#150)
Browse files Browse the repository at this point in the history
* refactor(ITS): inheriting InterchainAddressValidator

* fix(imports): unused interfaces

* fix: unused var

* style(Solidity): prettier
  • Loading branch information
re1ro authored Nov 5, 2023
1 parent 237907e commit b71c1bf
Show file tree
Hide file tree
Showing 13 changed files with 91 additions and 123 deletions.
2 changes: 1 addition & 1 deletion DESIGN.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ Most projects that look to go cross-chain nowadays have more complex needs that

## Interchain Address Tracker

We plan to finalize the design of the `InterchainTokenService` but we want to be able to support new chains as they get added to the Axelar Network. For this purpose, the service will ask a separate contract, the [`InterchainAddressTracker`](https://github.com/axelarnetwork/axelar-gmp-sdk-solidity/blob/main/contracts/utils/InterchainAddressTracker.sol) to obtain the destination address for outgoing messages, and for validation of incoming messages.
`InterchainTokenService` inherits the [`InterchainAddressTracker`](https://github.com/axelarnetwork/axelar-gmp-sdk-solidity/blob/main/contracts/utils/InterchainAddressTracker.sol) to support new chains as they get added to the Axelar Network. It's implemented for obtaining the destination address for outgoing messages, and for validation of incoming messages.

## Interchain Token

Expand Down
33 changes: 0 additions & 33 deletions contracts/AddressTracker.sol

This file was deleted.

5 changes: 4 additions & 1 deletion contracts/InterchainTokenFactory.sol
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,10 @@ contract InterchainTokenFactory is IInterchainTokenFactory, ITokenManagerType, M
constructor(address interchainTokenServiceAddress) {
if (interchainTokenServiceAddress == address(0)) revert ZeroAddress();
service = IInterchainTokenService(interchainTokenServiceAddress);
string memory chainName_ = IInterchainTokenService(interchainTokenServiceAddress).interchainAddressTracker().chainName();
string memory chainName_ = IInterchainTokenService(interchainTokenServiceAddress).chainName();

if (bytes(chainName_).length == 0) revert InvalidChainName();

chainNameHash = keccak256(bytes(chainName_));
}

Expand Down
54 changes: 41 additions & 13 deletions contracts/InterchainTokenService.sol
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@ import { SafeTokenTransferFrom } from '@axelar-network/axelar-gmp-sdk-solidity/c
import { AddressBytes } from '@axelar-network/axelar-gmp-sdk-solidity/contracts/libs/AddressBytes.sol';
import { StringToBytes32, Bytes32ToString } from '@axelar-network/axelar-gmp-sdk-solidity/contracts/libs/Bytes32String.sol';
import { Multicall } from '@axelar-network/axelar-gmp-sdk-solidity/contracts/utils/Multicall.sol';
import { IInterchainAddressTracker } from '@axelar-network/axelar-gmp-sdk-solidity/contracts/interfaces/IInterchainAddressTracker.sol';
import { Pausable } from '@axelar-network/axelar-gmp-sdk-solidity/contracts/utils/Pausable.sol';
import { InterchainAddressTracker } from '@axelar-network/axelar-gmp-sdk-solidity/contracts/utils/InterchainAddressTracker.sol';

import { IInterchainTokenService } from './interfaces/IInterchainTokenService.sol';
import { ITokenManagerDeployer } from './interfaces/ITokenManagerDeployer.sol';
Expand All @@ -37,6 +37,7 @@ contract InterchainTokenService is
Multicall,
Create3Address,
ExpressExecutorTracker,
InterchainAddressTracker,
IInterchainTokenService
{
using StringToBytes32 for string;
Expand All @@ -60,8 +61,6 @@ contract InterchainTokenService is
address internal immutable implementationLockUnlock;
address internal immutable implementationLockUnlockFee;

IInterchainAddressTracker public immutable interchainAddressTracker;

bytes32 internal constant PREFIX_INTERCHAIN_TOKEN_ID = keccak256('its-interchain-token-id');
bytes32 internal constant PREFIX_INTERCHAIN_TOKEN_SALT = keccak256('its-interchain-token-salt');

Expand All @@ -83,39 +82,36 @@ contract InterchainTokenService is
* @param interchainTokenDeployer_ the address of the InterchainTokenDeployer.
* @param gateway_ the address of the AxelarGateway.
* @param gasService_ the address of the AxelarGasService.
* @param interchainAddressTracker_ the address of the InterchainAddressTracker.
* @param chainName_ the name of the chain that this contract is deployed on.
* @param tokenManagerImplementations this needs to have implementations in the order: Mint-burn, Mint-burn from, Lock-unlock, and Lock-unlock with fee.
*/
constructor(
address tokenManagerDeployer_,
address interchainTokenDeployer_,
address gateway_,
address gasService_,
address interchainAddressTracker_,
string memory chainName_,
address[] memory tokenManagerImplementations
) {
if (
interchainAddressTracker_ == address(0) ||
gasService_ == address(0) ||
tokenManagerDeployer_ == address(0) ||
interchainTokenDeployer_ == address(0) ||
gateway_ == address(0)
) revert ZeroAddress();

gateway = IAxelarGateway(gateway_);
interchainAddressTracker = IInterchainAddressTracker(interchainAddressTracker_);
gasService = IAxelarGasService(gasService_);
tokenManagerDeployer = tokenManagerDeployer_;
interchainTokenDeployer = interchainTokenDeployer_;

if (tokenManagerImplementations.length != uint256(type(TokenManagerType).max) + 1) revert LengthMismatch();
if (bytes(chainName_).length == 0) revert InvalidChainName();

implementationMintBurn = _sanitizeTokenManagerImplementation(tokenManagerImplementations, TokenManagerType.MINT_BURN);
implementationMintBurnFrom = _sanitizeTokenManagerImplementation(tokenManagerImplementations, TokenManagerType.MINT_BURN_FROM);
implementationLockUnlock = _sanitizeTokenManagerImplementation(tokenManagerImplementations, TokenManagerType.LOCK_UNLOCK);
implementationLockUnlockFee = _sanitizeTokenManagerImplementation(tokenManagerImplementations, TokenManagerType.LOCK_UNLOCK_FEE);

string memory chainName_ = interchainAddressTracker.chainName();
chainNameHash = keccak256(bytes(chainName_));
}

Expand All @@ -129,7 +125,7 @@ contract InterchainTokenService is
* @param sourceAddress the address that the call came from.
*/
modifier onlyRemoteService(string calldata sourceChain, string calldata sourceAddress) {
if (!interchainAddressTracker.isTrustedAddress(sourceChain, sourceAddress)) revert NotRemoteService();
if (!isTrustedAddress(sourceChain, sourceAddress)) revert NotRemoteService();

_;
}
Expand Down Expand Up @@ -471,6 +467,23 @@ contract InterchainTokenService is
}
}

/**
* @notice Used to set a trusted address for a chain.
* @param chain the chain to set the trusted address of.
* @param address_ the address to set as trusted.
*/
function setTrustedAddress(string memory chain, string memory address_) external onlyOwner {
_setTrustedAddress(chain, address_);
}

/**
* @notice Used to remove a trusted address for a chain.
* @param chain the chain to set the trusted address of.
*/
function removeTrustedAddress(string memory chain) external onlyOwner {
_removeTrustedAddress(chain);
}

/**
* @notice Allows the owner to pause/unpause the token service.
* @param paused whether to pause or unpause.
Expand All @@ -488,7 +501,22 @@ contract InterchainTokenService is
\****************/

function _setup(bytes calldata params) internal override {
_addOperator(params.toAddress());
(address operator, string memory chainName_, string[] memory trustedChainNames, string[] memory trustedAddresses) = abi.decode(
params,
(address, string, string[], string[])
);
uint256 length = trustedChainNames.length;

if (operator == address(0)) revert ZeroAddress();
if (bytes(chainName_).length == 0) revert InvalidChainName();
if (length != trustedAddresses.length) revert LengthMismatch();

_addOperator(operator);
_setChainName(chainName_);

for (uint256 i; i < length; ++i) {
_setTrustedAddress(trustedChainNames[i], trustedAddresses[i]);
}
}

function _sanitizeTokenManagerImplementation(
Expand Down Expand Up @@ -659,8 +687,8 @@ contract InterchainTokenService is
* @param gasValue The amount of gas to be paid for the transaction
*/
function _callContract(string calldata destinationChain, bytes memory payload, uint256 gasValue) internal {
string memory destinationAddress = interchainAddressTracker.trustedAddress(destinationChain);
if (bytes(destinationAddress).length == 0) revert UntrustedChain(destinationChain);
string memory destinationAddress = trustedAddress(destinationChain);
if (bytes(destinationAddress).length == 0) revert UntrustedChain();

if (gasValue > 0) {
gasService.payNativeGasForContractCall{ value: gasValue }(
Expand Down
3 changes: 1 addition & 2 deletions contracts/interfaces/IAddressTracker.sol
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,9 @@

pragma solidity ^0.8.0;

import { IOwnable } from '@axelar-network/axelar-gmp-sdk-solidity/contracts/interfaces/IOwnable.sol';
import { IInterchainAddressTracker } from '@axelar-network/axelar-gmp-sdk-solidity/contracts/interfaces/IInterchainAddressTracker.sol';

interface IAddressTracker is IOwnable, IInterchainAddressTracker {
interface IAddressTracker is IInterchainAddressTracker {
/**
* @dev Sets the trusted address for the specified chain
* @param chain Chain name to be trusted
Expand Down
1 change: 1 addition & 0 deletions contracts/interfaces/IInterchainTokenFactory.sol
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ pragma solidity ^0.8.0;

interface IInterchainTokenFactory {
error ZeroAddress();
error InvalidChainName();
error NotDistributor(address distributor);
error NotOperator(address operator);
error NonZeroMintAmount();
Expand Down
15 changes: 4 additions & 11 deletions contracts/interfaces/IInterchainTokenService.sol
Original file line number Diff line number Diff line change
Expand Up @@ -5,23 +5,23 @@ pragma solidity ^0.8.0;
import { IAxelarValuedExpressExecutable } from '@axelar-network/axelar-gmp-sdk-solidity/contracts/interfaces/IAxelarValuedExpressExecutable.sol';
import { IContractIdentifier } from '@axelar-network/axelar-gmp-sdk-solidity/contracts/interfaces/IContractIdentifier.sol';
import { IMulticall } from '@axelar-network/axelar-gmp-sdk-solidity/contracts/interfaces/IMulticall.sol';
import { IInterchainAddressTracker } from '@axelar-network/axelar-gmp-sdk-solidity/contracts/interfaces/IInterchainAddressTracker.sol';
import { IPausable } from '@axelar-network/axelar-gmp-sdk-solidity/contracts/interfaces/IPausable.sol';

import { ITokenManagerType } from './ITokenManagerType.sol';
import { ITokenManagerImplementation } from './ITokenManagerImplementation.sol';
import { IAddressTracker } from './IAddressTracker.sol';

interface IInterchainTokenService is
ITokenManagerType,
ITokenManagerImplementation,
IAxelarValuedExpressExecutable,
IPausable,
IMulticall,
IContractIdentifier
IContractIdentifier,
IAddressTracker
{
error ZeroAddress();
error LengthMismatch();
error InvalidTokenManagerImplementationType(address implementation);
error InvalidChainName();
error NotRemoteService();
error TokenManagerDoesNotExist(bytes32 tokenId);
error NotTokenManager(address caller, address tokenManager);
Expand All @@ -33,7 +33,6 @@ interface IInterchainTokenService is
error InvalidMessageType(uint256 messageType);
error InvalidMetadataVersion(uint32 version);
error ExecuteWithTokenNotSupported();
error UntrustedChain(string chainName);
error InvalidExpressMessageType(uint256 messageType);

event InterchainTransfer(bytes32 indexed tokenId, string destinationChain, bytes destinationAddress, uint256 indexed amount);
Expand Down Expand Up @@ -84,12 +83,6 @@ interface IInterchainTokenService is
);
event InterchainTokenIdClaimed(bytes32 indexed tokenId, address indexed deployer, bytes32 indexed salt);

/**
* @notice Returns the address of the interchain router contract.
* @return interchainAddressTracker_ The interchainAddressTracker.
*/
function interchainAddressTracker() external view returns (IInterchainAddressTracker interchainAddressTracker_);

/**
* @notice Returns the address of the token manager deployer contract.
* @return tokenManagerDeployerAddress The address of the token manager deployer contract.
Expand Down
6 changes: 1 addition & 5 deletions contracts/proxies/InterchainTokenServiceProxy.sol
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,7 @@ contract InterchainTokenServiceProxy is Proxy {
* @param implementationAddress Address of the interchain token service implementation
* @param owner Address of the owner of the proxy
*/
constructor(
address implementationAddress,
address owner,
address operator
) Proxy(implementationAddress, owner, abi.encodePacked(operator)) {}
constructor(address implementationAddress, address owner, bytes memory setupParams) Proxy(implementationAddress, owner, setupParams) {}

/**
* @dev Override for the 'contractId' function in FinalProxy. Returns a unique identifier for this contract.
Expand Down
2 changes: 1 addition & 1 deletion hardhat.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ module.exports = {
evmVersion: process.env.EVM_VERSION || 'london',
optimizer: {
enabled: true,
runs: 1000,
runs: 10000,
details: {
peephole: process.env.COVERAGE === undefined,
inliner: process.env.COVERAGE === undefined,
Expand Down
8 changes: 4 additions & 4 deletions package-lock.json

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

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
},
"dependencies": {
"@axelar-network/axelar-cgp-solidity": "6.1.2",
"@axelar-network/axelar-gmp-sdk-solidity": "5.6.1"
"@axelar-network/axelar-gmp-sdk-solidity": "5.6.2"
},
"devDependencies": {
"@axelar-network/axelar-chains-config": "~0.1.2",
Expand Down
Loading

0 comments on commit b71c1bf

Please sign in to comment.