QUADRIGA INITIATIVE
CRYPTO WATCHDOG & FRAUD RECOVERY PLATFORM
A COMMUNITY-BASED, NOT-FOR-PROFIT
$1 000 000 USD
JULY 2024
GLOBAL
DELTAPRIME
DESCRIPTION OF EVENTS

"Unlock the full potential of your capital with the Prime Account: an empowered, escrow smart contract, just for you."
"Traditional lending systems like banks rely on trust and credit checks to ensure loan repayment. When that trust is broken, everyone feels it." "Trustless lending platforms like Aave / Radiant rely on locking high amounts of collateral to ensure loan repayment. This locked liquidity is trapped, harming the chain the platform is in."
"Prime Brokerage solutions (read: DeltaPrime) rely on keeping access to borrowed funds to ensure loan repayment. While a borrower can use and profit from their collateral and borrowed funds to use in other DeFi platforms, funds are always accessible by an automated escrow smart contract. This ensures trustless loan repayment, without the need for credit checks."
"On the 23rd of July an attacker had gained access to $1.000.000 from 13 different Prime Accounts. This access was gained through a misconfiguration issue, allowing the attacker to illegitimately move ownership of the Prime Accounts to his own address and, in turn, repay their loans to withdraw their collateral."
"DeltaPrime uses a DiamondBeaconProxy (DBP) pattern that allows it to perform upgrades of all Prime Accounts simultaneously as well as keeps the PrimeAccount deployment costs lightweight.
DBP — as a flavor of EVM proxy patterns — uses an architecture in which contracts that can be roughly divided into 2 types: - PrimeAccounts serve as storage contracts — they store all the state (smart contract’s storage) as well as hold the ownership over all assets/positions within the account.
- Implementation contracts (facets) — they hold the implementation code of the methods that can be used within the PrimeAccount.
Upon calling various methods on a PrimeAccount storage, it uses EVM .delegatecall() (as opposed to a standard .call()) which allows for executing implementations contracts’ methods in the storage context of a PrimeAccount (instead of the implementation contract).
For the PrimeAccount to know what is the address of implementation for a specific method, it interacts with the centerpiece of the architecture which is the DiamondBeacon contract. DiamondBeacon is a singleton contract that maps supported methods selectors (4 bytes identifier unique to each method) to their respective implementation contracts addresses.
In all of the EVM proxy patterns, an important consideration is to ensure that various implementation contracts (or even new versions of the same contracts in cases where there’s only 1 implementation contract) use mechanisms to avoid storage layout collision which would result in overwriting already existing storage variables which could lead to unforeseen results.
One of the methods of avoiding such storage collision, is to use custom storage slots as opposed to the EVM default storage layout. Contract’s storage is divided into ²²⁵⁶ slots — 32 bytes each.
It is possible to calculate a keccak256 hash out of an arbitrary (but unique) string and use the result as a pointer to a specific slot in the storage. This approach guarantees with enough probability that each of the structs stored at a unique slot generated with the keccak256 function will not overlap with other slots that are already in use.
As part of the design, contracts can use multiple custom storage slots in order to divide them into more coherent parts that serve a specific purpose. Out of many storage slots used within the protocol, 2 of them are crucial to understanding the flow of the recent exploit.
1st slot (0x8d5bb42e0ac1496a2c326edc9c00758985246e6c2bb146d6c2f4a0d509e0960a) serves as storage slot for PrimeAccounts general state which includes the address owner variable as well as the bool _initialized variable. Owner specifies which address is the owner of the contract and _initialized makes sure that the contract can only be initialized once.
2nd slot (0xc8fcad8db84d3cc18b4c41d551ea0ee66dd599cde068d998e57d5e09332c131c) serves as the storage slot for DiamondBeacon-specific variables including bytes4 selector -> address mappings as well as the bool _initialized variable.
As per design, proxy contracts upon deployment are often initialized with starting values which includes setting the contract owner.
In case of DiamondBeacon the method for initialization was init() -> (bytes4 selector 0xe1c7392a) and for PrimeAccounts that’s initialize() -> (bytes4 selector 0xc4d66de8).
The DiamondBeacon init()` method serves the first initialization of the Diamond at the moment of deploying the protocol and should be removed after the deployment is finalized and initial configuration is finished (which has not been performed). Since a Prime Account does not have the implementation of this method, it asked DiamondBeacon for the logic. The DiamondBeacon provided the logic of `init()` to the Prime Account (which was an unintended scenario by developers)."
"What allowed for the breach, was the fact that although both implementations checked for the _initialized flag, they did so using two different storage slots."
"After exploiting this route, the attacker could perform Prime Account specific methods on the hijacked account. At all times, he was restricted by the other Prime Account safeguards (like solvency checks or withdrawal guard), so he had to unwind positions and repay the borrowed amounts to the pools, before he could proceed with withdrawing (draining the collateral)."
$1m
"Within 48 hours the attack was detected, the code re-audited, the bugs fixed, and all affected users made whole with $900.000 returned by the attacker + $100.000 used from the DeltaPrime stability pool."
"We understand that you are responsible for this mornings attack on DeltaPrime. Please reach out on Blockscan chat as we would like to discuss next steps."
"We, DeltaPrime, agree that, should 261.27 ETH (90% of the funds withdrawn) be returned in reasonable time and good faith to our Gnosis Safe (0x321FcB7B7ECa3EdD75603A5de451c577E137C7F9), we will view this incident as whitehat, with the remaining assets being considered a bug bounty fee, free at your disposal. This comes with the assurance of no pursuit or legal action from our side against you. We guarantee complete anonymity and a cessation of any investigative activities aimed at asset recovery"
"Shortly after this vector of attack was confirmed, DeltaPrime’s team deployed a transaction to the timelock to remove the `init` method from the DiamondBeacon to disable this unauthorized route and together with auditors checked for similar scenarios in the protocol."
$900k
DeltaPrime is a decentralized lending platform which aims to be more capital efficient, but still fully collateralized. An unfortunate vulnerability allowed account ownership to be transfered, which was used against 13 accounts to repay loans and withdraw collateral, netting the attacker $1m USD worth of funds. After negotiation, the attacker returned $900k USD, and it was agreed that the remaining $100k USD would be retained as a whitehat bounty. The DeltaPrime project has pointed out that they already offered such bounties and would have been happy to pay out for such an exploit if reported responsibly. They warn that they would be unlikely to pay out bounties if the protocol is attacked maliciously in the future.
SlowMist Hacked - SlowMist Zone (Aug 20)
DeltaPrime Post-Mortem Report. On July 23nd, Prime Accounts were… | by DeltaPrime | Jul, 2024 | Medium (Aug 20)
Arbitrum One Transaction Hash (Txhash) Details | Arbitrum One
(Aug 20)
Arbitrum One Transactions Information | Arbitrum One
(Aug 20)
Arbitrum One Transaction Hash (Txhash) Details | Arbitrum One
(Aug 20)
Arbitrum One Transaction Hash (Txhash) Details | Arbitrum One
(Aug 20)
Blockscan Chat - Wallet to Wallet Messaging for Web3
(Aug 20)
Arbitrum One Transaction Hash (Txhash) Details | Arbitrum One
(Aug 20)
DeltaPrime (Aug 20)
Unlock the Blockchain | DeltaPrime (Aug 20)
