Clumsy Pink Otter
Medium
When user submits Intent, he specifies the account
which will be the counterparty of the trade:
function update(address account, Intent calldata intent, bytes memory signature) external nonReentrant whenNotPaused {
if (intent.fee.gt(UFixed6Lib.ONE)) revert MarketInvalidIntentFeeError();
verifier.verifyIntent(intent, signature);
_updateIntent(
account,
msg.sender,
intent.amount.mul(Fixed6Lib.NEG_ONE),
intent.price,
address(0),
address(0),
UFixed6Lib.ZERO,
UFixed6Lib.ZERO,
false
); // account
...
The issue is that msg.sender
must be the operator
of the account
, because he doesn't sign anything in this function. However, his address is used as signer in _updateIntent
(which loads update context, filling in signer from the factory, and then later checking the signer flag in InvariantLib.validate
), thus it's enough for msg.sender
to be either signer
or operator
. If msg.sender
is only signer
, he should have no access to this function, but he can execute it and it's enough to be signer
while not submitting any signature.
The same issue happens with the following market.update
:
function update(address account, Fixed6 amount, address referrer) external nonReentrant whenNotPaused {
_updateMarket(account, msg.sender, Fixed6Lib.ZERO, amount, Fixed6Lib.ZERO, referrer);
}
It's enough for msg.sender
to be signer of account to execute the action, although he doesn't provide any signature, so it must be operator-only.
msg.sender
is used as signer argument to _updateIntent
:
https://github.com/sherlock-audit/2025-01-perennial-v2-4-update/blob/main/perennial-v2/packages/core/contracts/Market.sol#L154
And the same issue here: https://github.com/sherlock-audit/2025-01-perennial-v2-4-update/blob/main/perennial-v2/packages/core/contracts/Market.sol#L223-L225
- User is set as a signer of account, but not as operator
None.
- User who only has signer access to account is able to execute
market.update
on behalf of account which is supposed to be only used by the operator.
Security access violation: user with incorrect role is able to access function which should be accessed only by the other role.
Use address(0)
in _updateIntent
for account
signer, and in _updateMarket
which is not connected with the signature.