Access Control Vulnerabilities
Access control vulnerabilities in smart contracts were one of the primary factors leading to the Poly Network cross-chain bridge hack with losses of $611 million and contributed to a $300,000 hack of the ShadowFi DeFi project on Binance Smart Chain (BSC).
Alternatives to OpenZeppelin
While OpenZeppelin is a widely used and respected smart contract library, there are alternative libraries that offer improved gas efficiency. Two notable examples are Solmate and Solady. These libraries have been tested and recommended by developers for their focus on gas optimization.
Bad Randomness
Pseudo-Random Numbers
Balance Accounting
Smart contracts often maintain state variables that track balances. However, direct transfers not mediated by contract functions (like direct Ether sends to a contract address or transfer calls for ERC20 tokens that bypass the contract's logic) can create discrepancies between the actual balance held by the contract and the balance recorded in the contract’s internal state variables.
Better Increment
Incrementing operations are fundamental in contract development due to their frequent use in counting and looping mechanisms. Each method of incrementing has subtle nuances that may affect gas consumption and readability:
Bitmap & Bitwise operation
Storing data on the blockchain is extremely expensive. To decrease gas costs, innovative projects implement clever techniques. The method we're discussing today is often found in the source code of leading projects.
Bypass Contract Check
Many free-mint projects utilize the isContract() method to limit access to external accounts (EOAs) and restrict contract addresses. This method leverages extcodesize to determine the runtime bytecode length of an address. If it is greater than zero, the address is deemed a contract; otherwise, it is considered an EOA.
Bytes32 vs String
In Solidity, the type of data storage you choose can affect the gas cost of your contract operations, especially when storing or modifying state variables. The Ethereum Virtual Machine (EVM) charges gas for all operations, and the choice between using bytes32 and string types can impact these costs.
Clone vs New/Create2
In factory contracts, we often need to create several child contracts, and there are three common ways to do this:
Comparison Operators
In the Ethereum Virtual Machine (EVM), the selection of comparison operators influences the efficiency and gas consumption of smart contracts. Opting for ` (greater than) over ≤ (less than or equal to) and ≥ (greater than or equal to) is notably more gas-efficient. This is due to the absence of direct opcode instructions for ≤ and ≥` in the EVM's design, which requires additional operations to achieve these comparisons.
Constant vs Immutable
1. constant: Declares a constant that must be initialized at the time of declaration and cannot be altered thereafter.
Contratos Inteligentes
¿Qué es un Smart Contract?
Denial of Service Attacks
In April 2022, a popular NFT project called Akutar conducted a successful Dutch auction to raise funds, amassing 11,539.5 ETH. However, when processing refunds for previous community pass holders, a flaw in their smart contract prevented operations, locking all funds within the contract due to a DoS vulnerability.
Efficient Initialization
In Solidity, how you initialize state variables can have a impact on the deployment cost of your contracts, specifically in terms of gas usage. The Ethereum Virtual Machine (EVM) requires gas for every operation, including the initialization of variables.
Efficient Use of Storage Pointers
This tutorial explores how using storage pointers instead of copying data to memory can result in substantial gas savings. Storage pointers allow developers to directly reference storage without unnecessary copying of data, leading to more efficient smart contract execution.
ERC20 Transfer Issues
ERC20 transfer issues are a common source of vulnerabilities in smart contracts. These issues arise from inconsistent implementations of the ERC20 standard, particularly in how different tokens handle the return value of transfer functions.
ERC20Permit
In standard ERC20, users typically need to execute two separate transactions:
Error
In Solidity, developers can define errors in three main forms
Excessive Function Restrictions
Excessive function restrictions in smart contracts can lead to critical issues such as funds being locked, which can prevent rightful access even in necessary situations. A well-documented example is the Akutars NFT incident, where $34 million in Ethereum was trapped due to overly restrictive contract mechanics intended for security.
Fixed-Size/Dynamic Arrays
In Solidity, the way you manage and interact with arrays can impact the gas cost of your smart contract operations. This tutorial demonstrates the difference in gas usage between fixed-size arrays and dynamic arrays when they are filled with values. This understanding can help developers make more cost-effective decisions when designing smart contracts.
Flashloan Governance Attacks
Flashloans are a powerful feature in decentralized finance (DeFi) that allows users to borrow assets without collateral, under the condition that they return the borrowed amount within the same transaction. This feature has enabled unique financial strategies, but it also poses significant risks for governance systems.
Gas Optimization
Some Tips to Make Gas Fee Lower
Implement multicall in router-like contracts
In Solidity, implementing multicall functionality in router-like contracts can significantly reduce gas costs by batching multiple state-modifying calls into a single transaction. This technique is invaluable in contracts similar to those used by platforms like Uniswap and Compound.
Improper Input Validation
If access control is about controlling who calls a function, input validation is about controlling what they call the contract with. This usually comes down to forgetting to put the proper require statements in place.
Integer Overflow
One of the most significant incidents involving an integer overflow vulnerability occurred with the BeautyChain (BEC) token in April 2018. This exploit allowed attackers to generate an astronomical number of BEC tokens from thin air, leading to a substantial financial loss and undermining the token's value.
Local Variables
In many common DeFi projects, we frequently encounter various complex calculations that inevitably require defining many new local variables and updating existing global variables. It's well-known that modifying storage is significantly more expensive than making changes in memory.
Low-Cost Reentrancy Guard
Using a modifier for re-entrancy checks in smart contracts boosts security by confirming if the contract is currently executing. Typically, a boolean flag controls access, allowing functions to run only if the contract is not already active.
Mapping vs Dynamic Array
In Solidity, different data structures can significantly impact the gas costs associated with contract operations. This article explores the differences in gas usage between mapping and dynamic array when performing typical operations like insertions, deletions, and retrievals. Understanding these differences can help developers optimize their smart contracts for both functionality and cost.
Memory vs Calldata
1. memory: Typically used for function parameters and temporary variables within functions. Stored in memory and not persistent on the blockchain.
MethodId Optimization
When transactions are executed by the Ethereum Virtual Machine (EVM), the accompanying calldata, which specifies the contract function to be executed, incurs gas fees. These fees are calculated based on the calldata size, with 0 bytes costing 4 gas units and non-0 bytes costing 16 gas units. This pricing structure encourages the efficient use of calldata to reduce transaction costs, especially in contracts with high transaction volumes or complex operations.
MethodId Sort Optimization
In the contract, all functions are organized into an array and systematically sorted by their MethodID, a unique identifier for each function. This organization not only streamlines the management of function calls but also facilitates quick access by imposing a structured order that can be efficiently searched during function executions.
Modifiers vs Internal Functions
In Solidity, the choice between using modifiers and internal functions can impact the gas costs associated with contract operations. This article explores the differences in gas usage between modifiers and internal functions when performing typical operations. Understanding these differences can help developers optimize their smart contracts for both functionality and cost.
msg.value in Loops
When developing smart contracts, security is one of the most critical considerations. This tutorial will delve into a common but dangerous pattern: using msg.value within loops. We'll explain why this is dangerous and provide some best practices to avoid related vulnerabilities.
Non-Zero Balances
Initializing a storage variable from zero to a non-zero value is one of the most gas-intensive operations a contract can perform. It requires a total of 22,100 gas, including 20,000 gas for changing the value from zero to non-zero and 2,100 gas for cold storage access.
Optimize Timestamps and Block Numbers
In Solidity, the way data is stored can significantly impact the gas costs associated with deploying and interacting with smart contracts. Gas costs can quickly become a major concern, especially in applications that handle a large number of transactions.
Packing
Variable Packing
Predicting Contract Addresses Using Account Nonce
In Solidity, predicting contract addresses before their deployment can save substantial gas, especially when deploying interdependent contracts. This method eliminates the need for setter functions and storage variables, which are costly in terms of gas usage. We can use the LibRLP library from Solady to deterministically compute the addresses based on the deployer's nonce.
Price Manipulation
Price manipulation poses a significant risk to smart contracts that utilize decentralized exchanges (DEXs) like Uniswap, where asset prices are influenced by the liquidity within trading pools. These pools are vulnerable to manipulation by well-resourced entities capable of altering market balances to artificially influence prices. Such manipulative actions can severely undermine the functionality and security of financial applications that rely on this pricing data for essential operations.
Private Variables Security
When developing smart contracts, it's crucial to understand that marking variables as private does not make them confidential. This tutorial explains why private variables are still accessible and provides best practices for handling sensitive information in smart contracts.
Re-entrancy Attacks
Re-entrancy attacks are among the most common types of assaults on smart contracts, where attackers exploit contract vulnerabilities to recursively call the contract, enabling them to transfer assets out of the contract or mint a large number of tokens.
ResetVariable
In Solidity, using the delete keyword to remove a state variable resets it to the default value for its type. The default values differ according to the data type:
Safe Downcasting
In Solidity, downcasting from a larger integer type to a smaller one can be hazardous due to the lack of automatic overflow checks in versions before 0.8.0. This tutorial explains the risks of downcasting, provides an example of a problematic function in older Solidity versions, and offers a solution using a library like SafeCast to ensure safe operations. Even though Solidity 0.8.0 and later versions include built-in overflow checks, using SafeCast can enhance code clarity and safety.
Selector Collision Attack
The selector collision attack was one of the key reasons behind the hacking of the Poly Network cross-chain bridge.
Short-Circuiting
In Solidity, where every blockchain-affecting operation requires gas, short-circuiting is a coding technique that evaluates the second argument of a logical operation only if the first doesn't conclusively determine the outcome, thus significantly reducing unnecessary gas consumption and enhancing efficiency.
Signature Replay Attacks
Signature Replay Attacks
Smart Contract Security
Ensuring the security of smart contracts is crucial as they directly handle and store value, and are difficult to modify once deployed on a blockchain. To secure your smart contracts, follow these key steps and best practices:
Smart Contracts Development
Introduction to Smart Contracts Development on Conflux Network
SSTORE2
The cost of executing transactions on the Ethereum network can be very high, especially when interacting with smart contract storage using the SSTORE opcode. To mitigate these costs, developers can leverage alternative methods like SSTORE2 for more efficient data handling.
Tx Origin Attacks
A transaction origin attack is form of phising attack that can drain a contract of all funds.In Solidity, tx.origin retrieves the address of the transaction originator, distinguishing it from msg.sender.
Uint Types Gas Comparison
It's a common belief that in Solidity, smaller integer types like uint8, uint16, uint32, uint64, uint128, and uint256 might save gas due to their smaller size. However, this isn't always the case.
Unchecked
We know that before the Solidity version 0.8, it was necessary to manually import the SafeMath library to ensure data safety and avoid overflow, thereby preventing overflow attacks.
Unchecked Low-Level Calls
Unchecked low-level calls are a common source of vulnerabilities in smart contract development. These calls include call(), delegatecall(), staticcall(), and send(), which do not revert the transaction when they fail but instead return a boolean false. Failing to check these return values can lead to critical security issues.
Use Monolithic Contract Architecture
This tutorial explores how making the architecture of your smart contracts monolithic, rather than having several contracts that communicate with each other, can result in gas savings. Inter-contract calls can be expensive, and by consolidating logic into a single contract, you can avoid these costs, albeit with some trade-offs in terms of complexity and modularity.
Using Payable
In Solidity, leveraging the payable keyword can be a subtle yet effective way to optimize gas usage. In this article, we explore two distinct scenarios where using payable can lead to gas savings: in constructors and admin functions.
Using selfdestruct in Constructors
In Solidity, optimizing gas usage is crucial for creating efficient smart contracts. One technique involves using the selfdestruct function within the constructor for contracts designed for one-time use. This approach can reduce gas costs by eliminating the contract from the blockchain once its purpose is fulfilled.
UUPS vs Transparent Proxy
When designing upgradable smart contracts, gas efficiency is critical for users interacting with the contract. There are two common upgrade patterns: UUPS (Universal Upgradeable Proxy Standard) and the Transparent Upgradeable Proxy. While both enable upgradability, the UUPS pattern is generally more gas efficient for users.