Starting My Smart Contract Security Journey
Daily posts on real vulnerabilities, exploits, and lessons from audits. Learning in public, one bug at a time.
Let's build a more secure Web3 together
This one line silently gives users 0 tokens.
Day 103 of my SR Journey π§΅
Consider:
uint tokens = msg.value / weiPerEth * tokensPerEth;
Looks reasonable.
But Solidity uses integer division.
Meaning: π
Anything less than 1 ETH becomes 0 before multiplication happens.
The result,
Users receive 0 tokens.
The fix:
Multiply first, then divide.
uint tokens = msg.value * tokensPerEth / weiPerEth;
Same math.
Completely different outcome.
Big lesson: Order matters.
Audit Checklist
Whenever you see:
β for loops
β while loops
Ask:
""Can users increase the size of this data structure?""
If yes:
Dig deeper.
#SmartContractSecurity
One protocol had 1,100 ETH stuck because of a loop.
Not because of hackers.
Because of gas limits.
Day 102 of my SR Journey π§΅
A common Solidity mistake:
Looping through arrays users can grow indefinitely.
Example:
for (...)
Looks harmless. π
Until the array becomes huge.
Then execution cost exceeds block gas limits.
Now the function can never complete.
GovernMental suffered from a version of this problem.
Funds became effectively trapped.
Why? π
Because the contract couldn't afford to finish its own logic.
Modern rule:
β Never iterate through user-controlled arrays
Instead:
β Withdrawal pattern
β Pull over push architecture
Big lesson:
Scalability issues often become security issues.
#Ethereum#Solidity#Web3ββ
Randomness on Ethereum is hard.
Why?
Because everyone must verify the same result.
True randomness and deterministic systems don't naturally mix.
#Ethereum#Web3Explained
Would you trust a lottery where the organizer can slightly adjust the winning number?
That's basically what happens when developers use block.timestamp for randomness.
Day 101 of my SR Journey π§΅
Many beginners write:
if(block.timestamp % 15 == 0)
and think it's random. π
It isn't.
Validators can influence timestamps within acceptable limits.
Only slightly.
But sometimes slightly is enough.
For lottery systems, that tiny adjustment can become profit.
That's why timestamp-based randomness has repeatedly caused vulnerabilities. π
Safer alternatives include:
β VRF solutions
β Commit-reveal schemes
β Dedicated randomness protocols
For timing logic, use:
block.number where appropriate.
Big lesson:
Time is not randomness.
Never confuse the two.
#Ethereum#SmartContracts#Web3Security
If your protocol uses block.timestamp for randomness...
You're not generating randomness.
You're generating attack opportunities.
#Ethereum#Web3Security
This old Solidity bug powered countless honeypots.
And it was only one missing word.
Day 100 of my SR Journey π§΅
Older Solidity versions had a dangerous quirk.
Local structs without explicit location defaults could point directly to STORAGE.
Example: π
MyStruct s;
Developers thought they created a temporary variable.
They didn't.
Instead: s pointed to storage slot 0.
Meaning writes to the struct modified real contract state.
Attackers abused this to:
β Flip booleans
β Change ownership
β Disable locks π
β Manipulate balances
All without touching the intended variables directly.
The fix is simple:
Always declare memory or storage explicitly.
Never leave location ambiguous.
Big lesson:
Defaults are dangerous.
Especially in security-critical code.
#Ethereum#Solidity#Web3
The scariest bugs are the ones that look harmless.
One missing keyword once allowed attackers to rewrite critical contract state.
#SmartContracts#Ethereum