Incident,
The Hedgey Finance-related contract was drained of approximately 2 million USD.
Source: De.Fi incident database.
- Audits before it
- 1.
- Audits since
- 2, the latest dated 12 Nov 2024.
As of 29 Oct 2026, Hedgey has 3 audit reports by 2 security firms on Trustblock; the latest is by Resonance Security, dated 12 Nov 2024. Those reports list no open critical findings. It also holds 1 incident (latest 18 Apr 2024).
Record last updated . It holds audits and findings, contracts and incidents up to Oct 2026. Trustblock does not review code.
Newest first
| Audit | Security firm | Date | Scope | Critical findings | Report |
|---|---|---|---|---|---|
| Hedgey Finance | Security firm: Resonance Security | Date: | Scope: 94 addresses on 13 chains | No open critical findings | Open · IPFS |
| Hedgey Finance | Security firm: Resonance Security | Date: | Scope: 94 addresses on 13 chains | No open critical findings | Open · IPFS |
| Hedgey Token Lockup and Vesting Plans | Security firm: Consensys | Date: | Scope: Files named in the report | No open critical findings | Open · diligence.security |
Statuses are the security firm’s own, from each report.
| Severity | Open | Acknowledged | Fixed |
|---|---|---|---|
| Critical | 0 | 0 | 0 |
| High | 0 | 0 | 0 |
| Medium | 5 | 0 | 1 |
| Low | 16 | 0 | 9 |
The function claimMultipleWithSig() is used by paymasters to claim tokens from multiple campaigns on behalf of a claimer. It uses a signature verification mechanism to control the access to this function and the ability to claim the claimer's tokens.The signature provided as an input parameter to this function includes several variables necessary to prevent signature attacks, e.g. signature replay, however, it does not do so effectively. When attempting to claim from multiple campaigns, the paymaster needs to provide a signature that, along with other variables, will verify the id and amount of tokens of the first campaign as well as the number of campaigns to claim. Solely relying on these variables opens up the possibility for the paymaster to claim unintended campaigns.As an example of a proof of concept:Claimer can claim from 4 campaigns;Claimer provides a proper signature to the paymaster to claim on his behalf for only 3 of the campaigns, specifically campaigns 1, 2, and 3.Paymaster uses the same signature to claim from campaigns 1, 2, and 4.The scenario identified previously is possible due to the fact that the first campaign matches what the claimer intended, and the number of claimed campaigns also matches. However, it does not match the intended campaigns that were meant to be claimed on behalf of the claimer.
Open the reportThe protocol adds a fee in native ETH to users through the frontend. However, it is possible to prevent the fee payment by using the smart contract directly without using the web application.
Open the reportThe function claimMultipleWithSig() is used by paymasters to claim tokens from multiple campaigns on behalf of a claimer. It uses a signature verification mechanism to control the access to this function and the ability to claim the claimer's tokens.The signature provided as an input parameter to this function includes several variables necessary to prevent signature attacks, e.g. signature replay, however, it does not do so effectively. When attempting to claim from multiple campaigns, the paymaster needs to provide a signature that, along with other variables, will verify the id and amount of tokens of the first campaign as well as the number of campaigns to claim. Solely relying on these variables opens up the possibility for the paymaster to claim unintended campaigns.As an example of a proof of concept:Claimer can claim from 4 campaigns;Claimer provides a proper signature to the paymaster to claim on his behalf for only 3 of the campaigns, specifically campaigns 1, 2, and 3.Paymaster uses the same signature to claim from campaigns 1, 2, and 4.The scenario identified previously is possible due to the fact that the first campaign matches what the claimer intended, and the number of claimed campaigns also matches. However, it does not match the intended campaigns that were meant to be claimed on behalf of the claimer.
Open the reportThe createPlan functions in contracts/VestingPlans/TokenVestingPlans.sol and contracts/VestingPlans/VotingTokenVestingPlans.sol do not validate vestingAdmin arguments, so callers can accidentally set important state variables to the zero address.This fact allows for plans to be created without the capability of being revoked.
Open the reportThe report gives no description here.
Open the reportWhen it is not possible for counters to overflow, as is the case when used in for and while-loops, they should be unchecked. The unchecked keyword is new in solidity version 0.8.0, so this only applies to that version or higher, which these instances are. This saves 30-40 gas per loop.
Open the reportThe critical procedures used to change treasury or whitelist or blacklist tokens in this protocol should use a two step process in order to ensure the modification is indeed intended.
Open the reportThe smart contract allows users to provide ETH as fee, but does not refund the amount in excess of what is required, sending incorrect amounts to treasury.
Open the reportUnlike the basic Transfer function, SafeTransfer incorporates safeguards against potential smart contract vulnerabilities, such as reentrancy attacks and unexpected token loss.
Open the reportThe function transferFrom() is used by a vestingAdmin of a plan to transfer an NFT on behalf of its holder. The success of the execution of this function is determined by the toggle variable adminTransferOBO than can only be set by the holder of the NFT. As such, a vestingAdmin is hindered from acting rogue and transferring NFTs at will.However, a malicious or a compromised vestingAdmin that already has the transfer capability enabled may still transfer the plan to an arbitrary address, e.g. an address controlled by the malicious vestingAdmin.
Open the reportThe functions createUnlockedCampaign() and createLockedCampaign() do not perform the necessary validations on the variable donation.tokenLocker to ensure that a malicious address cannot be provided as input. The address pointed by this variable can be arbitrarily chosen by a malicious actor, and its allowance of the campaign token will be increased illegitimately.As an example of a proof of concept:Malicious actor creates contract to interact and exploit the ClaimCampaigns smart contract.Malicious actor creates a campaign providing donation tokens to be collected by the donationCollector. The variable donation.tokenLocker is set to the malicious contract created previously.The event TokensDonated() is emitted with a legitimate donationCollector.Since the malicious actor's allowance was increased by donation.amount, they can withdraw the donation back to themselves.Since the malicious actor also set themselves as the campaign.manager, they can cancel the campaign and reclaim the campaign.amount.The scenario identified above can be used to illegitimately force the emission of the TokensDonated() event that can be wrongfully ingested by other on-chain or off-chain components.
Open the reportThe function changeDonationcollector() and the constructor() do not validate the variables donationCollector and _tokenLockers against the Zero Address, allowing for undefined behavior within the protocol, and drainage of donation tokens.
Open the reportThe functions planBalanceOf() and planEnd() do not validate the variable planId against the Zero Value, allowing for incorrect information to be presented by the protocol. Even though a planId of 0 would most likely be invalid, the protocol can still confirm it exists even when it does not. Also it allows for divisions by 0 to occur.
Open the reportIt was observed that throughout the protocol there are multiple instances of redundant code on several accounts:Duplicated functions, e.g planBalanceOf() and planEnd();Similar functions with slight differences do not reuse code, e.g. createUnlockedCampaign() and createLockedCampaign();Similar contracts with slight differences do not use inheritance, e.g. TokenLockupPlans, VotingTokenLockupPlans, TokenVestingPlans and VotingTokenVestingPlans;These design patterns increase code complexity and do not maximize transaction gas and storage efficiency on the blockchain.
Open the reportThe function batchLockingPlans() performs the same Zero Address validation on the variable token already provided by other functions such as transferTokens(), safeIncreaseAllowance(), and createPlan().
Open the reportThe function _claimUnlockedTokens() performs the same validation twice on the same variable campaign.tokenLockup as the functions who call it. The first time always occurs within if conditions, and the second time occurs on _claimUnlockedTokens().
Open the reportThe function validateEnd() defines an output bool variable valid that identifies whether the execution of this function was successful. The usage of this variable is unnecessary since it is always set to true or the entire transaction reverts through the require statements.
Open the reportThe report gives no description here.
Open the reportThe report gives no description here.
Open the reportThe report gives no description here.
Open the reportThe report gives no description here.
Open the reportAttached through a shared contract address. Our incident data ends in Oct 2026.
The Hedgey Finance-related contract was drained of approximately 2 million USD.
Source: De.Fi incident database.
The reports name a repository or files. Open a report to see its scope.
Is this your project? Show this record on your own website. The label states what the record holds, links to this page and updates by itself. It is free and needs no sign-in.
Automatic: the three strongest facts of this project’s own record (its last audit and two more), highlighted. They update with the record. Picking a fact turns Automatic off.
<head><script src="https://widget.trustblock.run/project-widget.min.js" defer></script></head><body><divdata-tb-project-widgetdata-tb-project-slug="hedgey-finance"></div></body>
Paste the code where the label should appear. It uses no API credit and updates by itself.
Something wrong on this page? A missing report, a wrong date, a finding that was fixed since. Tell us and we check it against its source.
Tell us