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

Function setFee can be called after fillOrder #211

Closed
code423n4 opened this issue Jul 4, 2022 · 1 comment
Closed

Function setFee can be called after fillOrder #211

code423n4 opened this issue Jul 4, 2022 · 1 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 This issue or pull request already exists

Comments

@code423n4
Copy link
Contributor

Lines of code

https://github.com/code-423n4/2022-06-putty/blob/3b6b844bc39e897bd0bbb69897f2deff12dc3893/contracts/src/PuttyV2.sol#L268
https://github.com/code-423n4/2022-06-putty/blob/3b6b844bc39e897bd0bbb69897f2deff12dc3893/contracts/src/PuttyV2.sol#L240

Vulnerability details

Impact

Function setFee can be called at any time, including after fillOrder has been called. This could be deemed unfair to the user in the Short Position, since they created the order at a particular point in time.

The impact is that they may end up paying more fees than they expected when they call withdraw.

Proof of Concept

  • User creates order and fee is currently 5 (i.e. 0.5%).
  • Function fillOrder is called on the order.
  • Owner calls setFee increasing it to 30 (i.e. 3%)
  • User in short position calls withdraw (either when Call and Exercised, or when Put and not Exercised). They end up paying 3% in fees instead of 0.5%.

Recommended Mitigation Steps

Add a new mapping variable that records the fee at the time fillOrder is called.

mapping (uint256 => uint256) public positionFees;

Then make the following edits to fillOrder and withdraw.

Edit for function fillOrder:

        Order memory order,
        bytes calldata signature,
        uint256[] memory floorAssetTokenIds
    ) public payable returns (uint256 positionId) {
...
positionExpirations[order.isLong ? uint256(orderHash) : positionId] = block.timestamp + order.duration;
// Saves fee at at time fillOrder called
positionFees[order.isLong ? positionId : uint256(orderHash)] = fee;
...

Edit for function withdraw:

function withdraw(Order memory order) public {
...
if ((order.isCall && isExercised) || (!order.isCall && !isExercised)) {
    // send the fee to the admin/DAO if fee is greater than 0%
    uint256 feeAmount = 0;
    uint256 positionFee = positionFees[uint256(orderHash)];
    if (positionFee > 0) {
        feeAmount = (order.strike * positionFee) / 1000;
        ERC20(order.baseAsset).safeTransfer(owner(), feeAmount);
    }

    ERC20(order.baseAsset).safeTransfer(msg.sender, order.strike - feeAmount);
    return;
}
...
@code423n4 code423n4 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 Jul 4, 2022
code423n4 added a commit that referenced this issue Jul 4, 2022
@outdoteth
Copy link
Collaborator

Duplicate: Admin can change fee at any time for existing orders: #422

@outdoteth outdoteth added the duplicate This issue or pull request already exists label Jul 6, 2022
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 This issue or pull request already exists
Projects
None yet
Development

No branches or pull requests

3 participants