Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix!: prefix gateway token salt derivation #269

Merged
merged 4 commits into from
Aug 7, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/codecov.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ jobs:
if grep -q -i "error" build.log || grep -q -i "warning" build.log; then
echo "Build contains following errors or warnings..."
cat build.log
exit 0;
exit 1;
else
exit 0;
fi
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/test.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ jobs:

cat build.log

exit 0;
exit 1;
else
exit 0;
fi
Expand Down
17 changes: 15 additions & 2 deletions contracts/InterchainTokenFactory.sol
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ contract InterchainTokenFactory is IInterchainTokenFactory, ITokenManagerType, M
bytes32 private constant CONTRACT_ID = keccak256('interchain-token-factory');
bytes32 internal constant PREFIX_CANONICAL_TOKEN_SALT = keccak256('canonical-token-salt');
bytes32 internal constant PREFIX_INTERCHAIN_TOKEN_SALT = keccak256('interchain-token-salt');
bytes32 internal constant PREFIX_GATEWAY_TOKEN_SALT = keccak256('gateway-token-salt');
address private constant TOKEN_FACTORY_DEPLOYER = address(0);

/**
Expand Down Expand Up @@ -71,6 +72,15 @@ contract InterchainTokenFactory is IInterchainTokenFactory, ITokenManagerType, M
salt = keccak256(abi.encode(PREFIX_CANONICAL_TOKEN_SALT, chainNameHash_, tokenAddress));
}

/**
* @notice Calculates the salt for a gateway interchain token.
* @param tokenIdentifier A unique identifier to generate the salt.
* @return salt The calculated salt for the interchain token.
*/
function gatewayTokenSalt(bytes32 tokenIdentifier) public pure returns (bytes32 salt) {
salt = keccak256(abi.encode(PREFIX_GATEWAY_TOKEN_SALT, tokenIdentifier));
}

/**
* @notice Computes the ID for an interchain token based on the deployer and a salt.
* @param deployer The address that deployed the interchain token.
Expand Down Expand Up @@ -285,13 +295,16 @@ contract InterchainTokenFactory is IInterchainTokenFactory, ITokenManagerType, M

/**
* @notice Register 'canonical' gateway tokens. The same salt needs to be used for the same gateway token on every chain.
* @param salt The salt to be used for the token registration. Should be the same for all tokens and something that will not have collisions with any of the other salts used by the factory.
* @param tokenIdentifier A gateway token identifier to be used for the token registration. Should be the same for all chains.
* @param symbol The symbol of the token to register.
*/
function registerGatewayToken(bytes32 salt, string calldata symbol) external onlyOwner returns (bytes32 tokenId) {
function registerGatewayToken(bytes32 tokenIdentifier, string calldata symbol) external onlyOwner returns (bytes32 tokenId) {
address tokenAddress = gateway.tokenAddresses(symbol);
if (tokenAddress == address(0)) revert NotGatewayToken(symbol);

bytes memory params = abi.encode('', tokenAddress);
bytes32 salt = gatewayTokenSalt(tokenIdentifier);

tokenId = interchainTokenService.deployTokenManager(salt, '', TokenManagerType.GATEWAY, params, 0);
}

Expand Down
2 changes: 1 addition & 1 deletion contracts/InterchainTokenService.sol
Original file line number Diff line number Diff line change
Expand Up @@ -290,7 +290,7 @@ contract InterchainTokenService is
bytes calldata params,
uint256 gasValue
) external payable whenNotPaused returns (bytes32 tokenId) {
// Custom token managers can't be deployed with Interchain token mint burn type, which is reserved for interchain tokens
// Custom token managers can't be deployed with native interchain token type, which is reserved for interchain tokens
if (tokenManagerType == TokenManagerType.NATIVE_INTERCHAIN_TOKEN) revert CannotDeploy(tokenManagerType);

address deployer = msg.sender;
Expand Down
3 changes: 2 additions & 1 deletion contracts/TokenHandler.sol
Original file line number Diff line number Diff line change
Expand Up @@ -166,7 +166,8 @@ contract TokenHandler is ITokenHandler, ITokenManagerType, ReentrancyGuard, Crea
ITokenManager(tokenManager).approveService();
}

// Approve the gateway here. One-time infinite approval works for gateway wrapped tokens, and for most origin tokens. Approval can be refreshed in the future if needed for certain tokens.
// Approve the gateway here. One-time infinite approval works for gateway wrapped tokens, and for most origin tokens.
// Approval can be refreshed in the future if needed for certain tokens via an upgrade, but realistically should never be exhausted.
if (tokenManagerType == uint256(TokenManagerType.GATEWAY)) {
address token = ITokenManager(tokenManager).tokenAddress();
_approveGateway(token, UINT256_MAX);
Expand Down
11 changes: 9 additions & 2 deletions contracts/interfaces/IInterchainTokenFactory.sol
Original file line number Diff line number Diff line change
Expand Up @@ -130,10 +130,17 @@ interface IInterchainTokenFactory is IUpgradable, IMulticall {
uint256 gasValue
) external payable returns (bytes32 tokenId);

/**
* @notice Calculates the salt for a gateway interchain token.
* @param tokenIdentifier A unique identifier to generate the salt.
* @return salt The calculated salt for the interchain token.
*/
function gatewayTokenSalt(bytes32 tokenIdentifier) external pure returns (bytes32 salt);

/**
* @notice Register 'canonical' gateway tokens. The same salt needs to be used for the same gateway token on every chain.
* @param salt The salt to be used for the token registration. Should be the same for all tokens and something that will not have collisions with any of the other salts used by the factory.
* @param tokenIdentifier A gateway token identifier to be used for the token registration. Should be the same for all chains.
* @param symbol The symbol of the token to register.
*/
function registerGatewayToken(bytes32 salt, string calldata symbol) external returns (bytes32 tokenId);
function registerGatewayToken(bytes32 tokenIdentifier, string calldata symbol) external returns (bytes32 tokenId);
}
9 changes: 3 additions & 6 deletions hardhat.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,6 @@ const chains = require(`@axelar-network/axelar-chains-config/info/${env}.json`);
const keys = readJSON(`${__dirname}/keys.json`);
const { networks, etherscan } = importNetworks(chains, keys);

// TODO: Remove this temporary override
networks.hardhat.allowUnlimitedContractSize = true;

const optimizerSettings = {
enabled: true,
runs: 1000,
Expand All @@ -38,12 +35,12 @@ const compilerSettings = {
},
};
const itsCompilerSettings = {
version: '0.8.21',
version: '0.8.24',
settings: {
evmVersion: process.env.EVM_VERSION || 'london',
optimizer: {
...optimizerSettings,
runs: 100, // Reduce runs to keep bytecode size under limit
runs: 150, // Reduce runs to keep bytecode size under limit
},
},
};
Expand Down Expand Up @@ -76,7 +73,7 @@ module.exports = {
},
contractSizer: {
runOnCompile: process.env.CHECK_CONTRACT_SIZE,
// strict: process.env.CHECK_CONTRACT_SIZE, // TODO: uncomment this
strict: process.env.CHECK_CONTRACT_SIZE,
except: ['contracts/test'],
},
};
4 changes: 2 additions & 2 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
@@ -1,6 +1,6 @@
{
"name": "@axelar-network/interchain-token-service",
"version": "1.2.4",
"version": "2.0.0",
"repository": {
"type": "git",
"url": "https://github.com/axelarnetwork/interchain-token-service"
Expand Down
5 changes: 3 additions & 2 deletions test/InterchainTokenFactory.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ const {
getContractAt,
Wallet,
constants: { AddressZero },
utils: { defaultAbiCoder, keccak256, toUtf8Bytes },
utils: { defaultAbiCoder, keccak256, toUtf8Bytes, id },
} = ethers;
const { deployAll, deployContract } = require('../scripts/deploy');
const { getRandomBytes32, expectRevert } = require('./utils');
Expand Down Expand Up @@ -188,7 +188,8 @@ describe('InterchainTokenFactory', () => {

await gateway.deployToken(params, getRandomBytes32()).then((tx) => tx.wait);

tokenId = await service.interchainTokenId(AddressZero, salt);
const deploySalt = keccak256(defaultAbiCoder.encode(['bytes32', 'bytes32'], [id('gateway-token-salt'), salt]));
tokenId = await service.interchainTokenId(AddressZero, deploySalt);
tokenManagerAddress = await service.tokenManagerAddress(tokenId);

if (lockUnlock) {
Expand Down
Loading