Skip to content

CEI violation in FxERC20ChildTunnel.sol #76

@b0gdaniy

Description

@b0gdaniy

There is a CEI (Checks-Effects-Interactions) pattern violation in FxERC20ChildTunnel.sol.
In costructor() assignment value tokenTemplate = _tokenTemplate; before _isContract(_tokenTemplate) check:

    constructor(address _fxChild, address _tokenTemplate) FxBaseChildTunnel(_fxChild) {
        tokenTemplate = _tokenTemplate; // Effect on state variable
        require(_isContract(_tokenTemplate), "Token template is not contract"); // Check
    }

so the code should look like this:

    constructor(address _fxChild, address _tokenTemplate) FxBaseChildTunnel(_fxChild) {
        require(_isContract(_tokenTemplate), "Token template is not contract"); // Check
        tokenTemplate = _tokenTemplate; // Interaction with state variable
    }

Also in _mapToken() function where
IFxERC20(childToken).initialize() called before rootToChildToken[rootToken] = childToken:

function _mapToken(bytes memory syncData) internal returns (address) {
        (address rootToken, string memory name, string memory symbol, uint8 decimals) = abi.decode(
            syncData,
            (address, string, string, uint8)
        );

        // get root to child token
        address childToken = rootToChildToken[rootToken];

        // check if it's already mapped
        require(childToken == address(0x0), "FxERC20ChildTunnel: ALREADY_MAPPED");

        // deploy new child token
        bytes32 salt = keccak256(abi.encodePacked(rootToken));
        childToken = createClone(salt, tokenTemplate);
        // slither-disable-next-line reentrancy-no-eth
        IFxERC20(childToken).initialize(
            address(this),
            rootToken,
            string(abi.encodePacked(name, SUFFIX_NAME)),
            string(abi.encodePacked(PREFIX_SYMBOL, symbol)),
            decimals
        ); // Interaction with childToken

        // map the token
        rootToChildToken[rootToken] = childToken; // Effect on state variable
        emit TokenMapped(rootToken, childToken);

        // return new child token
        return childToken;
    }

and code should look like:

function _mapToken(bytes memory syncData) internal returns (address) {
        (address rootToken, string memory name, string memory symbol, uint8 decimals) = abi.decode(
            syncData,
            (address, string, string, uint8)
        );

        // get root to child token
        address childToken = rootToChildToken[rootToken];

        // check if it's already mapped
        require(childToken == address(0x0), "FxERC20ChildTunnel: ALREADY_MAPPED");

        // deploy new child token
        bytes32 salt = keccak256(abi.encodePacked(rootToken));
        childToken = createClone(salt, tokenTemplate);

        // map the token
        rootToChildToken[rootToken] = childToken; // Effect on state variable
        
        // slither-disable-next-line reentrancy-no-eth
        IFxERC20(childToken).initialize(
            address(this),
            rootToken,
            string(abi.encodePacked(name, SUFFIX_NAME)),
            string(abi.encodePacked(PREFIX_SYMBOL, symbol)),
            decimals
        ); // Interaction with childToken
        
        emit TokenMapped(rootToken, childToken);

        // return new child token
        return childToken;
    }

These changes reduce gas cost if some of these checks will revert an error, before effects/interactions.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions