Platform: Code4rena
Start Date: 08/09/2023
Pot Size: $70,000 USDC
Total HM: 8
Participants: 84
Period: 6 days
Judge: gzeon
Total Solo HM: 2
Id: 285
League: ETH
Rank: 38/84
Findings: 1
Award: $132.86
🌟 Selected for report: 0
🚀 Solo Findings: 0
🌟 Selected for report: Kow
Also found by: 0xRobsol, 0xfuje, 0xkazim, 0xpiken, Aymen0909, T1MOH, bin2chen, codegpt, gumgumzum, josephdara, lsaudit, nmirchev8, ravikiranweb3, rvierdiiev
132.8565 USDC - $132.86
https://github.com/code-423n4/2023-09-centrifuge/blob/512e7a71ebd9ae76384f837204216f26380c9f91/src/token/ERC20.sol#L80 https://github.com/code-423n4/2023-09-centrifuge/blob/512e7a71ebd9ae76384f837204216f26380c9f91/src/token/ERC20.sol#L228
Unless ERC20@DOMAIN_SEPARATOR
is used or chainid
is updated, building the domain separator by reading values directly from the contract will lead to invalid signatures.
The _DOMAIN_SEPARATOR
is set in the constructor when the name
is still not set for Tranche
tokens.
Furthermore, Tranche
tokens name
can also be updated afterwards via an UpdateTrancheTokenMetadata
message.
function testDomainSeparator() public { assertEq(token.name(), ""); token.file("name", "DAI"); assertEq(token.name(), "DAI"); assertFalse(token.DOMAIN_SEPARATOR() == keccak256( abi.encode( keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)"), keccak256(bytes("")), keccak256(bytes(token.version())), block.chainid, address(token) ) )); assertEq(token.DOMAIN_SEPARATOR(), keccak256( abi.encode( keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)"), keccak256(bytes(token.name())), keccak256(bytes(token.version())), block.chainid, address(token) ) )); }
Manual Review
Recache the _DOMAIN_SEPARATOR
after a name
change
diff --git a/src/token/ERC20.sol b/src/token/ERC20.sol index 4fbba5e..0e97193 100644 --- a/src/token/ERC20.sol +++ b/src/token/ERC20.sol @@ -28,7 +28,7 @@ contract ERC20 is Context { // --- EIP712 niceties --- uint256 public immutable deploymentChainId; - bytes32 private immutable _DOMAIN_SEPARATOR; + bytes32 private _DOMAIN_SEPARATOR; bytes32 public constant PERMIT_TYPEHASH = keccak256("Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)"); @@ -81,7 +81,10 @@ contract ERC20 is Context { } function file(bytes32 what, string memory data) external auth { - if (what == "name") name = data; + if (what == "name") { + name = data; + _DOMAIN_SEPARATOR = _calculateDomainSeparator(deploymentChainId); + } else if (what == "symbol") symbol = data; else revert("ERC20/file-unrecognized-param"); emit File(what, data);
Other
#0 - c4-pre-sort
2023-09-15T04:10:32Z
raymondfam marked the issue as sufficient quality report
#1 - c4-pre-sort
2023-09-15T04:11:22Z
raymondfam marked the issue as duplicate of #146
#2 - c4-judge
2023-09-26T18:08:32Z
gzeon-c4 marked the issue as satisfactory