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

DOMAIN_SEPARATOR of ERC20 is incorrectly calculated and used #247

Closed
c4-submissions opened this issue Sep 13, 2023 · 3 comments
Closed

DOMAIN_SEPARATOR of ERC20 is incorrectly calculated and used #247

c4-submissions opened this issue Sep 13, 2023 · 3 comments
Labels
2 (Med Risk) Assets not at direct risk, but function/availability of the protocol could be impacted or leak value bug Something isn't working duplicate-146 satisfactory satisfies C4 submission criteria; eligible for awards sufficient quality report This report is of sufficient quality

Comments

@c4-submissions
Copy link
Contributor

Lines of code

https://github.com/code-423n4/2023-09-centrifuge/blob/main/src/token/ERC20.sol#L48
https://github.com/code-423n4/2023-09-centrifuge/blob/main/src/token/ERC20.sol#L71

Vulnerability details

DOMAIN_SEPARATOR of ERC20 is incorrectly calculated and used

Impact

permit() of ERC20 doesn't work as intented, implementation of EIP-1271 _isValidSignature() will use incorrect digest

Description

_DOMAIN_SEPARATOR of ERC20 is incorrectly calculated. _DOMAIN_SEPARATOR is used as DOMAIN_SEPARATOR in permit() and passed in the _isValidSignature() function.

Since block.chainId will always equal deploymentChainId as we see in the constructor: this means in permit() always the incorrectly calculated _DOMAIN_SEPARATOR will be used since the expression block.chainid == deploymentChainId ? _DOMAIN_SEPARATOR is always true.

src/token/ERC.20.sol - constructor

	constructor(uint8 decimals) {
		...
		deploymentChainId = block.chainId
		_DOMAIN_SERATOR = _calculateDomainSeparator(block.chainid)
	}

src/token/ERC20.sol - _calculateDomainSeparator()

    function _calculateDomainSeparator(uint256 chainId) private view returns (bytes32) {
        return keccak256(
            abi.encode(
                keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)"),
                keccak256(bytes(name)),
                keccak256(bytes(version)),
                chainId,
                address(this)
            )
        );
    }

The problem is that the _calculateDomainSeparator() will use the empty name when it is not yet set in the constructor, only later via file(). Even after the name was set, the incorrectly calculated _DOMAIN_SEPARATOR (set in constructor) remains to be used.

Tools Used

Manual review

Recommended Mitigation Steps

Set name in the constructor before calculating _DOMAIN_SEPARATOR via _calculateDomainSeparator(). Consider setting symbol in the constructor as well for convenience.

Assessed type

Timing

@c4-submissions c4-submissions added 2 (Med Risk) Assets not at direct risk, but function/availability of the protocol could be impacted or leak value bug Something isn't working labels Sep 13, 2023
c4-submissions added a commit that referenced this issue Sep 13, 2023
@c4-pre-sort
Copy link

raymondfam marked the issue as sufficient quality report

@c4-pre-sort c4-pre-sort added the sufficient quality report This report is of sufficient quality label Sep 15, 2023
@c4-pre-sort
Copy link

raymondfam marked the issue as duplicate of #146

@c4-judge
Copy link

gzeon-c4 marked the issue as satisfactory

@c4-judge c4-judge added the satisfactory satisfies C4 submission criteria; eligible for awards label Sep 26, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
2 (Med Risk) Assets not at direct risk, but function/availability of the protocol could be impacted or leak value bug Something isn't working duplicate-146 satisfactory satisfies C4 submission criteria; eligible for awards sufficient quality report This report is of sufficient quality
Projects
None yet
Development

No branches or pull requests

3 participants