People often ask me "How did you learn how to hack?" The answer: by reading. This page is a collection of the blog posts and other articles that I have accumulated over the years of my journey. Enjoy!
deposit contract is used for sending the money to be a validator. This takes in three main parameters: BLS public key for validator, withdrawal credentials and signature of the data above. deposit for a NEW user, the user is created within an IF statement. However, if the user, which is defined by the public key is already in the system, the funds are simply added to that validator. array of tickets can be used. The flow of code verifies that the ticket has not been claimed yet and adds the reward for each ticket in a variable. Once the verification has been done, the reward is sent to the user. multiClaim() with the same winning ticket up to 255 times. I think there is a hard limit on the amount of elements for dynamic arrays in Solidity. SafeTransfer and BoringBatchable. The BoringBatchable library is added in order to easily introduce batch calls to any contract that imports it. This is done with a simple delegateCall flow. msg.value in the loop. This was the same bug in a different form.commitEth for an auction once. Then again. And over and over for all auctions, while only ever spending the 1ETH.refund on repeat. By sending ETH that went over the auctions hard cap, the contract would simply refund the ETH. By doing this over and over again via the batch call, all of the funds from the contract could be drained. startPayout, setPayout, doPayout, finishPayout. The administrator of the contract can initiate a payout for Asset at some index. Then, the four payout functions are called in order. The payout is marked as finished. rewardAmount and rewardDebt. The rewardAmount indicates the amount of money a user should be paid out. rewardDebt shows the amount taken out already. Since the pool had already finished, the rewardDebt for the asset is 0 (default value of Solidity). user.rewardAmount - user.rewardDebt is performed. But, user.rewardDebt starts with 0, giving the user more money than they are really entitled to. In particular, the unset variable of the user for a specific field is what is causing the problem here. balanceSnapshot and wantLockedInHere. wantLockedInHere is the balance of the contract not being put to work to generate yield on the assets. balanceSnapshot holds the balance of the contract.
wantLockedInHere it will send this. Otherwise, it will liquidate the yield-generating asset and decrease the value of balanceSnapshot. balanceSnapshot and wantLockedInHere will be subtracted from. Why does this happen when calling directly? There's an if statement that fails to actually NOT withdraw the money but update the state variables. earn to get the real value of the contract. Practically, this means that this attack can be performed multiple times. withdraw to claim all of the shares they have earned from the contract. They now have more money than what they started with.resolveReserve, the debt increases but the shares remains at 1. Because of the off by 1 error, the contract believes that NO money has been taken out! yUSD balance / totalSupply yUSDVault. for loop checks to ensure that no duplicate IDs are included to be unlocked. Interesting! Even code written in Rust can have security issues.