sherlock-audit / 2024-02-perennial-v2-3-judging

6 stars 5 forks source link

panprog - MultiInvoker's stored TriggerOrders are not migrated to new format, potentially causing huge interface fees charged to users. #12

Closed sherlock-admin3 closed 4 months ago

sherlock-admin3 commented 5 months ago

panprog

high

MultiInvoker's stored TriggerOrders are not migrated to new format, potentially causing huge interface fees charged to users.

Summary

TriggerOrder struct which is used to store orders in MultiInvoker has changed in v2.3 compared to v2.2, however, there is no migration process for these orders mentioned in the Migration Guide, meaning there might be problems with existing v2.2 orders, in particular:

Vulnerability Detail

Previous version's TriggerOrder:

struct StoredTriggerOrder {
    /* slot 0 */
    uint8 side;                // 0 = maker, 1 = long, 2 = short, 3 = collateral
    int8 comparison;           // -2 = lt, -1 = lte, 0 = eq, 1 = gte, 2 = gt
    uint64 fee;                // <= 18.44tb
    int64 price;               // <= 9.22t
    int64 delta;               // <= 9.22t
    uint48 interfaceFeeAmount; // <= 281m

    /* slot 1 */
    address interfaceFeeReceiver;
    bool interfaceFeeUnwrap;
    bytes11 __unallocated0__;
}

New version's TriggerOrder:

struct StoredTriggerOrder {
    /* slot 0 */
    uint8 side;         // 0 = maker, 1 = long, 2 = short
    int8 comparison;    // -2 = lt, -1 = lte, 0 = eq, 1 = gte, 2 = gt
    uint64 fee;         // <= 18.44tb
    int64 price;        // <= 9.22t
    int64 delta;        // <= 9.22t
    bytes6 __unallocated0__; // @audit existing orders interfaceFeeAmount will be there

    /* slot 1 */
    address interfaceFeeReceiver1;
    uint48 interfaceFeeAmount1;      // <= 281m @audit existing orders unwrap flag here (in the high order byte), thus either 0 or 2^40 for existing orders
    bool interfaceFeeUnwrap1;   // @audit previously unallocated, thus false for all existing orders
    bytes5 __unallocated1__;

    /* slot 2 */
    address interfaceFeeReceiver2;
    uint48 interfaceFeeAmount2;      // <= 281m
    bool interfaceFeeUnwrap2;
    bytes5 __unallocated2__;
}

Notice the @audit remarks in the code. When existing v2.2 orders will be executed in v2.3 code, the overlapping fields in slot1 will cause incorrect values for these orders.

Impact

For existing orders with interface fee specified:

Code Snippet

Previous version of TriggerOrder: https://github.com/equilibria-xyz/perennial-v2/blob/7e60e69de9a613bfb449dc976801a000daa72aa4/packages/perennial-extensions/contracts/types/TriggerOrder.sol#L18-L31

New version of TriggerOrder: https://github.com/sherlock-audit/2024-02-perennial-v2-3/blob/main/perennial-v2/packages/perennial-extensions/contracts/types/TriggerOrder.sol#L19-L39

Tool used

Manual Review

Recommendation

Possible solutions:

arjun-io commented 4 months ago

This issue is actually invalid, the deployed storage and the v2.2 storage are the same, see the diff here: https://github.com/equilibria-xyz/perennial-v2/pull/263/files#diff-8f246f534b2e8eff82827f965b322065dcb8de7145a0950338032fcf24cd1fee

as well as the latest impl deployment here: https://arbiscan.io/address/0x31e1d5c8e8646cd581a4d930b3e5bfe12069c189#code

panprog commented 4 months ago

I've compared against the previously audited version which I've reviewed fixes for: https://github.com/equilibria-xyz/perennial-v2/pull/184

As this doesn't seem to be the correct code from which it's being migrated, then I believe this issue is invalid. But it's best to specify the exact version of the code which is being migrated in the future to avoid misunderstandings like this.

ydspa commented 4 months ago

Escalate

Have a check on this too, looks like the sponsor is correct

This issue is actually invalid, the deployed storage and the v2.2 storage are the same, see the diff here: https://github.com/equilibria-xyz/perennial-v2/pull/263/files#diff-8f246f534b2e8eff82827f965b322065dcb8de7145a0950338032fcf24cd1fee

as well as the latest impl deployment here: https://arbiscan.io/address/0x31e1d5c8e8646cd581a4d930b3e5bfe12069c189#code

sherlock-admin2 commented 4 months ago

Escalate

Have a check on this too, looks like the sponsor is correct

This issue is actually invalid, the deployed storage and the v2.2 storage are the same, see the diff here: https://github.com/equilibria-xyz/perennial-v2/pull/263/files#diff-8f246f534b2e8eff82827f965b322065dcb8de7145a0950338032fcf24cd1fee

as well as the latest impl deployment here: https://arbiscan.io/address/0x31e1d5c8e8646cd581a4d930b3e5bfe12069c189#code

You've created a valid escalation!

To remove the escalation from consideration: Delete your comment.

You may delete or edit your escalation comment anytime before the 48-hour escalation window closes. After that, the escalation becomes final.

nevillehuang commented 4 months ago

Unfortunately, this wasn’t caught during the competition, judging and preliminary judging phase by all parties, which should have been asked and clarified regarding the latest implementation deployed. So agree with the escalation to invalidate the issue.

@arjun-io I presume this also apply to base as well, given you linked to only a arbitrum address for the implementation contract.

Evert0x commented 4 months ago

Planning to accept escalation and invalidate issue. As no one had any context on the right reference contract. We should take the sponsors current opinion.

Evert0x commented 4 months ago

Result: Invalid Has Duplicates

sherlock-admin3 commented 4 months ago

Escalations have been resolved successfully!

Escalation status: