Platform: Code4rena
Start Date: 09/02/2024
Pot Size: $60,500 USDC
Total HM: 17
Participants: 283
Period: 12 days
Judge:
Id: 328
League: ETH
Rank: 134/283
Findings: 1
Award: $20.07
🌟 Selected for report: 0
🚀 Solo Findings: 0
🌟 Selected for report: 0xSmartContract
Also found by: 0xAsen, 0xDetermination, 0xStriker, 0xblack_bird, 0xbrett8571, 0xepley, 0xweb3boy, 14si2o_Flint, Bauchibred, DarkTower, JayShreeRAM, JcFichtner, K42, McToady, Myd, PoeAudits, Rolezn, SAQ, ZanyBonzy, aariiif, albahaca, ansa-zanjbeel, cheatc0d3, clara, cudo, dimulski, fouzantanveer, foxb868, hassanshakeel13, hunter_w3b, kaveyjoe, klau5, peanuts, pipidu83, popeye, rspadi, scokaf, shaflow2, tala7985, wahedtalash77, yongskiws
20.0744 USDC - $20.07
AI Arena is a unique platform fighting game where players train artificial intelligence (AI) characters to battle against each other. Think of it as a combination of Pokémon and Super Smash Bros, but instead of controlling the characters directly, you train them to learn various skills and strategies.
Training Phase: Players start by selecting an AI character or creating their own. They then enter a training phase where they teach their AI character different moves, techniques, and strategies. This could involve programming specific actions, setting priorities, or even using machine learning algorithms to let the AI learn from its own experiences.
Battle Phase: Once the training is complete, players can enter the battle phase where their AI characters compete against each other in a platform fighting arena. The battles can be real-time or turn-based, depending on the game's mechanics.
Skill Development: During battles, AI characters can learn and adapt based on their experiences. They may adjust their strategies, prioritize certain moves, or develop new tactics on the fly. This creates a dynamic and evolving gameplay experience.
Customization: Players have a high level of control over how their AI characters are trained and developed. They can tweak various parameters, experiment with different techniques, and tailor their strategies to counter specific opponents.
Competition: Players can compete against each other in tournaments or challenge matches to see whose AI character reigns supreme. The outcome of battles depends not only on the AI's abilities but also on the effectiveness of the strategies devised by the players.
Unique Fighter Tokens: Instead of traditional in-game characters, AI Arena represents fighters as non-fungible tokens (NFTs) on the blockchain. Each fighter token is distinct, with its own set of attributes and abilities, making them collectible and tradable assets within the game ecosystem.
Player-Driven Training: Players take on the role of trainers, not just controlling characters but actively shaping their abilities and strategies through training. This introduces a layer of player agency and creativity, as they experiment with different training methods to optimize their fighters for battle.
Blockchain Integration: By tokenizing fighters and game assets on the blockchain, AI Arena leverages the transparency, security, and decentralized nature of blockchain technology. This enables true ownership of in-game assets, as players can buy, sell, and trade their fighter NFTs in a secure and transparent manner.
Economic Incentives: The game's native token, $NRN, serves as both a medium of exchange and a means of incentivizing player participation. Players can stake their tokens for a chance to earn rewards through ranked battles, creating economic incentives for engagement and skill improvement.
Risk-Reward Dynamics: The risk-reward dynamics of the game add another layer of strategy and excitement. Players must carefully manage their stakes and performance in battles, as poor performance can result in the loss of stakes. This introduces a level of risk that adds tension and strategic depth to each match.
Resource Management: The concept of voltage and batteries introduces a resource management aspect to the game. Players must consider how they allocate their voltage, balancing the cost of participating in battles with the need to replenish their energy over time or through in-game purchases.
Off-Chain Game Logic: While the core game logic operates off-chain via game servers, the integration of blockchain technology ensures that critical game data, such as fighter ownership and transaction history, remains secure and tamper-proof on the blockchain.
I use the below analyzing approach for each smart contract to ensure that evaluates various aspects of the smart contracts from different perspectives including security, gas efficiency, usability, scalability, interoperability, and key functionalities.
Contract Overview:
Key Functionalities:
Security Considerations:
Recommendations:
Static Analysis:
Dynamic Analysis:
Conclusion:
AiArenaHelper
is used to generate and manage the physical attributes of AI fighters in a game or simulation. The contract includes functionality to handle ownership, attribute probabilities, and the creation of fighter attributes based on DNA.
State Variables:
attributes
: An array storing the names of physical attributes a fighter can have.defaultAttributeDivisor
: An array storing default DNA divisors for each attribute.Mappings:
attributeProbabilities
: A mapping tracking fighter generation to attribute probabilities.attributeToDnaDivisor
: A mapping of attribute names to DNA divisors.Constructor:
External Functions:
transferOwnership
: Allows the current owner to transfer ownership to another address.addAttributeDivisor
: Allows the owner to add attribute divisors for attributes.createPhysicalAttributes
: Creates physical attributes for a fighter based on its DNA, generation, icons type, and dendroid status.Public Functions:
addAttributeProbabilities
: Allows the owner to add attribute probabilities for a given generation.
deleteAttributeProbabilities
: Allows the owner to delete attribute probabilities for a given generation.
getAttributeProbabilities
: Retrieves attribute probabilities for a given generation and attribute.
dnaToIndex
: Converts DNA and rarity rank into an attribute probability index.
Access Control: The contract uses require(msg.sender == _ownerAddress);
in functions like transferOwnership
and addAttributeDivisor
to enforce access control. However, it could benefit from using a standardized access control mechanism like OpenZeppelin's Ownable
contract for better readability and security.
Input Validation: Functions such as addAttributeProbabilities
and deleteAttributeProbabilities
lack input validation for the generation
parameter. Adding validation to ensure that generation
is within a reasonable range could enhance the contract's robustness.
Magic Numbers: There are hardcoded numbers like 6
and 99
in various places in the contract. It's a good practice to define these numbers as constants with meaningful names for better readability and maintenance.
Gas Considerations: The contract uses nested mappings, which can lead to high gas costs for storage and computation. Considerations should be made to optimize gas usage, especially when dealing with potentially large datasets.
Ownership Transfer: Executing the transferOwnership
function in a controlled environment can verify if ownership transfer works as intended and only the current owner can transfer ownership.
Attribute Management: Testing addAttributeDivisor
and addAttributeProbabilities
functions can ensure that only the owner can modify attribute divisors and probabilities, and the changes are reflected correctly.
Attribute Generation: Running tests on createPhysicalAttributes
with different inputs for DNA, generation, icons type, and dendroid status can validate if the function generates physical attributes correctly based on the provided parameters.
Attribute Probability Calculation: Testing dnaToIndex
function with various inputs for DNA, rarity rank, and attribute can verify if it correctly calculates the attribute probability index based on the provided parameters and attribute probabilities.
Gas Optimization:
Usability:
Scalability:
Interoperability:
Centralization of Control: The contract is highly centralized, with the owner having the power to change attribute divisors and probabilities. This could be a point of failure or manipulation.
Lack of Access Control: The contract uses a simple require
statement for owner-only functions. It could benefit from using more sophisticated access control mechanisms like OpenZeppelin's Ownable
contract.
No Input Validation: There is no validation on the input for the dna
parameter in createPhysicalAttributes
, which could lead to unexpected behavior if invalid DNA is provided.
Magic Numbers: The contract uses magic numbers (e.g., 50
in createPhysicalAttributes
), which should be replaced with named constants for better readability and maintainability.
No Events: The contract lacks events for state-changing operations, which would be useful for off-chain monitoring and indexing.
Potential Integer Overflow: While Solidity 0.8.x introduces built-in overflow checks, the contract should still be cautious with arithmetic operations, especially when dealing with probabilities and indexes.
Ownership: The contract has a transferOwnership function that allows the current owner to transfer ownership to another address. However, there are no access controls for certain critical functions like addAttributeProbabilities and deleteAttributeProbabilities. Adding access controls, such as only allowing specific addresses to call these functions, could enhance security.
External Calls: There don't appear to be any external calls in this contract, reducing the risk of attack vectors such as reentrancy or malicious contract interactions.
Input Validation: The contract performs input validation in some functions, ensuring that only valid inputs are accepted. However, further validation checks could be added to prevent unexpected behavior.
FighterFarm
, is an ERC721 token representing AI Arena Fighter NFTs. The contract includes functionality for minting, transferring, and managing these NFTs, including staking and rerolling fighters. It inherits from OpenZeppelin's ERC721
and ERC721Enumerable
contracts.
Contract Inheritance and Imports:
ERC721
and ERC721Enumerable
, which are OpenZeppelin contracts for non-fungible tokens (NFTs).FighterOps.sol
, Verification.sol
, AAMintPass.sol
, AiArenaHelper.sol
, Neuron.sol
) and an external library from OpenZeppelin.State Variables:
MAX_FIGHTERS_ALLOWED
, maxRerollsAllowed
, rerollCost
, generation
, totalNumTrained
, treasuryAddress
, and addresses for various contracts.Constructor:
External and Public Functions:
Internal and Private Functions:
Event Logging:
Locked
and Unlocked
when fighters are locked or unlocked.Metadata and URI Functions:
Modifiers:
_beforeTokenTransfer
to perform actions before token transfers.Supports Interface:
supportsInterface
function to declare support for ERC721 and ERC721Enumerable interfaces.Security Considerations:
claimFighters
function.transferFrom
and safeTransferFrom
functions to include custom transferability checks.reRoll
function allows users to reroll a fighter's attributes for a cost in an ERC20 token.contractURI
function to return the metadata URI for the contract and a tokenURI
function to return the metadata URI for individual tokens.supportsInterface
function to indicate which interfaces the contract supports.getAllFighterInfo
function to retrieve comprehensive information about a fighter.NFT Management:
Game Mechanics:
Economic Model:
External Dependencies:
FighterOps
, Verification
, AAMintPass
, AiArenaHelper
, Neuron
) for additional functionalities such as fighter operations, signature verification, mint pass redemption, AI model handling, and token transactions.Access Control:
Interoperability:
User Experience:
Metadata Management:
Scalability:
require
statements to restrict certain functions to the owner or other privileged addresses, which is a common pattern to control access. However, it relies on a single _ownerAddress
for owner-only functions, which could be a single point of failure. Consider using a multisig wallet or implementing a more decentralized governance mechanism.claimFighters
function uses a signature verification mechanism to ensure that claims are authorized. This is a good security practice, but it's crucial that the private key for _delegatedAddress
is securely managed.transferOwnership
and other administrative functions do not emit events. It's a best practice to emit events for critical state changes for transparency and easier off-chain tracking.mintFromMergingPool
function can only be called by the _mergingPoolAddress
. This is a good use of access control, but ensure that the merging pool contract itself is secure.reRoll
function allows users to reroll fighters' attributes by spending an ERC20 token (_neuronInstance
). It checks for sufficient balance and successful transfer, which is good. However, it uses approveSpender
followed by transferFrom
, which could be susceptible to reentrancy attacks. Consider using the Checks-Effects-Interactions pattern and reentrancy guards._ableToTransfer
function to add additional checks before transfers. This is a good practice to enforce business logic, but ensure that the logic is sound and does not unintentionally restrict valid transfers.fighters
). This could potentially cause gas issues if the array becomes too large. Consider implementing a cap on the total supply.totalNumTrained
counter without any apparent limit, which could theoretically overflow if incremented enough times. However, since it's a uint32
, this is unlikely to be an issue in practice.
FighterOps
is intended to be used for managing fighter NFTs within a game called AI Arena.
Library Purpose: This library is intended for managing non-fungible tokens (NFTs) representing fighters in the AI Arena game.
Events:
FighterCreated
: This event is emitted whenever a new fighter NFT is created. It includes the ID of the fighter, its weight, elemental attribute, and generation.Structs:
FighterPhysicalAttributes
: Defines the physical attributes of a fighter, including its head, eyes, mouth, body, hands, and feet.Fighter
: Defines a complete fighter NFT, including its weight, elemental attribute, physical attributes (using FighterPhysicalAttributes
), ID, model hash, model type, generation, icons type, and dendroid boolean.Public Functions:
fighterCreatedEmitter
: A public function that emits the FighterCreated
event. This function could be a security risk if it is not intended for public use, as any user could emit the event, potentially leading to event spamming or misinformation.getFighterAttributes
: A public view function that returns an array of the fighter's physical attributes. This function is read-only and does not pose a direct security risk.viewFighterInfo
: A public view function that returns comprehensive information about a fighter, including the owner's address and various attributes of the fighter. This function is read-only and does not pose a direct security risk.Modularity and Reusability:
Gas Efficiency:
getFighterAttributes
function returns an array of attributes in a single call, which can be more gas-efficient than fetching attributes individually.Event-driven Architecture:
Data Access Control:
onlyOwner
or integrating with an access control mechanism could enhance security by restricting certain functions to authorized users.Immutability and Extensibility:
Potential Improvements:
view
functions, could optimize gas usage further.fighterCreatedEmitter
function is marked as public
, which means anyone can call it and emit the FighterCreated
event. This could be a design flaw if the intention is to restrict the creation of fighters to certain privileged users or contracts. It should likely be internal
or have some access control mechanism in place.Fighter storage self
) in the functions suggests that it expects to be tightly coupled with a contract's storage layout. It's important to ensure that the contract using this library is designed to accommodate this storage pattern.
GameItems
inherits from OpenZeppelin's ERC1155
standard, which is a multi-token standard allowing for the creation of fungible and non-fungible tokens within a single contract. The contract is designed to manage game items for a platform called AI Arena.
Contract Structure:
GameItems
and inherits from the OpenZeppelin ERC1155 standard contract.BoughtItem
), item locking (Locked
), and item unlocking (Unlocked
).Structs:
GameItemAttributes
to store attributes of each game item, such as name, supply, transferability, price, and daily allowance.State Variables:
name
and symbol
represent the name and symbol of the collection of game items.allGameItemAttributes
stores attributes for all game items.treasuryAddress
holds the address that receives funds from purchased game items._ownerAddress
stores the address with owner privileges._itemCount
keeps track of the total number of game items._neuronInstance
holds the Neuron contract instance.Mappings:
allowanceRemaining
tracks remaining allowance for each user and game item.dailyAllowanceReplenishTime
tracks the replenishment time for daily allowances.allowedBurningAddresses
and isAdmin
are mappings for managing permissions.Events: The contract defines events for buying items, locking, and unlocking them, which are emitted when these actions occur.
Constructor:
External Functions:
transferOwnership
and adjustAdminAccess
allow the owner to manage admin access.adjustTransferability
allows the owner to adjust transferability of game items.instantiateNeuronContract
sets the address of the Neuron contract.Public Functions:
setAllowedBurningAddresses
and setTokenURI
are for managing allowed burning addresses and setting token URIs respectively.createGameItem
is used by admins to create new game items.burn
allows burning of game items by allowed addresses.contractURI
returns the URI where contract metadata is stored.uri
, getAllowanceRemaining
, remainingSupply
, and uniqueTokensOutstanding
provide information about game items.safeTransferFrom
enables safe transfer of game items.Private Functions:
_replenishDailyAllowance
replenishes daily allowances for users.Gas Efficiency:
Interoperability:
safeTransferFrom
enhances compatibility with wallets and decentralized applications.Usability:
Economic Considerations:
itemPrice
) and their availability (itemsRemaining
) based on economic principles.dailyAllowance
) introduces a dynamic element to item availability, potentially influencing user behavior and engagement.Scalability:
Upgradeability:
Regulatory Compliance:
Centralization Risks: The contract has a single owner who has significant control over the contract, which introduces centralization risks. If the owner's private key is compromised, the attacker could manipulate admin access, lock/unlock tokens, and change ownership.
Reentrancy: The mint
function calls an external contract (_neuronInstance.transferFrom
) before updating the state. This could potentially lead to reentrancy attacks if the Neuron contract is not secure. However, since Solidity 0.8.0 includes checks against overflows and underflows, the risk is mitigated.
Daily Allowance Replenishment: The daily allowance replenishment logic could be exploited if the _replenishDailyAllowance
function is not carefully managed. It's important to ensure that this function cannot be called arbitrarily to reset allowances.
Access Control: The contract relies on custom access control logic, which could be error-prone. It's generally safer to use established access control patterns like OpenZeppelin's Ownable
and AccessControl
.
Token URI Privacy: The _tokenURIs
mapping is private, which means that there's no direct way for other contracts to access the token URIs if needed.
Contract Upgradeability: The contract does not appear to be upgradeable. If a flaw is found or an improvement is needed, a new contract must be deployed, and state and tokens would need to be migrated.
ERC1155 Compliance: The contract should ensure full compliance with the ERC1155 standard, including proper handling of hooks like _beforeTokenTransfer
if needed.
Gas Optimization: The contract could be optimized for gas usage, for example, by using uint256
for the dailyAllowanceReplenishTime
instead of uint32
to avoid potential storage layout inefficiencies.
MergingPool
,is part of a system that allows users to earn new fighter NFTs. The contract includes functionality for managing points associated with fighter tokens, selecting winners, and claiming rewards.
Events:
PointsAdded
: Triggered when merging pool points are added.Claimed
: Triggered when a user claims rewards.State Variables:
winnersPerPeriod
: Indicates the number of winners per period.roundId
: Tracks the current round.totalPoints
: Total points accumulated in the merging pool._ownerAddress
: Address with owner privileges._rankedBattleAddress
: Address of the ranked battle contract._fighterFarmInstance
: Instance of the FighterFarm
contract.Constructor:
External Functions:
transferOwnership
: Allows transferring ownership of the contract.adjustAdminAccess
: Lets the owner adjust admin access for an address.updateWinnersPerPeriod
: Allows admins to update the number of winners per period.pickWinner
: Admins can pick winners for the current round.claimRewards
: Users can claim rewards for multiple rounds.getUnclaimedRewards
: Retrieves unclaimed rewards for a specific address.Public Functions:
addPoints
: Adds merging pool points to a fighter. Only the ranked battle contract can call this.getFighterPoints
: Retrieves points for multiple fighters up to the specified maximum token ID.Functionality:
Security:
addPoints
, can only be called by the ranked battle contract to prevent unauthorized manipulation of merging pool points.Gas Efficiency:
claimRewards
and getUnclaimedRewards
, the contract iterates over data to process rewards. Depending on the size of the data, gas costs for these operations could become significant, especially if the contract scales to handle a large number of users and rounds.Flexibility and Extensibility:
FighterFarm
contract to mint new fighter NFTs. This modular design allows for integration with other contracts within the ecosystem.Usability:
Scalability:
transferOwnership
and adjustAdminAccess
use a simple require
statement for access control. It is recommended to use a more robust access control mechanism, such as OpenZeppelin's Ownable
or AccessControl
for better security practices.claimRewards
function iterates over all rounds and winners, which could potentially run out of gas if there are many rounds or winners, leading to denial of service._fighterFarmInstance.mintFromMergingPool
function makes an external call to an untrusted contract, it could be vulnerable to reentrancy attacks. It's important to ensure that state changes are made before external calls to prevent this.unchecked
keyword is used.pickWinner
function does not validate the winners
array elements, which could lead to unexpected behavior if invalid token IDs are passed.getFighterPoints
function initializes an array of size 1 but then attempts to fill it with maxId
elements, which will cause an out-of-bounds error. This function needs to be corrected to initialize the array with the correct size._fighterFarmInstance.mintFromMergingPool
function is not vulnerable to reentrancy attacks.pickWinner
.getFighterPoints
function to properly initialize the points array.Neuron
which is an ERC20 token with additional roles and functionalities. It inherits from OpenZeppelin's ERC20
and AccessControl
contracts.
Contract Initialization: The contract is initialized with a name ("Neuron") and a symbol ("NRN"). Upon deployment, it mints an initial supply of tokens to the treasury and contributor addresses.
Roles: The contract defines three roles using AccessControl
:
MINTER_ROLE
: Allowed to mint new tokens.SPENDER_ROLE
: Allowed to approve spending of tokens.STAKER_ROLE
: Allowed to approve staking of tokens.Ownership: The contract has an owner address that can transfer ownership, add minters, stakers, spenders, and adjust admin access.
Admins: There is a mapping to track which addresses have admin privileges.
Airdrop Setup: Admins can set up airdrops by approving a list of recipients to claim a specified amount of tokens from the treasury.
Token Claiming: Users can claim tokens if they have an allowance from the treasury.
Minting: The mint
function allows addresses with the MINTER_ROLE
to mint new tokens, provided the max supply is not exceeded.
Burning: The burn
and burnFrom
functions allow token holders to destroy their tokens or tokens from another account with an allowance.
Approvals: The approveSpender
and approveStaker
functions allow addresses with the respective roles to approve allowances for spending or staking tokens.
Functionality:
transfer
, transferFrom
), approving spending (approve
), and checking balances (balanceOf
).mint
), burning (burn
, burnFrom
), and role management (addMinter
, addStaker
, addSpender
, adjustAdminAccess
).setupAirdrop
), which can be useful for distributing tokens in bulk.Gas Optimization:
calldata
for function parameters where appropriate, which saves gas costs by avoiding unnecessary copying of data.Scalability:
Usability:
TokensClaimed
, TokensMinted
), which can be helpful for off-chain applications to track and react to on-chain events.Interoperability:
Upgradeability:
Centralization of Power: The contract is highly centralized, with the owner having the power to add roles and adjust admin access. This could be a single point of failure or abuse.
Lack of Ownership Transfer Checks: The transferOwnership
function does not check if the newOwnerAddress
is a non-zero address, which could lead to loss of contract control if set to the zero address.
Role Management: The contract uses AccessControl
for role management, which is generally secure, but the addition of roles is centralized under the owner.
Initial Minting: A large number of tokens are minted at deployment without any checks or restrictions. This could be a problem if not correctly managed or if the initial addresses are not secure.
Max Supply Enforcement: The mint
function checks that the new total supply will not exceed the MAX_SUPPLY
, which is good practice to prevent over-minting.
Airdrop Approval: The setupAirdrop
function could potentially approve large amounts of tokens without ensuring the treasury has sufficient balance, leading to failed claims later.
ERC20 Compliance: The contract should remain compliant with the ERC20 standard, but custom functions should be carefully reviewed to ensure they don't introduce unexpected behaviors.
Gas Optimization: The contract could be optimized for gas usage. For example, the setupAirdrop
function could be expensive due to the loop.
No Reentrancy Guards: While not directly an issue with the ERC20 functions, any additional functionality that interacts with external contracts should have reentrancy guards to prevent attacks.
No Event Emission on Ownership Transfer: The contract does not emit an event when ownership is transferred, which is a common practice for transparency and tracking changes in control.
No Input Validation: There is no validation on the addresses provided to the constructor, which could lead to setting the zero address for critical roles like the treasury.
RankedBattle
is part of a game where players can stake NRN tokens on fighters, participate in battles, and earn rewards based on the outcomes of these battles. The contract includes functionality for staking and unstaking tokens, claiming rewards, and updating battle records.
Events: The contract emits events for stake, unstake, claim, and points changed.
Structs:
BattleRecord
: Records the wins, ties, and losses for each fighter.State Variables:
Mappings:
Constructor: Initializes the contract with addresses and instantiates contract instances.
External Functions:
Public Functions:
Private Functions:
Modifiers: None are present in this contract.
Usage of External Contracts:
FighterFarm
, VoltageManager
, MergingPool
, Neuron
, and StakeAtRisk
for various functionalities like updating fighter staking status, spending voltage, adding points to the merging pool, transferring NRN tokens, and managing stake at risk.claimNRN()
should be optimized to minimize gas consumption, especially if the loop may iterate over a large number of rounds.require
statements to restrict certain functions to the owner or admins, which is a common pattern to control access. However, it's crucial to ensure that the admin system is robust and that there's a secure way to transfer ownership or adjust admin access.Neuron
, FighterFarm
, VoltageManager
, StakeAtRisk
, MergingPool
) which could potentially introduce reentrancy attacks if not handled properly. It's important to follow the Checks-Effects-Interactions pattern and consider using reentrancy guards where necessary.claimNRN
, loop through rounds to calculate rewards, which could become expensive in terms of gas if there are many rounds to process.eloFactor
to calculate points, which should be reviewed to ensure it's calculated fairly and cannot be manipulated.battleResult
(0 for win, 1 for tie, 2 for loss). It's important to ensure that these values are consistently used and validated.Neuron
, FighterFarm
, VoltageManager
, StakeAtRisk
, MergingPool
) are audited and secure.StakeAtRisk
interacts with a gaming or competition system where participants, referred to as "fighters," can stake tokens (NRNs) that are at risk of being lost during a round of competition. The contract is designed to work with a RankedBattle
contract and a Neuron
contract, which seem to handle the logic for the battles and the token mechanics, respectively.
State Variables and Mappings:
roundId
: Tracks the current round of competition.treasuryAddress
: The address where lost stakes are sent.totalStakeAtRisk
: Maps each round to the total amount of NRNs at risk.stakeAtRisk
: Maps each round and fighter ID to the amount of NRNs at risk for that fighter.amountLost
: Tracks the amount of NRNs swept from each address.Events:
ReclaimedStake
: Emitted when a fighter reclaims NRNs after a win.IncreasedStakeAtRisk
: Emitted when a fighter's stake at risk is increased.Constructor:
External Functions:
setNewRound
: Called by the RankedBattle contract to start a new round and sweep lost stakes to the treasury.reclaimNRN
: Allows fighters to reclaim their staked NRNs if they win a match.updateAtRiskRecords
: Updates the records when a fighter loses and has to place more NRNs at risk.getStakeAtRisk
: Returns the amount of NRNs at risk for a specific fighter in the current round.Private Functions:
_sweepLostStake
: Transfers the lost stake to the treasury contract.Gas Efficiency Perspective:
transfer
function is used for token transfers, which might consume more gas compared to using send
or call
in some cases. However, using transfer
is considered safer to prevent reentrancy attacks.Usability Perspective:
StakeAtRisk
contract.ReclaimedStake
and IncreasedStakeAtRisk
) provide transparency, allowing users to track stake changes.Scalability Perspective:
Interoperability Perspective:
Neuron
and RankedBattle
) through defined interfaces, making it interoperable with these contracts.Access Control:
require
statements to restrict certain functions (setNewRound
, reclaimNRN
, updateAtRiskRecords
) to be callable only by the RankedBattle
contract. This is a good security practice to prevent unauthorized access.Reentrancy:
_neuronInstance.transfer
function is assumed to be a simple ERC20 transfer, which should not be susceptible to reentrancy if implemented correctly.Integer Overflow/Underflow:
Token Transfer:
Neuron
contract's transfer
function returns a boolean indicating success. It is important that the Neuron
contract adheres to the ERC20 standard, which includes returning a boolean from the transfer
function.Error Handling:
Contract Upgrades:
Neuron
or RankedBattle
contracts, which means if there is a need to upgrade, a new contract must be deployed and the system must be migrated.Centralization Risks:
RankedBattle
contract for key operations, which could be a central point of failure or control. The trustworthiness of the RankedBattle
contract is crucial.Visibility of Functions:
_sweepLostStake
function is private and can only be called internally, which is appropriate for its use case.Gas Optimization:
SafeERC20
library from OpenZeppelin for token transfers, which handles token transfer errors more gracefully.Lack of Circuit Breakers:
VoltageManager
appears to be part of a gaming ecosystem, specifically for a game called AI Arena. The contract manages a system of "voltage," which seems to be a resource or currency within the game.
Imports: The contract imports GameItems.sol
, suggesting that it relies on functionality provided by the GameItems
contract.
Contract Documentation: The contract includes documentation using NatSpec comments, providing information about the contract's title, author, and purpose.
Events: It defines an event named VoltageRemaining
, which is emitted when the voltage amount is altered.
State Variables:
_ownerAddress
: Stores the address with owner privileges._gameItemsContractInstance
: Holds the instance of the GameItems
contract.Constructor: Initializes the contract by setting the owner address and instantiating the GameItems
contract.
External Functions:
transferOwnership
: Allows transferring ownership of the contract to a new address.adjustAdminAccess
: Allows the owner to adjust admin access for a user.adjustAllowedVoltageSpenders
: Allows admins to adjust whether an address is allowed to spend voltage.Public Functions:
useVoltageBattery
: Allows users to replenish their voltage by using a voltage battery.spendVoltage
: Allows users or allowed voltage spenders to spend voltage._replenishVoltage
: Internal function to replenish voltage for the owner._ownerAddress
) who has special privileges, such as transferring ownership and adjusting admin access.GameItems
contract that interacts with this contract, presumably to manage in-game items.allowedVoltageSpenders
), the time when an address's voltage will be replenished (ownerVoltageReplenishTime
), and the amount of voltage an address has (ownerVoltage
).GameItems
contract.Gas Efficiency:
useVoltageBattery
function burns a game item token, which may incur additional gas costs depending on the implementation of the burn
function in the GameItems
contract.Usability:
Interoperability:
GameItems.sol
) for functionality related to game items and burning tokens.GameItems
) to access its functions and data.VoltageManager
to integrate with the game items functionality seamlessly.Scalability:
Upgradability:
Decentralization:
Owner Privileges: The contract allows the owner to transfer ownership and adjust admin access. This is a centralized point of control, which could be a risk if the owner's address is compromised.
Admin Controls: The adjustAllowedVoltageSpenders
function allows admins to control who can spend voltage. If an admin account is compromised, the attacker could potentially allow malicious addresses to spend voltage.
Reentrancy: The useVoltageBattery
function interacts with an external contract (_gameItemsContractInstance.burn
) before updating the state (ownerVoltage[msg.sender] = 100;
). This could potentially be a reentrancy vulnerability if the burn
function in the GameItems
contract is not properly secured. However, since the state is updated after the external call and there are no further calls that could be influenced by the changed state within the same transaction, the risk is minimal.
Integer Underflow: The spendVoltage
function reduces the voltage of a spender without checking if the spender has enough voltage to cover the voltageSpent
. This could lead to an integer underflow where the voltage becomes very high if the spender does not have enough voltage. However, since Solidity 0.8.0 and above have built-in overflow/underflow checks, this risk is mitigated.
Timestamp Dependence: The contract uses block.timestamp
for the voltage replenishment logic. Miners have some influence over this value, which could potentially be exploited, although the risk is generally considered low.
Access Control: The spendVoltage
function allows a spender to spend voltage if they are the message sender or if the message sender is an allowed voltage spender. This logic could be confusing and might lead to unintended behavior if not properly understood by users.
Magic Numbers: The contract uses magic numbers like 100
for voltage replenishment and 0
for the item ID in the GameItems
contract. These should ideally be defined as constants or configurable parameters to improve code readability and maintainability.
Event Information: The VoltageRemaining
event is emitted after voltage is spent or replenished, but it does not include the amount spent or replenished. Including this information could be useful for tracking voltage changes.
Lack of Input Validation: There is no validation on the newOwnerAddress
in transferOwnership
or adminAddress
in adjustAdminAccess
. If either is set to the zero address, it could result in a loss of control over those functionalities.
Contract Upgradeability: The contract does not appear to be upgradeable. If any issues or vulnerabilities are found, they cannot be fixed without deploying a new contract and migrating the state.
60 hours
#0 - c4-pre-sort
2024-02-25T20:24:51Z
raymondfam marked the issue as sufficient quality report
#1 - c4-judge
2024-03-19T08:21:06Z
HickupHH3 marked the issue as grade-b