Organization
@centrifugeEngagement Type
Cantina Reviews
Period
-
Repositories
N/A
Researchers
Findings
Medium Risk
1 findings
1 fixed
0 acknowledged
Low Risk
2 findings
2 fixed
0 acknowledged
Informational
5 findings
3 fixed
2 acknowledged
Gas Optimizations
2 findings
2 fixed
0 acknowledged
Medium Risk1 finding
Function CFG::burn() doesn't call _moveDelegateVotes()
Severity
- Severity: Medium
≈
Likelihood: High×
Impact: Low Submitted by
Gerard Persoon
Description
Function
CFG::burn()
doesn't call_moveDelegateVotes()
unlike the similar functions likeDelegationToken::burn()
.This could leave token delegations, while the underlying tokens are burnt and could lead to incorrect results in voting.
This function will mostly be used by tokens bridges to the impact seems low.
Recommendation
Consider adding a call to
_moveDelegateVotes()
.
Low Risk2 findings
Invalid signatures not detected in delegateWithSig()
Severity
- Severity: Low
Submitted by
Gerard Persoon
Description
Invalid signatures not detected in
delegateWithSig()
. In that situationdelegator
will beaddress(0)
.The risk is limited because
address(0)
won't contain tokens.However, the following unwanted effects are present:
- setting a delegate for
address(0)
, that normally shouldn't have a delegate - emitting
DelegateeChanged
foraddress(0)
Also future changes/bugs could potentially allow tokens to exist on
address(0)
.Recommendation
Consider reverting when
delegator == address(0)
.Alternatively use a variation of
isValidSignature()
, which is also used used inERC20:Permit()
and already contains this check.msg.sender of CFG.sol might hold unwanted authorizations
Severity
- Severity: Low
Submitted by
Gerard Persoon
Description
The
msg.sender
ofCFG.sol
is authorized via auth to be able to dofile()
. Thenward
is also authorized.Assuming
ward
is not equal tomsg.sender
,msg.sender
stays authorized and can still tomint()
.Recommendation
Make sure only one address is authorized after the contract is deployed. This can be done in several ways:
- add something like:
if (ward != msg.sender) deny(msg.sender);
in the constructor ofCFG.sol
; - change the code so only
ward
is authorized; - uncomment the
deny
statement in the deployment script.
Informational5 findings
transfer() and transferFrom() don't check result of their super functions
State
- Acknowledged
Severity
- Severity: Informational
Submitted by
Gerard Persoon
Description
The functions
transfer()
andtransferFrom()
don't explicitly check the result of theirsuper
functions.The risk is limited because the underlying implementation is known and allways returns
true
. However it is safer not to rely on this implicit information.Recommendation
Consider check the return values of the
super
functions, or at least add a comment.URL in comment has a newer version
Severity
- Severity: Informational
Submitted by
Gerard Persoon
Description
The URL
https://github.com/morpho-org/morpho-token-upgradeable
resolves tohttps://github.com/morpho-org/morpho-token
. So the resulting url could also be references inDelegationToken.sol
.Recommendation
Consider changing the comment in the following way:
-/// @author Modified from https://github.com/morpho-org/morpho-token-upgradeable+/// @author Modified from https://github.com/morpho-org/morpho-tokenThe repository protocol-v3 might not be accessible
State
- Fixed
PR #1
Severity
- Severity: Informational
Submitted by
Gerard Persoon
Description
The repository
protocol-v3
might not be accessible by everyone, which makes reviewing the code more difficult.Recommendation
Consider adding the underlying code to the
cfg-token
repository.delegateWithSig() doesn't support signatures from smart contract accounts
State
- Acknowledged
Severity
- Severity: Informational
Submitted by
Gerard Persoon
Description
ERC20::permit()
usesSignatureLib.isValidSignature()
, which also allow smart contract accounts to sign.However
delegateWithSig()
doesn't support this. The result is that smart contract accounts can't used. This is increasingly relevant withERC 4337/EIP 7702
.Recommendation
Consider using a variation of
SignatureLib.isValidSignature()
to also allow smart contract accounts.Note:
SignatureLib.isValidSignature()
currently requiressigner
as an input parameter, which isn't passed todelegateWithSig()
.no interface file for CFG.sol exists
Severity
- Severity: Informational
Submitted by
Gerard Persoon
Description
There is no interface file for
CFG.sol
. This makes using the token more complicated.Recommendation
Consider creating an interface file
ICFG.sol
. Also inherit from it to make sure the interface is correct.
Gas Optimizations2 findings
Use of balanceOf() in burn() not optimal
Severity
- Severity: Gas optimization
Submitted by
Gerard Persoon
Description
Function
burn()
uses bothbalanceOf()
and_balanceOf()
. The second call could be replaced withbalance
, which cantains the value of the first version.Recommendation
Consider changing the code to:
function burn(uint256 value) external {uint256 balance = balanceOf(msg.sender);require(balance >= value, InsufficientBalance());...- _setBalance(msg.sender, _balanceOf(msg.sender) - value);+ _setBalance(msg.sender, balance - value);...}Note: these changes can also be done in
ERC20.sol
for functionstransfer()
,_transferFrom()
andburn()
.Optimization possible for calculation of totalSupply
Severity
- Severity: Gas optimization
Submitted by
Gerard Persoon