# Solidity Security ## Common mistakes ### private variables can be read by anyone ```js web3.eth.getStorageAt(contract.address, SLOT_NUMBER) ``` ### reentrance When contract sends funds to another contract, receive() is called. While this happens, receive() function can call original smartcontract function ("reenter" it). ### uint unsafe math uint can be overflown, so need to use SafeMath ### view functions can return different results at different times, so cannot be trusted ``` gasleft() ``` ### random must be used from oracles, there is not on-chain random ### Bytecode Minimal bytecode to return number: ``` 60 2a // push 2a 60 00 // push 00 52 // mstore(00, 2a) 60 01 // push 01 60 00 // push 00 f3 // return (from: 00, length: 01) ``` To deploy we need a bytecode that returns our code: ``` 60 0a // copy 1d bytes 60 0c // which are in code position 0c 60 00 // to memory position 0 39 // do it 60 0a // return 1d bytes 60 00 // which are in memory position 0 f3 // do it 60 2a // push 2a 60 00 // push 00 52 // mstore(00, 2a) 60 01 // push 01 60 00 // push 00 f3 // return (from: 00, length: 01) ``` Deployment: ```js const solver = new web3.eth.Contract([]) solver.deploy({data: "602a60005260016000f3"}).send({from: player}) ``` ### Gate one Count of gas: 82164 (via debugger) ### Gate two - extcodesize returns 0 during constructor ### Out of bound reading - if we can write to any index of array without checks, we can rewrite any variable of smartcontract - If we can lessen array length, we can make it negative -> so it overflows and we can write anywhere - Pointer to array is a number, to get actual storage address we need to keccak256(it) - If index is uint, you can overflow it ## Puzzle 1. Overwrite owner of PuzzleWallet (it is in place of pendingAdmin of proxy) 2. Drain balance to 0 (use multicall to call multicall with delegate multiple times) 3. Rewrite maxBalance (it is in place of admin of proxy)