diff --git a/solidity/locked-eth-in-contract.sol b/solidity/locked-eth-in-contract.sol new file mode 100644 index 0000000..64efdfe --- /dev/null +++ b/solidity/locked-eth-in-contract.sol @@ -0,0 +1,61 @@ +pragma solidity 0.8.13; + +// ruleid: locked-eth-in-contract +contract Test1 { + receive() external payable {} +} + +// ruleid: locked-eth-in-contract +contract Test2 { + bool flag; + function get(bool payed) external payable { + if (msg.value > 0){ + flag = true; + } + } +} + +// ok: locked-eth-in-contract +contract Test3 { + receive() external payable {} + + function skim(address payable to) external{ + to.send(this(address).balance); + } +} + +// ok: locked-eth-in-contract +contract Test4 { + receive() external payable {} + + function skim(address payable to) external{ + to.transfer(this(address).balance); + } +} + +// ok: locked-eth-in-contract +contract Test5 { + receive() external payable {} + + function destruct(address payable to) external{ + selfdestruct(to); + } +} + +// ruleid: locked-eth-in-contract +contract Test6 { + receive() external payable {} + + function skim(address payable to) external{ + to.call(...); + } +} + +// ok: locked-eth-in-contract +contract Test7 { + receive() external payable {} + + function skim(address payable to) external{ + (bool sent, bytes memory data) = to.call{value: msg.value}(""); + } +} \ No newline at end of file diff --git a/solidity/locked-eth-in-contract.yaml b/solidity/locked-eth-in-contract.yaml new file mode 100644 index 0000000..908ebd9 --- /dev/null +++ b/solidity/locked-eth-in-contract.yaml @@ -0,0 +1,71 @@ +rules: + - id: locked-eth-in-contract + message: Contract supports depositing ETH, but have no direct way to withdraw any ETH balance present in the contract. + languages: + - solidity + severity: WARNING + metadata: + references: + - https://blog.openzeppelin.com/compound-iii-audit/ + - https://github.com/compound-finance/comet/commit/36816138e15477d0ac487b9d97affc0d296ccc49 + category: security + tags: + - compound + patterns: + - pattern: | + contract $CONTRACT { + ... + function $RECEIVE(...) payable { + ... + } + ... + } + - pattern-not: | + contract $CONTRACT { + ... + function $FUNC(...) { + ... + $ADDR.call{value: $AMOUNT, gas: $GAS}(...); + } + ... + } + - pattern-not: | + contract $CONTRACT { + ... + function $FUNC(...) { + ... + $ADDR.call{value: $AMOUNT}(...); + } + ... + } + - pattern-not: | + contract $CONTRACT { + ... + function $FUNC(...) { + ... + $ADDR.send(...); + } + ... + } + - pattern-not: | + contract $CONTRACT { + ... + function $FUNC(...) { + ... + $ADDR.transfer($AMOUNT); + } + ... + } + - pattern-not: | + contract $CONTRACT { + ... + function $FUNC(...) { + ... + selfdestruct(...); + } + ... + } + - pattern-not-inside: | + abstract contract $CONTRACT { + ... + }