Topics
- Recommended design patterns
- Smart contract best practices
Smart contracts
- "Code is law"
- Ethereum smart contracts are immutables by design
Immutability
- Great for users
- Minimize trust require by contract's users
- Users can check set of rules
-
Require caution for developers
Recommended smart contract design patterns
Recommended smart contract design patterns
While writing a smart contract there are some known design patterns that are recommended
- External call
- On-Chain Data is Public Data!
External call
Be very careful when making calls to other contracts as they can expose you to several unexpected risks or errors.
External call
Makes an untrusted contract
- Name variables and contract interfaces in a way that makes it clear that interacting with them is potentially unsafe i.e.
makeWithdrawl()
and makeUntrustedWithdrwal()
.
External call
Avoid state changes after external call
- Contract A calls Contract B, Contract B is clean but it calls Contract C which contains malicious code, therefore Contract A is at risk.
- Malicious code can force race conditions by altering control flow of the contract.
- Use checks-effects-interactions pattern
External call
Understand the trade-offs between .send()
, .transfer()
, and call.value()
.send()
and .transfer()
are considered safe against reentrancy.
.send()
and .transfer()
are incompatiable with any contract whose fallback function requires more than 2,300 gas(block gas stipend).
External call
Favor pull over push for external calls
- In the case of payments this would allow users to withdraw funds rather than having funds pushed to them automatically.
- Avoid using multiple
.send()
calls in a single transaction.
On-chain data is public!
Favor pull over push for external calls
- Private data might not be exposed during a specific amount of time i.e. Rock-Paper-Scissors.
- In the case of RPS, a hash of the players move is submitted to the contract but not the blockchain, then when the time is right, the players reveal their moves. If the move the player submitted to the contract does not match their revealed move the answer is thrown out and the player is disqualified.
Smart Contract Best practices
Smart contract Best practices
Contrary to most Software Engineering enviroments smart contracts are hard to change and have a high cost of failure.
The best approach is to move slowly and carefully
Smart contract Best practices
Bugs are inevitable, so prepare for them.
- Leverage Circuit Breaker design pattern e.g.
ERC20Pausable.sol
- Manage the amount at risk with rate limits or caps e.g.
ERC20Capped.sol
- Setup effective upgrade path for bug fixes and updates.
Smart contract Best practices
Roll out with caution.
- Take advantage of bug bounties and testing tools
- Get contracts audited by 3rd parties
Smart contract Best practices
When possible opt for less complexity, as this usually leads to less bugs.
Smart contract Best practices
Use audited / hardened code whenever possible.
Smart contract Best practices
Write code that is human readable.
Smart contract Best practices
Only use the blockchain when necessary.
Smart contract Best practices
Understand the environment.
- Be cautious when calling external contracts
- Contract functions are public and can be called in ways that arent intended.
Smart contract Best practices
Rigidity versus Upgradeability.
- Upgradeability is great from an engineering perspective but amplifies the amount of vulnerabilities in code.
- Contracts that have a defined lifespan and are relatively simple, Upgradeability is likely not a concern.
Smart contract Best practices
Monolithic versus Modular
- Self contained contracts make reviewing the contract much easier.
- Modular code is typically easier to maintain from and engineering standpoint.
Smart contract Best practices
Code Duplication versus Reuse
- Whenever possible use hardened, proven code rather than rolling your own.