Skip to content
On this page

S1C7: Delegate

1. Problem

The challenge uses delegatecall to invoke a Delegate contract. You need to manipulate the target and parameters of the delegatecall to obtain the flag.

2. Root Cause

delegatecall executes the code of the called contract within the caller's storage context. If the Delegate contract has a function that modifies key storage variables, an attacker can modify the challenge contract's storage via delegatecall.

3. Solution

  1. Analyze the storage layout of the Delegate contract to determine which function modifies the challenge contract's critical variable
  2. Call that function through the challenge contract's delegatecall entry point
  3. Complete the attack with two cast send calls
bash
# Step 1: Modify critical state via delegatecall
cast send $CHALLENGE "forwardCall(bytes)" <encoded_delegate_call>
# Step 2: Call mintFlag
cast send $CHALLENGE "mintFlag()"

4. Pitfalls Encountered

Storage layout collision: delegatecall preserves the caller's storage layout, so variables must occupy the same storage slots.

5. Why the Pitfall Exists

delegatecall does not change msg.sender or the storage context — it only borrows the called contract's code logic. Variables are stored in slots in declaration order. If two contracts declare variables in different orders, unexpected storage overwrites can occur.

6. How to Resolve

Carefully analyze the storage layouts of both the challenge contract and the Delegate contract. Use cast storage to read key slots and ensure the correct function is called.

7. Key Takeaways

PointExplanation
delegatecallBorrows the target contract's code but uses the caller's storage context and msg.sender
Storage layout collisionA classic problem in contract upgrade/proxy patterns: storage slots must be aligned
Proxy patterndelegatecall is the foundation of UUPS/Transparent proxy patterns

Built with AiAda