Block: 111
Timestamp: 12:47:54
AuditProfile
Security blog
Ethereum Validator Lifecycle: A Deep Dive
Ethereum today implements the most decentralized proof-of-stake consensus. The current number of active validator keys exceeds 10^6, and each block is attested by hundreds of validators. The Eth 2.0 validating infrastructure is complex, split into beacon and execution layers, and includes many interesting mechanics. This intricate system is continuously upgraded "on-the-fly," which adds significant complexity. With that in mind, we decided to fill the gap between the higher-level documentation about Ethereum's consensus, economic security, and validation, and the actual code running in real production. The goal of this article is to give readers a comprehensive understanding of how an Ethereum validator works and provide links to the real code for those who want to dive deeper.
Continue readingBlock: 110
Timestamp: 01:46:23
AuditProfile
Security blog
Random Solidity tip
Implement this `batch` function in your contract so that your users can compose function calls. e.g. calling a deposit method multiple times
Continue readingBlock: 109
Timestamp: 12:47:36
AuditProfile
Security blog
How Liquidations Work in DeFi: A Deep Dive
Liquidation mechanisms are vital to the stability and solvency of decentralized finance (DeFi) protocols, especially in volatile market conditions. However, their complexity and sensitivity to various challenges—such as liquidity constraints, cascading liquidations, and cross-chain interactions—make them a critical area of focus for developers and auditors alike.
Continue readingBlock: 108
Timestamp: 11:39:12
AuditProfile
Security blog
Hong Kong tokenized court notices sent to USDT wallets
In Hong Kong, courts have been granted the right to issue tokenized court notices and send them to wallets with USDT, whose anonymous owners have been identified in illegal activities.
Continue readingBlock: 107
Timestamp: 12:38:39
AuditProfile
Security blog
Web3.js to sunset: ChainSafe transitioning developers
Web3.js libraries will be archived on March 4th, 2025. ChainSafe will provide migration support and documentation for affected users in the coming days.
Continue readingBlock: 106
Timestamp: 12:35:44
AuditProfile
Security blog
2024 Exploits Recap: Top 10 Most Exploited DeFi Vulnerabilities and How to Prevent Them
Stolen keys, hacked oracles, and millions lost! 2024's DeFi exploits revealed shocking vulnerabilities. Why did these attacks work, and what can be done to prevent them?
Continue readingBlock: 105
Timestamp: 12:47:55
AuditProfile
Security blog
PUMP.FUN Protocol Insights: From Bonding Curve Calculation to Profit Strategy Construction
Bitcoin has laid the foundation for the value of cryptocurrency because it cannot be issued in large quantities. Ethereum has triggered an ICO craze through smart contracts, and Inscription and Memecoin have attracted massive amounts of funds due to fair distribution. The replacement of new technologies has continuously expanded the audience of crypto applications; and the differences in the issuance mechanisms of emerging tokens further reflect the changes in the audiences investment value concepts.
Continue readingBlock: 104
Timestamp: 12:03:16
AuditProfile
Security blog
Adversary can block claimAuction() due to push-strategy to transfer assets to multiple bidders
claimAuction() implements a push-strategy instead of a pull-strategy for returning the bidders funds. This gives the opportunity for an adversary to DOS the function, locking all funds from other participants.
function claimAuction(uint256 _tokenid) public WinnerOrAdminRequired(_tokenid,this.claimAuction.selector){
require(block.timestamp >= minter.getAuctionEndTime(_tokenid) && auctionClaim[_tokenid] == false && minter.getAuctionStatus(_tokenid) == true);
auctionClaim[_tokenid] = true;
uint256 highestBid = returnHighestBid(_tokenid);
address ownerOfToken = IERC721(gencore).ownerOf(_tokenid);
address highestBidder = returnHighestBidder(_tokenid);
for (uint256 i=0; i< auctionInfoData[_tokenid].length; i ++) {
if (auctionInfoData[_tokenid][i].bidder == highestBidder && auctionInfoData[_tokenid][i].bid == highestBid && auctionInfoData[_tokenid][i].status == true) {
IERC721(gencore).safeTransferFrom(ownerOfToken, highestBidder, _tokenid);
(bool success, ) = payable(owner()).call{value: highestBid}("");
emit ClaimAuction(owner(), _tokenid, success, highestBid);
} else if (auctionInfoData[_tokenid][i].status == true) {
(bool success, ) = payable(auctionInfoData[_tokenid][i].bidder).call{value: auctionInfoData[_tokenid][i].bid}("");
emit Refund(auctionInfoData[_tokenid][i].bidder, _tokenid, success, highestBid);
} else {}
}
}
Continue reading
Block: 103
Timestamp: 12:38:44
AuditProfile
Security blog
Attacker can reenter to mint all the collection supply
Here is a very popular NFT problem that was found in the Nextgen protocol over a year ago. Where do you think this bug is hiding?
function mint(uint256 mintIndex, address _mintingAddress , address _mintTo, string memory _tokenData, uint256 _saltfun_o, uint256 _collectionID, uint256 phase)
external {
require(msg.sender == minterContract, "Caller is not the Minter Contract");
collectionAdditionalData[_collectionID].collectionCirculationSupply = collectionAdditionalData[_collectionID].collectionCirculationSupply + 1;
if (collectionAdditionalData[_collectionID].collectionTotalSupply >= collectionAdditionalData[_collectionID].collectionCirculationSupply) {
_mintProcessing(mintIndex, _mintTo, _tokenData, _collectionID, _saltfun_o);
if (phase == 1) {
tokensMintedAllowlistAddress[_collectionID][_mintingAddress] = tokensMintedAllowlistAddress[_collectionID][_mintingAddress] + 1;
} else {
tokensMintedPerAddress[_collectionID][_mintingAddress] = tokensMintedPerAddress[_collectionID][_mintingAddress] + 1;
}
}
}
Continue reading
Block: 102
Timestamp: 01:36:40
AuditProfile
Security blog
Haystack Editor for your next audit
Today I want to tell you about a great code editor that is perfect for auditing - Haystack Editor. An IDE built on top of a canvas, Haystack takes care of the tedious and confusing parts of coding for you.
Continue readingBlock: 101
Timestamp: 01:15:08
AuditProfile
Security blog
How I'm re-learning how to audit. Working with notes. Sablier contest
It's very hard to take part in competitive auditing when you only have 8-10 hours a week to spend studying code and looking for vulnerabilities. Full-time auditors will laugh at this amount of time, and they will be right. It's unlikely that you'll be able to study the project well in that time, let alone find any significant bugs.
Continue readingBlock: 100
Timestamp: 12:45:31
AuditProfile
Security blog
A small story about my auditing journey
A really great story from the amazing CharlesWang about his journey into auditing. It would be so useful for anyone just starting out on his journey! Read it here:
Continue readingBlock: 99
Timestamp: 02:53:43
AuditProfile
Security blog
Understanding Merkle-Patricia Trees
In the realm of blockchain technology, an advanced data structure known as the Merkle-Patricia Tree forms a pivotal part of the infrastructure. This structure combines the properties of Merkle Trees and Patricia Tries, culminating in a highly efficient and secure model for data representation and verification. Although they are primarily associated with Ethereum, their usefulness extends far beyond just this single blockchain. Read the full article here:
Continue readingBlock: 95
Timestamp: 02:34:56
AuditProfile
Security blog
One of the VS Code extensions could be malicious
You should be careful when using any code extension and always check it's build date and reviews! One of them could be dangerous to use:
Continue readingBlock: 94
Timestamp: 12:42:49
AuditProfile
Security blog
Watch out for copy-paste code
Sometimes developers copy and paste parts of code to reduce development time and speed up the process. Such actions can cause you serious problems in the future if your code is not reviewed by professionals. Take a look at the next snippet:
function decodeWellData(bytes memory data) public view virtual returns (uint256[] memory decimals) {
(uint256 decimal0, uint256 decimal1) = abi.decode(data, (uint256, uint256));
// if well data returns 0, assume 18 decimals.
if (decimal0 == 0) {
decimal0 = 18;
}
if (decimal0 == 0) { //@audit
decimal1 = 18;
}
if (decimal0 > 18 || decimal1 > 18) revert InvalidTokenDecimals();
decimals = new uint256[](2);
decimals[0] = decimal0;
decimals[1] = decimal1;
}
Continue reading