CTF Name
Context
In the digital realm of Etheria, there exists a legendary Treasure Vault overseen by a mysterious figure known as the Curator. This vault is said to hold vast amounts of digital treasures that many explorers seek. To prevent unworthy or malevolent entities from plundering its riches, the Curator has devised a system of approvals and blackmarks.
Explorers must first prove themselves by depositing unique digital artifacts into the vault. Once approved by the Curator, explorers can trade treasures with one another. However, should an explorer act with deceit or malintent, the Curator marks them, preventing any further interaction with the vault's contents.
CTF participants are tasked with finding a way to bypass the Curator's security, transfer treasures without consent, or exploit potential vulnerabilities within the contract to seize control from the Curator. The challenge lies in understanding the smart contract's code, identifying weaknesses, and crafting transactions that would enable them to break the rules set by the Curator without being detected.
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.13;
contract TreasureVault {
address public curator;
constructor() {
curator = msg.sender;
}
modifier onlyCurator() {
require(msg.sender == curator, "Not the curator");
_;
}
modifier isExplorerApproved(address explorer) {
require(!_blackmark[explorer], "Explorer is not approved");
_;
}
mapping (address => uint256) public _treasureBalance;
mapping (address => bool) public _blackmark;
function markExplorer(address explorer) public onlyCurator {
uint256 balance = _treasureBalance[explorer];
require(balance != 0, "Explorer has no treasures");
_blackmark[explorer] = true;
}
function approveExplorer(address explorer) public onlyCurator {
bool blackmarked = _blackmark[explorer];
require(blackmarked, "Explorer is already approved");
_blackmark[explorer] = false;
}
function depositTreasure(
address _explorer,
uint256 _amount
) public {
require(_explorer == msg.sender, "Unauthorized action");
require(_treasureBalance[_explorer] == 0, "Explorer already has treasures");
require(_amount > 0, "Invalid treasure amount");
_treasureBalance[_explorer] += _amount;
_blackmark[_explorer] = false;
}
function checkTreasure(address _explorer) public view returns (uint256) {
return _treasureBalance[_explorer];
}
function transferTreasure(
address _from,
address _to,
uint256 _amount
) public isExplorerApproved(_from) {
uint256 fromBalance = _treasureBalance[_from];
uint256 toBalance = _treasureBalance[_to];
require(_from == msg.sender, "Unauthorized transfer");
require(fromBalance != 0, "No treasures to transfer");
require(toBalance != 0, "Recipient is unknown");
require(_amount <= fromBalance, "Insufficient treasures");
_treasureBalance[_from] = fromBalance - _amount;
_treasureBalance[_to] = toBalance + _amount;
}
function removeTreasure(
address _from,
uint256 _amount
) public isExplorerApproved(_from) {
require(_from == msg.sender, "Unauthorized removal");
uint256 accountBalance = _treasureBalance[_from];
require(_amount <= accountBalance, "Insufficient treasures");
if (_amount == accountBalance) {
delete _treasureBalance[_from];
delete _blackmark[_from];
} else {
accountBalance -= _amount;
_treasureBalance[_from] = accountBalance;
}
}
}