From 0ea62fd532b743de97497f7c6bd14ed2c32a06d4 Mon Sep 17 00:00:00 2001 From: Kiryl Yermakou Date: Tue, 3 Oct 2023 11:43:29 -0400 Subject: [PATCH] ci(Slither): action + fixes + comments --- .github/workflows/slither.yml | 16 +++++ .../InterchainTokenService.sol | 71 ++++++++++++------- contracts/interfaces/IDistributable.sol | 8 +-- contracts/interfaces/IImplementation.sol | 7 ++ contracts/interfaces/IInterchainToken.sol | 9 +++ .../interfaces/IInterchainTokenService.sol | 2 +- .../interfaces/IRemoteAddressValidator.sol | 4 +- contracts/interfaces/IStandardizedToken.sol | 21 ++---- .../interfaces/ITokenManagerLiquidityPool.sol | 7 +- .../interfaces/ITokenManagerLockUnlock.sol | 6 +- .../interfaces/ITokenManagerLockUnlockFee.sol | 6 +- .../interfaces/ITokenManagerMintBurn.sol | 6 +- contracts/proxies/StandardizedTokenProxy.sol | 4 +- .../RemoteAddressValidator.sol | 2 + .../token-implementations/ERC20Permit.sol | 4 +- .../StandardizedToken.sol | 10 ++- contracts/token-manager/TokenManager.sol | 9 +-- .../TokenManagerLiquidityPool.sol | 21 +++--- .../TokenManagerLockUnlock.sol | 19 ++--- .../TokenManagerLockUnlockFeeOnTransfer.sol | 20 +++--- .../implementations/TokenManagerMintBurn.sol | 12 ++-- contracts/utils/Implementation.sol | 8 --- contracts/utils/Multicall.sol | 1 + contracts/utils/StandardizedTokenDeployer.sol | 2 + contracts/utils/TokenManagerDeployer.sol | 2 + hardhat.config.js | 2 +- slither.config.json | 4 ++ 27 files changed, 170 insertions(+), 113 deletions(-) create mode 100644 .github/workflows/slither.yml create mode 100644 slither.config.json diff --git a/.github/workflows/slither.yml b/.github/workflows/slither.yml new file mode 100644 index 00000000..d807be46 --- /dev/null +++ b/.github/workflows/slither.yml @@ -0,0 +1,16 @@ +name: Slither Static Analysis + +on: + - pull_request + +jobs: + analyze: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + + - name: Install Dependencies + run: npm ci + + - name: Run Slither + uses: crytic/slither-action@v0.3.0 diff --git a/contracts/interchain-token-service/InterchainTokenService.sol b/contracts/interchain-token-service/InterchainTokenService.sol index 4ba539c6..3f4d36db 100644 --- a/contracts/interchain-token-service/InterchainTokenService.sol +++ b/contracts/interchain-token-service/InterchainTokenService.sol @@ -282,7 +282,9 @@ contract InterchainTokenService is function deployRemoteCanonicalToken(bytes32 tokenId, string calldata destinationChain, uint256 gasValue) public payable notPaused { address tokenAddress = getValidTokenManagerAddress(tokenId); tokenAddress = ITokenManager(tokenAddress).tokenAddress(); + if (getCanonicalTokenId(tokenAddress) != tokenId) revert NotCanonicalTokenManager(); + (string memory tokenName, string memory tokenSymbol, uint8 tokenDecimals) = _validateToken(tokenAddress); _deployRemoteStandardizedToken(tokenId, tokenName, tokenSymbol, tokenDecimals, '', '', 0, '', destinationChain, gasValue); } @@ -300,8 +302,10 @@ contract InterchainTokenService is ) public payable notPaused returns (bytes32 tokenId) { address deployer_ = msg.sender; tokenId = getCustomTokenId(deployer_, salt); - _deployTokenManager(tokenId, tokenManagerType, params); + emit CustomTokenIdClaimed(tokenId, deployer_, salt); + + _deployTokenManager(tokenId, tokenManagerType, params); } /** @@ -324,8 +328,10 @@ contract InterchainTokenService is ) external payable notPaused returns (bytes32 tokenId) { address deployer_ = msg.sender; tokenId = getCustomTokenId(deployer_, salt); - _deployRemoteTokenManager(tokenId, destinationChain, gasValue, tokenManagerType, params); + emit CustomTokenIdClaimed(tokenId, deployer_, salt); + + _deployRemoteTokenManager(tokenId, destinationChain, gasValue, tokenManagerType, params); } /** @@ -361,7 +367,7 @@ contract InterchainTokenService is * @param distributor the address that will be able to mint and burn the deployed token. * @param mintTo The address where the minted tokens will be sent upon deployment * @param mintAmount The amount of tokens to be minted upon deployment - * @param operator The operator data for standardized tokens + * @param operator_ The operator data for standardized tokens * @param destinationChain the name of the destination chain to deploy to. * @param gasValue the amount of native tokens to be used to pay for gas for the remote deployment. At least the amount * specified needs to be passed to the call @@ -375,7 +381,7 @@ contract InterchainTokenService is bytes memory distributor, bytes memory mintTo, uint256 mintAmount, - bytes memory operator, + bytes memory operator_, string calldata destinationChain, uint256 gasValue ) external payable notPaused { @@ -388,7 +394,7 @@ contract InterchainTokenService is distributor, mintTo, mintAmount, - operator, + operator_, destinationChain, gasValue ); @@ -490,11 +496,12 @@ contract InterchainTokenService is * @param tokenIds an array of the token Ids of the tokenManagers to set the flow limit of. * @param flowLimits the flowLimits to set */ - function setFlowLimit(bytes32[] calldata tokenIds, uint256[] calldata flowLimits) external onlyOperator { + function setFlowLimits(bytes32[] calldata tokenIds, uint256[] calldata flowLimits) external onlyOperator { uint256 length = tokenIds.length; if (length != flowLimits.length) revert LengthMismatch(); for (uint256 i; i < length; ++i) { ITokenManager tokenManager = ITokenManager(getValidTokenManagerAddress(tokenIds[i])); + // slither-disable-next-line calls-loop tokenManager.setFlowLimit(flowLimits[i]); } } @@ -580,6 +587,9 @@ contract InterchainTokenService is bytes memory data; (, , , , sourceAddress, data) = abi.decode(payload, (uint256, bytes32, bytes, uint256, bytes, bytes)); + // slither-disable-next-line reentrancy-events + emit TokenReceivedWithData(tokenId, sourceChain, destinationAddress, amount, sourceAddress, data); + IInterchainTokenExpressExecutable(destinationAddress).executeWithInterchainToken( sourceChain, sourceAddress, @@ -587,8 +597,8 @@ contract InterchainTokenService is tokenId, amount ); - emit TokenReceivedWithData(tokenId, sourceChain, destinationAddress, amount, sourceAddress, data); } else { + // slither-disable-next-line reentrancy-events emit TokenReceived(tokenId, sourceChain, destinationAddress, amount); } } @@ -688,9 +698,10 @@ contract InterchainTokenService is TokenManagerType tokenManagerType, bytes memory params ) internal { + emit RemoteTokenManagerDeploymentInitialized(tokenId, destinationChain, gasValue, tokenManagerType, params); + bytes memory payload = abi.encode(SELECTOR_DEPLOY_TOKEN_MANAGER, tokenId, tokenManagerType, params); _callContract(destinationChain, payload, gasValue); - emit RemoteTokenManagerDeploymentInitialized(tokenId, destinationChain, gasValue, tokenManagerType, params); } /** @@ -702,7 +713,7 @@ contract InterchainTokenService is * @param distributor The distributor address for the token * @param mintTo The address where the minted tokens will be sent upon deployment * @param mintAmount The amount of tokens to be minted upon deployment - * @param operator The operator data for standardized tokens + * @param operator_ The operator data for standardized tokens * @param destinationChain The destination chain where the token will be deployed * @param gasValue The amount of gas to be paid for the transaction */ @@ -714,12 +725,12 @@ contract InterchainTokenService is bytes memory distributor, bytes memory mintTo, uint256 mintAmount, - bytes memory operator, + bytes memory operator_, string calldata destinationChain, uint256 gasValue ) internal { - bytes memory payload = abi.encode( - SELECTOR_DEPLOY_AND_REGISTER_STANDARDIZED_TOKEN, + // slither-disable-next-line reentrancy-events + emit RemoteStandardizedTokenAndManagerDeploymentInitialized( tokenId, name, symbol, @@ -727,10 +738,13 @@ contract InterchainTokenService is distributor, mintTo, mintAmount, - operator + operator_, + destinationChain, + gasValue ); - _callContract(destinationChain, payload, gasValue); - emit RemoteStandardizedTokenAndManagerDeploymentInitialized( + + bytes memory payload = abi.encode( + SELECTOR_DEPLOY_AND_REGISTER_STANDARDIZED_TOKEN, tokenId, name, symbol, @@ -738,10 +752,9 @@ contract InterchainTokenService is distributor, mintTo, mintAmount, - operator, - destinationChain, - gasValue + operator_ ); + _callContract(destinationChain, payload, gasValue); } /** @@ -751,13 +764,14 @@ contract InterchainTokenService is * @param params Additional parameters for the token manager deployment */ function _deployTokenManager(bytes32 tokenId, TokenManagerType tokenManagerType, bytes memory params) internal { + // slither-disable-next-line reentrancy-events + emit TokenManagerDeployed(tokenId, tokenManagerType, params); + + // slither-disable-next-line controlled-delegatecall (bool success, ) = tokenManagerDeployer.delegatecall( abi.encodeWithSelector(ITokenManagerDeployer.deployTokenManager.selector, tokenId, tokenManagerType, params) ); - if (!success) { - revert TokenManagerDeploymentFailed(); - } - emit TokenManagerDeployed(tokenId, tokenManagerType, params); + if (!success) revert TokenManagerDeploymentFailed(); } /** @@ -788,9 +802,12 @@ contract InterchainTokenService is uint256 mintAmount, address mintTo ) internal { + emit StandardizedTokenDeployed(tokenId, distributor, name, symbol, decimals, mintAmount, mintTo); + bytes32 salt = _getStandardizedTokenSalt(tokenId); address tokenManagerAddress = getTokenManagerAddress(tokenId); + // slither-disable-next-line controlled-delegatecall (bool success, ) = standardizedTokenDeployer.delegatecall( abi.encodeWithSelector( IStandardizedTokenDeployer.deployStandardizedToken.selector, @@ -807,7 +824,6 @@ contract InterchainTokenService is if (!success) { revert StandardizedTokenDeploymentFailed(); } - emit StandardizedTokenDeployed(tokenId, distributor, name, symbol, decimals, mintAmount, mintTo); } function _decodeMetadata(bytes memory metadata) internal pure returns (uint32 version, bytes memory data) { @@ -860,16 +876,21 @@ contract InterchainTokenService is ) internal { bytes memory payload; if (metadata.length < 4) { + // slither-disable-next-line reentrancy-events + emit TokenSent(tokenId, destinationChain, destinationAddress, amount); + payload = abi.encode(SELECTOR_SEND_TOKEN, tokenId, destinationAddress, amount); _callContract(destinationChain, payload, msg.value); - emit TokenSent(tokenId, destinationChain, destinationAddress, amount); return; } uint32 version; (version, metadata) = _decodeMetadata(metadata); if (version > 0) revert InvalidMetadataVersion(version); + + // slither-disable-next-line reentrancy-events + emit TokenSentWithData(tokenId, destinationChain, destinationAddress, amount, sourceAddress, metadata); + payload = abi.encode(SELECTOR_SEND_TOKEN_WITH_DATA, tokenId, destinationAddress, amount, sourceAddress.toBytes(), metadata); _callContract(destinationChain, payload, msg.value); - emit TokenSentWithData(tokenId, destinationChain, destinationAddress, amount, sourceAddress, metadata); } } diff --git a/contracts/interfaces/IDistributable.sol b/contracts/interfaces/IDistributable.sol index 7605eccd..cfe446dc 100644 --- a/contracts/interfaces/IDistributable.sol +++ b/contracts/interfaces/IDistributable.sol @@ -11,16 +11,16 @@ interface IDistributable { /** * @notice Get the address of the distributor - * @return distributor of the distributor + * @return distributor_ of the distributor */ - function distributor() external view returns (address distributor); + function distributor() external view returns (address distributor_); /** * @notice Change the distributor of the contract * @dev Can only be called by the current distributor - * @param distributor The address of the new distributor + * @param distributor_ The address of the new distributor */ - function transferDistributorship(address distributor) external; + function transferDistributorship(address distributor_) external; /** * @notice Proposed a change of the distributor of the contract diff --git a/contracts/interfaces/IImplementation.sol b/contracts/interfaces/IImplementation.sol index 950c90a3..357d3b22 100644 --- a/contracts/interfaces/IImplementation.sol +++ b/contracts/interfaces/IImplementation.sol @@ -4,4 +4,11 @@ pragma solidity ^0.8.0; interface IImplementation { error NotProxy(); + + /** + * @notice Called by the proxy to setup itself. + * @dev This should be hidden by the proxy. + * @param params the data to be used for the initialization. + */ + function setup(bytes calldata params) external; } diff --git a/contracts/interfaces/IInterchainToken.sol b/contracts/interfaces/IInterchainToken.sol index c4456cd6..2a427aa3 100644 --- a/contracts/interfaces/IInterchainToken.sol +++ b/contracts/interfaces/IInterchainToken.sol @@ -2,10 +2,19 @@ pragma solidity ^0.8.0; +import { ITokenManager } from './ITokenManager.sol'; + /** * @dev Interface of the ERC20 standard as defined in the EIP. */ interface IInterchainToken { + /** + * @notice Getter for the tokenManager used for this token. + * @dev Needs to be overwitten. + * @return tokenManager_ the TokenManager called to facilitate cross chain transfers. + */ + function tokenManager() external view returns (ITokenManager tokenManager_); + /** * @notice Implementation of the interchainTransfer method * @dev We chose to either pass `metadata` as raw data on a remote contract call, or, if no data is passed, just do a transfer. diff --git a/contracts/interfaces/IInterchainTokenService.sol b/contracts/interfaces/IInterchainTokenService.sol index a46bcfd2..2c63d8d8 100644 --- a/contracts/interfaces/IInterchainTokenService.sol +++ b/contracts/interfaces/IInterchainTokenService.sol @@ -266,7 +266,7 @@ interface IInterchainTokenService is ITokenManagerType, IExpressCallHandler, IAx * @param tokenIds An array of tokenIds. * @param flowLimits An array of flow limits corresponding to the tokenIds. */ - function setFlowLimit(bytes32[] calldata tokenIds, uint256[] calldata flowLimits) external; + function setFlowLimits(bytes32[] calldata tokenIds, uint256[] calldata flowLimits) external; /** * @notice Returns the flow limit for a specific token. diff --git a/contracts/interfaces/IRemoteAddressValidator.sol b/contracts/interfaces/IRemoteAddressValidator.sol index 93d6eda7..0d54e3e2 100644 --- a/contracts/interfaces/IRemoteAddressValidator.sol +++ b/contracts/interfaces/IRemoteAddressValidator.sol @@ -52,8 +52,8 @@ interface IRemoteAddressValidator { /** * @dev Fetches the interchain token service address for the specified chain - * @param chainName Name of the chain + * @param chainName_ Name of the chain * @return remoteAddress Interchain token service address for the specified chain */ - function getRemoteAddress(string calldata chainName) external view returns (string memory remoteAddress); + function getRemoteAddress(string calldata chainName_) external view returns (string memory remoteAddress); } diff --git a/contracts/interfaces/IStandardizedToken.sol b/contracts/interfaces/IStandardizedToken.sol index 9763a2ff..1fbd40bd 100644 --- a/contracts/interfaces/IStandardizedToken.sol +++ b/contracts/interfaces/IStandardizedToken.sol @@ -2,10 +2,10 @@ pragma solidity ^0.8.0; +import { IImplementation } from './IImplementation.sol'; import { IInterchainToken } from './IInterchainToken.sol'; import { IDistributable } from './IDistributable.sol'; import { IERC20MintableBurnable } from './IERC20MintableBurnable.sol'; -import { ITokenManager } from './ITokenManager.sol'; import { IERC20 } from '@axelar-network/axelar-gmp-sdk-solidity/contracts/interfaces/IERC20.sol'; /** @@ -13,23 +13,12 @@ import { IERC20 } from '@axelar-network/axelar-gmp-sdk-solidity/contracts/interf * @notice This contract implements a standardized token which extends InterchainToken functionality. * This contract also inherits Distributable and Implementation logic. */ -interface IStandardizedToken is IInterchainToken, IDistributable, IERC20MintableBurnable, IERC20 { +interface IStandardizedToken is IImplementation, IInterchainToken, IDistributable, IERC20MintableBurnable, IERC20 { + error TokenManagerAddressZero(); + error TokenNameEmpty(); + /** * @notice Returns the contract id, which a proxy can check to ensure no false implementation was used. */ function contractId() external view returns (bytes32); - - /** - * @notice Called by the proxy to setup itself. - * @dev This should be hidden by the proxy. - * @param params the data to be used for the initialization. - */ - function setup(bytes calldata params) external; - - /** - * @notice Getter for the tokenManager used for this token. - * @dev Needs to be overwitten. - * @return tokenManager_ the TokenManager called to facilitate cross chain transfers. - */ - function tokenManager() external view returns (ITokenManager tokenManager_); } diff --git a/contracts/interfaces/ITokenManagerLiquidityPool.sol b/contracts/interfaces/ITokenManagerLiquidityPool.sol index 902a0d1f..7390d428 100644 --- a/contracts/interfaces/ITokenManagerLiquidityPool.sol +++ b/contracts/interfaces/ITokenManagerLiquidityPool.sol @@ -11,11 +11,12 @@ import { ITokenManager } from './ITokenManager.sol'; interface ITokenManagerLiquidityPool is ITokenManager { /** * @notice Getter function for the parameters of a lock/unlock TokenManager. Mainly to be used by frontends. - * @param operator the operator of the TokenManager. - * @param tokenAddress the token to be managed. + * @param operator_ the operator of the TokenManager. + * @param tokenAddress_ the token to be managed. + * @param liquidityPool_ he address of the liquidity pool. * @return params the resulting params to be passed to custom TokenManager deployments. */ - function getParams(bytes memory operator, address tokenAddress, address liquidityPool) external pure returns (bytes memory params); + function getParams(bytes memory operator_, address tokenAddress_, address liquidityPool_) external pure returns (bytes memory params); /** * @dev Reads the stored liquidity pool address from the specified storage slot diff --git a/contracts/interfaces/ITokenManagerLockUnlock.sol b/contracts/interfaces/ITokenManagerLockUnlock.sol index 5c009ae8..cf8688c2 100644 --- a/contracts/interfaces/ITokenManagerLockUnlock.sol +++ b/contracts/interfaces/ITokenManagerLockUnlock.sol @@ -11,9 +11,9 @@ import { ITokenManager } from './ITokenManager.sol'; interface ITokenManagerLockUnlock is ITokenManager { /** * @notice Getter function for the parameters of a lock/unlock TokenManager. Mainly to be used by frontends. - * @param operator the operator of the TokenManager. - * @param tokenAddress the token to be managed. + * @param operator_ the operator of the TokenManager. + * @param tokenAddress_ the token to be managed. * @return params the resulting params to be passed to custom TokenManager deployments. */ - function getParams(bytes memory operator, address tokenAddress) external pure returns (bytes memory params); + function getParams(bytes memory operator_, address tokenAddress_) external pure returns (bytes memory params); } diff --git a/contracts/interfaces/ITokenManagerLockUnlockFee.sol b/contracts/interfaces/ITokenManagerLockUnlockFee.sol index 686b01d3..8dd3987c 100644 --- a/contracts/interfaces/ITokenManagerLockUnlockFee.sol +++ b/contracts/interfaces/ITokenManagerLockUnlockFee.sol @@ -11,9 +11,9 @@ import { ITokenManager } from './ITokenManager.sol'; interface ITokenManagerLockUnlockFee is ITokenManager { /** * @notice Getter function for the parameters of a lock/unlock TokenManager. Mainly to be used by frontends. - * @param operator the operator of the TokenManager. - * @param tokenAddress the token to be managed. + * @param operator_ the operator of the TokenManager. + * @param tokenAddress_ the token to be managed. * @return params the resulting params to be passed to custom TokenManager deployments. */ - function getParams(bytes memory operator, address tokenAddress) external pure returns (bytes memory params); + function getParams(bytes memory operator_, address tokenAddress_) external pure returns (bytes memory params); } diff --git a/contracts/interfaces/ITokenManagerMintBurn.sol b/contracts/interfaces/ITokenManagerMintBurn.sol index b9e1f4d1..5f954fc2 100644 --- a/contracts/interfaces/ITokenManagerMintBurn.sol +++ b/contracts/interfaces/ITokenManagerMintBurn.sol @@ -11,9 +11,9 @@ import { ITokenManager } from './ITokenManager.sol'; interface ITokenManagerMintBurn is ITokenManager { /** * @notice Getter function for the parameters of a lock/unlock TokenManager. Mainly to be used by frontends. - * @param operator the operator of the TokenManager. - * @param tokenAddress the token to be managed. + * @param operator_ the operator of the TokenManager. + * @param tokenAddress_ the token to be managed. * @return params the resulting params to be passed to custom TokenManager deployments. */ - function getParams(bytes memory operator, address tokenAddress) external pure returns (bytes memory params); + function getParams(bytes memory operator_, address tokenAddress_) external pure returns (bytes memory params); } diff --git a/contracts/proxies/StandardizedTokenProxy.sol b/contracts/proxies/StandardizedTokenProxy.sol index 7dcac348..d82d3989 100644 --- a/contracts/proxies/StandardizedTokenProxy.sol +++ b/contracts/proxies/StandardizedTokenProxy.sol @@ -3,8 +3,10 @@ pragma solidity ^0.8.0; import { FixedProxy } from '@axelar-network/axelar-gmp-sdk-solidity/contracts/upgradable/FixedProxy.sol'; + import { IStandardizedToken } from '../interfaces/IStandardizedToken.sol'; import { IStandardizedTokenProxy } from '../interfaces/IStandardizedTokenProxy.sol'; +import { IImplementation } from '../interfaces/IImplementation.sol'; /** * @title StandardizedTokenProxy @@ -21,7 +23,7 @@ contract StandardizedTokenProxy is FixedProxy, IStandardizedTokenProxy { constructor(address implementationAddress, bytes memory params) FixedProxy(implementationAddress) { if (IStandardizedToken(implementationAddress).contractId() != CONTRACT_ID) revert InvalidImplementation(); - (bool success, ) = implementationAddress.delegatecall(abi.encodeWithSelector(IStandardizedToken.setup.selector, params)); + (bool success, ) = implementationAddress.delegatecall(abi.encodeWithSelector(IImplementation.setup.selector, params)); if (!success) revert SetupFailed(); } diff --git a/contracts/remote-address-validator/RemoteAddressValidator.sol b/contracts/remote-address-validator/RemoteAddressValidator.sol index 89d7d40c..bb0581e4 100644 --- a/contracts/remote-address-validator/RemoteAddressValidator.sol +++ b/contracts/remote-address-validator/RemoteAddressValidator.sol @@ -23,7 +23,9 @@ contract RemoteAddressValidator is IRemoteAddressValidator, Upgradable { /** * @dev Store the interchain token service address as string across two immutable variables to avoid recomputation and save gas */ + // slither-disable-next-line similar-names uint256 private immutable interchainTokenServiceAddress1; + // slither-disable-next-line similar-names uint256 private immutable interchainTokenServiceAddress2; bytes32 private constant CONTRACT_ID = keccak256('remote-address-validator'); diff --git a/contracts/token-implementations/ERC20Permit.sol b/contracts/token-implementations/ERC20Permit.sol index 349bd7de..2747d6de 100644 --- a/contracts/token-implementations/ERC20Permit.sol +++ b/contracts/token-implementations/ERC20Permit.sol @@ -49,8 +49,8 @@ abstract contract ERC20Permit is IERC20, IERC20Permit, ERC20 { * @notice Calculates the DOMAIN_SEPARATOR. * @dev This is not cached because chainid can change on chain forks. */ - // solhint-disable-next-line func-name-mixedcase - function DOMAIN_SEPARATOR() public view returns (bytes32 domainSeparator) { + // slither-disable-next-line naming-convention + function DOMAIN_SEPARATOR() public view returns (bytes32 domainSeparator) { // solhint-disable-line func-name-mixedcase domainSeparator = keccak256(abi.encode(DOMAIN_TYPE_SIGNATURE_HASH, nameHash, keccak256(bytes('1')), block.chainid, address(this))); } diff --git a/contracts/token-implementations/StandardizedToken.sol b/contracts/token-implementations/StandardizedToken.sol index 769fa53e..80e1dbad 100644 --- a/contracts/token-implementations/StandardizedToken.sol +++ b/contracts/token-implementations/StandardizedToken.sol @@ -2,8 +2,9 @@ pragma solidity ^0.8.0; -import { IERC20MintableBurnable } from '../interfaces/IERC20MintableBurnable.sol'; +import { IStandardizedToken } from '../interfaces/IStandardizedToken.sol'; import { ITokenManager } from '../interfaces/ITokenManager.sol'; +import { IInterchainToken } from '../interfaces/IInterchainToken.sol'; import { InterchainToken } from '../interchain-token/InterchainToken.sol'; import { ERC20Permit } from '../token-implementations/ERC20Permit.sol'; @@ -16,7 +17,7 @@ import { Distributable } from '../utils/Distributable.sol'; * @notice This contract implements a standardized token which extends InterchainToken functionality. * This contract also inherits Distributable and Implementation logic. */ -contract StandardizedToken is IERC20MintableBurnable, InterchainToken, ERC20Permit, Implementation, Distributable { +contract StandardizedToken is InterchainToken, ERC20Permit, Implementation, Distributable, IStandardizedToken { using AddressBytesUtils for bytes; string public name; @@ -45,7 +46,7 @@ contract StandardizedToken is IERC20MintableBurnable, InterchainToken, ERC20Perm * @notice Returns the token manager for this token * @return ITokenManager The token manager contract */ - function tokenManager() public view override returns (ITokenManager) { + function tokenManager() public view override(InterchainToken, IInterchainToken) returns (ITokenManager) { return ITokenManager(tokenManager_); } @@ -64,6 +65,9 @@ contract StandardizedToken is IERC20MintableBurnable, InterchainToken, ERC20Perm (address, address, string, string, uint8) ); + if (tokenManagerAddress == address(0)) revert TokenManagerAddressZero(); + if (bytes(tokenName).length == 0) revert TokenNameEmpty(); + tokenManager_ = tokenManagerAddress; name = tokenName; diff --git a/contracts/token-manager/TokenManager.sol b/contracts/token-manager/TokenManager.sol index 516baea5..507e7c5e 100644 --- a/contracts/token-manager/TokenManager.sol +++ b/contracts/token-manager/TokenManager.sol @@ -60,9 +60,10 @@ abstract contract TokenManager is ITokenManager, Operatable, FlowLimit, Implemen /** * @notice A function that returns the token id. - * @dev This will only work when called by a proxy, which hides this and returns the correct value. + * @dev This will only work when implementation is called by a proxy, which stores the tokenId as an immutable. */ function tokenId() public view returns (bytes32) { + // slither-disable-next-line var-read-using-this return this.tokenId(); } @@ -108,7 +109,7 @@ abstract contract TokenManager is ITokenManager, Operatable, FlowLimit, Implemen _addFlowOut(amount); interchainTokenService.transmitSendToken{ value: msg.value }( - this.tokenId(), + tokenId(), sender, destinationChain, destinationAddress, @@ -135,7 +136,7 @@ abstract contract TokenManager is ITokenManager, Operatable, FlowLimit, Implemen _addFlowOut(amount); uint32 version = 0; interchainTokenService.transmitSendToken{ value: msg.value }( - this.tokenId(), + tokenId(), sender, destinationChain, destinationAddress, @@ -162,7 +163,7 @@ abstract contract TokenManager is ITokenManager, Operatable, FlowLimit, Implemen amount = _takeToken(sender, amount); _addFlowOut(amount); interchainTokenService.transmitSendToken{ value: msg.value }( - this.tokenId(), + tokenId(), sender, destinationChain, destinationAddress, diff --git a/contracts/token-manager/implementations/TokenManagerLiquidityPool.sol b/contracts/token-manager/implementations/TokenManagerLiquidityPool.sol index 5089a444..51ad6f1a 100644 --- a/contracts/token-manager/implementations/TokenManagerLiquidityPool.sol +++ b/contracts/token-manager/implementations/TokenManagerLiquidityPool.sol @@ -2,13 +2,13 @@ pragma solidity ^0.8.0; -import { TokenManager } from '../TokenManager.sol'; -import { NoReEntrancy } from '../../utils/NoReEntrancy.sol'; import { IERC20 } from '@axelar-network/axelar-gmp-sdk-solidity/contracts/interfaces/IERC20.sol'; -import { ITokenManagerLiquidityPool } from '../../interfaces/ITokenManagerLiquidityPool.sol'; - import { SafeTokenTransferFrom } from '@axelar-network/axelar-gmp-sdk-solidity/contracts/utils/SafeTransfer.sol'; +import { ITokenManagerLiquidityPool } from '../../interfaces/ITokenManagerLiquidityPool.sol'; +import { TokenManager } from '../TokenManager.sol'; +import { NoReEntrancy } from '../../utils/NoReEntrancy.sol'; + /** * @title TokenManagerLiquidityPool * @notice This contract is a an implementation of TokenManager that stores all tokens in a separate liquity pool @@ -16,7 +16,7 @@ import { SafeTokenTransferFrom } from '@axelar-network/axelar-gmp-sdk-solidity/c * @dev This contract extends TokenManagerAddressStorage and provides implementation for its abstract methods. * It uses the Axelar SDK to safely transfer tokens. */ -contract TokenManagerLiquidityPool is TokenManager, NoReEntrancy { +contract TokenManagerLiquidityPool is TokenManager, NoReEntrancy, ITokenManagerLiquidityPool { using SafeTokenTransferFrom for IERC20; // uint256(keccak256('liquidity-pool-slot')) - 1 @@ -102,6 +102,7 @@ contract TokenManagerLiquidityPool is TokenManager, NoReEntrancy { IERC20 token = IERC20(tokenAddress()); uint256 balance = token.balanceOf(to); + // slither-disable-next-line arbitrary-send-erc20 token.safeTransferFrom(liquidityPool(), to, amount); uint256 diff = token.balanceOf(to) - balance; @@ -113,16 +114,16 @@ contract TokenManagerLiquidityPool is TokenManager, NoReEntrancy { /** * @notice Getter function for the parameters of a liquidity pool TokenManager. Mainly to be used by frontends. - * @param operator the operator of the TokenManager. - * @param tokenAddress the token to be managed. + * @param operator_ the operator of the TokenManager. + * @param tokenAddress_ the token to be managed. * @param liquidityPoolAddress the liquidity pool to be used to store the bridged tokens. * @return params the resulting params to be passed to custom TokenManager deployments. */ function getParams( - bytes memory operator, - address tokenAddress, + bytes memory operator_, + address tokenAddress_, address liquidityPoolAddress ) external pure returns (bytes memory params) { - params = abi.encode(operator, tokenAddress, liquidityPoolAddress); + params = abi.encode(operator_, tokenAddress_, liquidityPoolAddress); } } diff --git a/contracts/token-manager/implementations/TokenManagerLockUnlock.sol b/contracts/token-manager/implementations/TokenManagerLockUnlock.sol index 96ebce7e..18ed3fa2 100644 --- a/contracts/token-manager/implementations/TokenManagerLockUnlock.sol +++ b/contracts/token-manager/implementations/TokenManagerLockUnlock.sol @@ -2,12 +2,13 @@ pragma solidity ^0.8.0; -import { TokenManager } from '../TokenManager.sol'; -import { IERC20 } from '@axelar-network/axelar-gmp-sdk-solidity/contracts/interfaces/IERC20.sol'; -import { ITokenManagerLockUnlock } from '../../interfaces/ITokenManagerLockUnlock.sol'; +import { IERC20 } from '@axelar-network/axelar-gmp-sdk-solidity/contracts/interfaces/IERC20.sol'; import { SafeTokenTransfer, SafeTokenTransferFrom } from '@axelar-network/axelar-gmp-sdk-solidity/contracts/utils/SafeTransfer.sol'; +import { ITokenManagerLockUnlock } from '../../interfaces/ITokenManagerLockUnlock.sol'; +import { TokenManager } from '../TokenManager.sol'; + /** * @title TokenManagerLockUnlock * @notice This contract is an implementation of TokenManager that locks and unlocks a specific token on behalf of the interchain token service. @@ -35,8 +36,8 @@ contract TokenManagerLockUnlock is TokenManager, ITokenManagerLockUnlock { */ function _setup(bytes calldata params) internal override { // The first argument is reserved for the operator. - (, address tokenAddress) = abi.decode(params, (bytes, address)); - _setTokenAddress(tokenAddress); + (, address tokenAddress_) = abi.decode(params, (bytes, address)); + _setTokenAddress(tokenAddress_); } /** @@ -69,11 +70,11 @@ contract TokenManagerLockUnlock is TokenManager, ITokenManagerLockUnlock { /** * @notice Getter function for the parameters of a lock/unlock TokenManager. Mainly to be used by frontends. - * @param operator the operator of the TokenManager. - * @param tokenAddress the token to be managed. + * @param operator_ the operator of the TokenManager. + * @param tokenAddress_ the token to be managed. * @return params the resulting params to be passed to custom TokenManager deployments. */ - function getParams(bytes memory operator, address tokenAddress) external pure returns (bytes memory params) { - params = abi.encode(operator, tokenAddress); + function getParams(bytes memory operator_, address tokenAddress_) external pure returns (bytes memory params) { + params = abi.encode(operator_, tokenAddress_); } } diff --git a/contracts/token-manager/implementations/TokenManagerLockUnlockFeeOnTransfer.sol b/contracts/token-manager/implementations/TokenManagerLockUnlockFeeOnTransfer.sol index 733ec6aa..225f4044 100644 --- a/contracts/token-manager/implementations/TokenManagerLockUnlockFeeOnTransfer.sol +++ b/contracts/token-manager/implementations/TokenManagerLockUnlockFeeOnTransfer.sol @@ -2,11 +2,13 @@ pragma solidity ^0.8.0; +import { IERC20 } from '@axelar-network/axelar-gmp-sdk-solidity/contracts/interfaces/IERC20.sol'; +import { SafeTokenTransferFrom, SafeTokenTransfer } from '@axelar-network/axelar-gmp-sdk-solidity/contracts/utils/SafeTransfer.sol'; + +import { ITokenManagerLockUnlock } from '../../interfaces/ITokenManagerLockUnlock.sol'; import { TokenManager } from '../TokenManager.sol'; import { NoReEntrancy } from '../../utils/NoReEntrancy.sol'; -import { IERC20 } from '@axelar-network/axelar-gmp-sdk-solidity/contracts/interfaces/IERC20.sol'; -import { SafeTokenTransferFrom, SafeTokenTransfer } from '@axelar-network/axelar-gmp-sdk-solidity/contracts/utils/SafeTransfer.sol'; /** * @title TokenManagerLockUnlock @@ -14,7 +16,7 @@ import { SafeTokenTransferFrom, SafeTokenTransfer } from '@axelar-network/axelar * @dev This contract extends TokenManagerAddressStorage and provides implementation for its abstract methods. * It uses the Axelar SDK to safely transfer tokens. */ -contract TokenManagerLockUnlockFee is TokenManager, NoReEntrancy { +contract TokenManagerLockUnlockFee is TokenManager, NoReEntrancy, ITokenManagerLockUnlock { using SafeTokenTransfer for IERC20; using SafeTokenTransferFrom for IERC20; @@ -35,8 +37,8 @@ contract TokenManagerLockUnlockFee is TokenManager, NoReEntrancy { */ function _setup(bytes calldata params) internal override { // The first argument is reserved for the operator. - (, address tokenAddress) = abi.decode(params, (bytes, address)); - _setTokenAddress(tokenAddress); + (, address tokenAddress_) = abi.decode(params, (bytes, address)); + _setTokenAddress(tokenAddress_); } /** @@ -79,11 +81,11 @@ contract TokenManagerLockUnlockFee is TokenManager, NoReEntrancy { /** * @notice Getter function for the parameters of a lock/unlock TokenManager. Mainly to be used by frontends. - * @param operator the operator of the TokenManager. - * @param tokenAddress the token to be managed. + * @param operator_ the operator of the TokenManager. + * @param tokenAddress_ the token to be managed. * @return params the resulting params to be passed to custom TokenManager deployments. */ - function getParams(bytes memory operator, address tokenAddress) external pure returns (bytes memory params) { - params = abi.encode(operator, tokenAddress); + function getParams(bytes memory operator_, address tokenAddress_) external pure returns (bytes memory params) { + params = abi.encode(operator_, tokenAddress_); } } diff --git a/contracts/token-manager/implementations/TokenManagerMintBurn.sol b/contracts/token-manager/implementations/TokenManagerMintBurn.sol index 779fd80f..0286293f 100644 --- a/contracts/token-manager/implementations/TokenManagerMintBurn.sol +++ b/contracts/token-manager/implementations/TokenManagerMintBurn.sol @@ -35,8 +35,8 @@ contract TokenManagerMintBurn is TokenManager, ITokenManagerMintBurn { */ function _setup(bytes calldata params) internal override { // The first argument is reserved for the operator. - (, address tokenAddress) = abi.decode(params, (bytes, address)); - _setTokenAddress(tokenAddress); + (, address tokenAddress_) = abi.decode(params, (bytes, address)); + _setTokenAddress(tokenAddress_); } /** @@ -69,11 +69,11 @@ contract TokenManagerMintBurn is TokenManager, ITokenManagerMintBurn { /** * @notice Getter function for the parameters of a lock/unlock TokenManager. Mainly to be used by frontends. - * @param operator the operator of the TokenManager. - * @param tokenAddress the token to be managed. + * @param operator_ the operator of the TokenManager. + * @param tokenAddress_ the token to be managed. * @return params the resulting params to be passed to custom TokenManager deployments. */ - function getParams(bytes memory operator, address tokenAddress) external pure returns (bytes memory params) { - params = abi.encode(operator, tokenAddress); + function getParams(bytes memory operator_, address tokenAddress_) external pure returns (bytes memory params) { + params = abi.encode(operator_, tokenAddress_); } } diff --git a/contracts/utils/Implementation.sol b/contracts/utils/Implementation.sol index 2ae3fd09..ad662978 100644 --- a/contracts/utils/Implementation.sol +++ b/contracts/utils/Implementation.sol @@ -27,12 +27,4 @@ abstract contract Implementation is IImplementation { if (implementationAddress == address(this)) revert NotProxy(); _; } - - /** - * @notice Initializes contract parameters. - * This function is intended to be overridden by derived contracts. - * The overriding function must have the onlyProxy modifier. - * @param params The parameters to be used for initialization - */ - function setup(bytes calldata params) external virtual; } diff --git a/contracts/utils/Multicall.sol b/contracts/utils/Multicall.sol index 50914d39..55fe0ad2 100644 --- a/contracts/utils/Multicall.sol +++ b/contracts/utils/Multicall.sol @@ -24,6 +24,7 @@ contract Multicall is IMulticall { bool success; bytes memory result; for (uint256 i = 0; i < data.length; ++i) { + // slither-disable-next-line calls-loop,delegatecall-loop (success, result) = address(this).delegatecall(data[i]); if (!success) { diff --git a/contracts/utils/StandardizedTokenDeployer.sol b/contracts/utils/StandardizedTokenDeployer.sol index 77536f3f..da28e244 100644 --- a/contracts/utils/StandardizedTokenDeployer.sol +++ b/contracts/utils/StandardizedTokenDeployer.sol @@ -35,6 +35,7 @@ contract StandardizedTokenDeployer is IStandardizedTokenDeployer { * @param mintAmount Amount of tokens to mint initially * @param mintTo Address to mint initial tokens to */ + // slither-disable-next-line locked-ether function deployStandardizedToken( bytes32 salt, address tokenManager, @@ -46,6 +47,7 @@ contract StandardizedTokenDeployer is IStandardizedTokenDeployer { address mintTo ) external payable { bytes memory params = abi.encode(tokenManager, distributor, name, symbol, decimals, mintAmount, mintTo); + // slither-disable-next-line too-many-digits bytes memory bytecode = bytes.concat(type(StandardizedTokenProxy).creationCode, abi.encode(implementationAddress, params)); address tokenAddress = Create3.deploy(salt, bytecode); diff --git a/contracts/utils/TokenManagerDeployer.sol b/contracts/utils/TokenManagerDeployer.sol index 14040795..a2fb413b 100644 --- a/contracts/utils/TokenManagerDeployer.sol +++ b/contracts/utils/TokenManagerDeployer.sol @@ -19,8 +19,10 @@ contract TokenManagerDeployer is ITokenManagerDeployer { * @param implementationType Token manager implementation type * @param params Additional parameters used in the setup of the token manager */ + // slither-disable-next-line locked-ether function deployTokenManager(bytes32 tokenId, uint256 implementationType, bytes calldata params) external payable { bytes memory args = abi.encode(address(this), implementationType, tokenId, params); + // slither-disable-next-line too-many-digits bytes memory bytecode = abi.encodePacked(type(TokenManagerProxy).creationCode, args); address tokenManagerAddress = Create3.deploy(tokenId, bytecode); if (tokenManagerAddress.code.length == 0) revert TokenManagerDeploymentFailed(); diff --git a/hardhat.config.js b/hardhat.config.js index b4a3f6ad..709fbfc6 100644 --- a/hardhat.config.js +++ b/hardhat.config.js @@ -13,7 +13,7 @@ const { networks, etherscan } = importNetworks(chains, keys); */ module.exports = { solidity: { - version: '0.8.18', + version: '0.8.19', settings: { evmVersion: process.env.EVM_VERSION || 'london', optimizer: { diff --git a/slither.config.json b/slither.config.json new file mode 100644 index 00000000..1a22cab9 --- /dev/null +++ b/slither.config.json @@ -0,0 +1,4 @@ +{ + "detectors_to_exclude": "assembly,low-level-calls,solc-version,timestamp,dead-code", + "filter_paths": "(contracts/test/|node_modules/)" +}