This commit is contained in:
osiris account 2023-03-15 11:08:04 -07:00
parent 8bb7099e1d
commit 54be66521a
7 changed files with 0 additions and 0 deletions

View file

@ -1,40 +0,0 @@
## smart contract vulnerabilities
### tl; dr
* `tx.origin` needs to bere placed by `msg.sender`, otherwise any contract you call can act on your behalf.
* inline assembly should be used only in rare cases.
* unclear semantics: `now` is alias for `block.timestamp` not current time; use of low level `call`, `callcode`, `delegatecall` should be avoided whenever possible; use `transfer` whenever failure of ether transfer should rollnack the whole transaction.
* beware of caller contracts: `selfdestruct` can block calling contracts unexpectedly.
* invocation of local functions via `this`: never use `this` to call functions in the same contract, it only consumes more gas than normal call.
* transferring Ether in a for/while/do-while loop should be avoid due to the block gas limit.
* erc20 `decimals` should have `uint8` as return type.
<br>
---
### in this dir
* [reentrancy](reentrancy_attacks)
* [randomness in ethereum](random_numbers.md)
* [code injection via `delegatecall`](delegatecall)
* [ddos attacks](ddos.md)
* [nonce reuse](nonce)
<br>
----
### resources
* [secureum-mind-map](https://github.com/x676f64/secureum-mind_map/blob/master/3.%20Solidity%20201.md)
* [defi hacks & exploits](https://github.com/SunWeb3Sec/DeFiHackLabs/#list-of-defi-hacks--exploits)
* [ethereum smart contract security best practices](https://consensys.github.io/smart-contract-best-practices/)
* [biased nonce sense lattice attacks against weak ECDSA](https://www.youtube.com/watch?v=6ssTlSSIJQE_

View file

@ -1,30 +0,0 @@
## DDoS attacks on the context of blockchains
<br>
### Failed Call
<br>
* [DDoS with Failed Call](https://swcregistry.io/docs/SWC-113)
<br>
### Block gas limit
<br>
* [Block gas limit by SWC registry](https://swcregistry.io/docs/SWC-128)
* [Gas limit and loops on Solidity docs](https://docs.soliditylang.org/en/latest/security-considerations.html#gas-limit-and-loops)
* [External Calls without Gas Stipends]()
<br>
### Learning references
<br>
* [Sigma Prime post](https://blog.sigmaprime.io/solidity-security.html#dos)
* [Not so smart contract](https://github.com/crytic/not-so-smart-contracts/tree/master/denial_of_service)

View file

@ -1,33 +0,0 @@
## attacks via code injection with `DELEGATECALL`
<br>
#### 🖤 This is my favorite vuln
<br>
---
### TL;DR
1. Call to untrusted contracts may introduce unexpected risks and errors.
2. External calls controlled by an attacker may force a contract to transition into an undefined state.
3. Types of external calls: `STATIC CALL` and `DELEGATE CALL`.
4. Using DELEGATE CALL, contract can preserve the storage state while using the logic of the contract. This introduces the concept of Proxies.
5. The proxy contract redirects all the calls it receives to an "logic contract", whose address is stored in its "proxy contract". The proxy runs the "logic contract"'s code as its own (modifying its storage and the balance of the "proxy contract").
<img width="956" alt="Screen Shot 2022-09-17 at 5 30 04 PM" src="https://user-images.githubusercontent.com/1130416/190880608-1b511a87-d91e-4ae4-8714-08cd7e8eec89.png">
<br>
---
### Learning resources
<br>
* [SWC docs on DELEGATECALL](https://swcregistry.io/docs/SWC-112)
* [Sigma Prime post on DELEGATECALL](https://blog.sigmaprime.io/solidity-security.html#delegatecall)

View file

@ -1,74 +0,0 @@
## proxies
### tl; dr
<br>
* here exists a special variant of a message call, named delegatecall which is identical to a message call apart from the fact that the code at the target address is executed in the context (i.e. at the address) of the calling contract and msg.sender and msg.value do not change their values. This means that a contract can dynamically load code from a different address at runtime. Storage, current address and balance still refer to the calling contract, only the code is taken from the called address.
<br>
---
### proxy patterns
<br>
- the proxy pattern uses data separation to keep business logic and data in separate contracts.
- however, in a proxy pattern, the storage contract (called a proxy) calls the logic contract during code execution.
- this is what happens in a proxy pattern:
- users interact with the proxy contract, which stores data, but doesn't hold the business logic.
- the proxy contract stores the address of the logic contract and delegates all function calls to the logic contract (which holds the business logic) using the delegatecall function.
- after the call is forwarded to the logic contract, the returned data from the logic contract is retrieved and returned to the user.
- using the proxy patterns requires an understanding of the delegatecall function. Basically, delegatecall is an opcode that allows a contract to call another contract, while the actual code execution happens in the context of the calling contract. An implication of using delegatecall in proxy patterns is that the proxy contract reads and writes to its storage and executes logic stored at the logic contract as if calling an internal function.
<br>
#### transparent proxy pattern (TPP)
1. upgrade logic is stored in proxy itself.
2. gas-inefficient
<br>
#### universal upgradable proxy standard (UUPS)
1. upgrade logic is stored in logic itself
2. gas-efficient
<br>
#### diamond pattern
* diamond patterns differ from proxy patterns because the diamond proxy contract can delegates function calls to more than one logic contract.
* when a user makes a function call, the proxy contract checks the mapping to find the facet responsible for executing that function. Then it invokes delegatecall (using the fallback function) and redirects the call to the appropriate logic contract.
<br>
---
### unitialized proxy bug
* Developers might leave proxies unitialized - this can be a problem when it leads to changes such as granting ownership to the caller
* the owners of the contract can upgrade the implementation contract
* this bug can lead to the self-destruction of the implementation contract (proxy contract is bricked)
<br>
---
### resources
* [proxy patterns](https://mirror.xyz/0xB38709B8198d147cc9Ff9C133838a044d78B064B/M7oTptQkBGXxox-tk9VJjL66E1V8BUF0GF79MMK4YG0)
* [how diamond upgrades work](https://dev.to/mudgen/how-diamond-upgrades-work-417j)
* [the state of smart contract updates](https://blog.openzeppelin.com/the-state-of-smart-contract-upgrades/)
* [multiple ways to update a contract](https://cryptomarketpool.com/multiple-ways-to-upgrade-a-solidity-smart-contract/)
* [Web3 Tutorial: write upgradeable smart contract (proxy) using OpenZeppelin](https://dev.to/yakult/tutorial-write-upgradeable-smart-contract-proxy-contract-with-openzeppelin-1916)

View file

@ -1,5 +0,0 @@
## nonce reuse
<br>
* [nonce reuse thread, by bertcmiller](https://twitter.com/bertcmiller/status/1475844939816833032)

View file

@ -1,25 +0,0 @@
## random number vulns
<br>
### post-merge notes
<br>
* `BLOCKHASH` opcode will still be available, but given that it will no longer be forged through the proof of work hashing process, the pseudorandomness provided by this opcode will be much weaker.
* `DIFFICULTY` is renamed to `PREVRANDAO`, and return the output of the randomness beacon provided by the beacon chain. It's stronger than `BLOCKHASH` but still biasable.
<br>
----
### resources
* [ethereum randomness ](https://eth2book.info/altair/part2/building_blocks/randomness)
* [randao github](https://github.com/randao/randao)
* [exploring the randao game in pos ethereum](https://ethereum.github.io/beaconrunner/notebooks/randao/randao.html)

View file

@ -1,88 +0,0 @@
## reentrancy attacks
### tl; dr
* when a contract calls an external function, that external function may itself call the calling function.
* a reentrancy attack may occur when a function makes an external call to another untrusted contract. Then, the unstrusted contract makes a recursive callback to the vulnerable contract function to steal funds.
* to prevent this attack, a contract can implement a lock in storage that prevents re-entrant calls.
<br>
---
### example
<br>
for example, suppose this method:
```
function withdrawBalance() public {
uint amountToWithdraw = userBalances[msg.sender];
(bool success, ) = msg.sender.call.value(amountToWithdraw)("");
requires(success);
userBalances[msg.sender] = 0;
}
```
and this exploit:
```
function() public payable {
if(msg.sender == address(vulnContract)) {
vulnContract.withdrawBalance();
}
}
```
How to fix?
#### Option 1: Adding a mutex locking:
```
modifier noReentrant() {
require(!locked, "nooooope");
locked = true;
_;
locked = false;
}
```
so
```
function withdrawBalance() public noReentrant {
...
}
```
<br>
#### Option 2: CEI (checks effects interaction) pattern
```
function withdrawBalance() public {
uint amountToWithdraw = userBalances[msg.sender];
userBalances[msg.sender] = 0; // update state first
(bool success, ) = msg.sender.call.value(amountToWithdraw)("");
requires(success);
}
```
<br>
----
### resources
* [reentrancy on solidity docs](https://docs.soliditylang.org/en/latest/security-considerations.html#re-entrancy)
* [reentrancy on DASP](https://www.dasp.co/#item-1)
* [reentrancy on SWC](https://swcregistry.io/docs/SWC-107)
* [reentrancy patterns](https://github.com/uni-due-syssec/eth-reentrancy-attack-patterns)
* [list of reentrancy attacks by pcaversaccio](https://github.com/pcaversaccio/reentrancy-attacks)
* [reentrancy on not so smart contract](https://github.com/crytic/not-so-smart-contracts/tree/master/reentrancy)