E1: AssetManagement.sol
Create a Solidity contract that demonstrates the use of different data types. Include at least one example of each: `uint`, `int`, `bool`, `address`, and `bytes`.
Exercise 1 Plan: Asset Management Contract
Project Overview: Design a Solidity contract for managing assets. Each asset should have various attributes demonstrating different data types.
Tasks:
Asset Registration: Create a function to register a new asset. The asset should have attributes like an ID (
uint
), valuation (int
), status (bool
), owner's address (address
), and a description (bytes
orstring
).Data Retrieval: Implement a function to retrieve the details of a registered asset using its ID.
Data Modification: Add functionality to update an asset's valuation and status.
Learning Outcome: This exercise will help you understand how to declare and manipulate different data types in Solidity.
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
contract AssetManagement {
/* structs */
struct Asset {
uint256 assetId; // Asset Id to be used as the identifier for the asset.
int assetValue; // Value of the asset, the owner of the asset will enter.
bool assetStatus; // Confirms the given asset is stored.
address assetOwner; // The address of the owner of the given asset.
string assetDescription; // Owners description of given asset.
}
/* mappings */
mapping(uint256 => Asset) private assets; // Mapping to give asset details using its assetId.
/* state variables */
uint256 public lastAssetId; // Counter to keep track of last asset Id.
bool public lastAssetStatus = false; // last asset status to update status automatically.
/* functions */
// A function to register new assets. Takes the asset value and description. Id, status, and owner updated automatically.
function assetRegistration(
int _assetValue,
string memory _assetDescription
) public {
if (_assetValue <= 0) {
// Throws an error if value is not above zero, otherwise sets status to true.
revert("Asset value must be above zero");
}
if (bytes(_assetDescription).length == 0) {
revert("Asset must have a description");
}
lastAssetId++; // Adds 1 to addressId counter
Asset memory newAsset = Asset(
lastAssetId,
_assetValue,
lastAssetStatus = true,
msg.sender,
_assetDescription
); // Creates a new asset
assets[lastAssetId] = newAsset; // Adds new asset to assets mapping, using the new asset Id.
}
// A function that updates exisitng assets.
function updateAsset(
uint256 _assetId,
int _assetValue,
string memory _assetDescription
) public {
if (assets[_assetId].assetStatus != true) {
revert("Asset does not exist");
}
require(
assets[_assetId].assetOwner == msg.sender,
"Caller is not asset owner"
);
Asset memory updatedAsset = Asset(
_assetId,
_assetValue,
true,
msg.sender,
_assetDescription
); // Creates an updated asset.
assets[_assetId] = updatedAsset; // Adds updated asset to asset mapping.
}
/* getter functions */
// Gets an asset using its assetId
function getAsset(uint256 assetId) public view returns (Asset memory) {
return assets[assetId];
}
}
Feedback
I prompt chatGpt for feedback as usual. I then took the criticisms and applied them to the smart contract. After which I prompted to review the final code.
Code Review
Strengths:
Struct Usage: The
Asset
struct is well-defined and effectively encapsulates the necessary attributes of an asset.Mapping for Asset Tracking: The mapping
assets
is correctly used to associate asset IDs withAsset
instances.Function Implementations:
assetRegistration
: It correctly creates and stores a new asset, including validation for the asset value.updateAsset
: This function now includes a check for the asset's existence and ownership, which adds a layer of security and ensures that only the owner can update the asset.
Error Handling: Using
revert
for validating asset existence andrequire
for ownership checks are good practices.Getter Function: The
getAsset
function is well implemented, allowing users to retrieve asset details by ID.
Areas for Improvement:
Redundant State Variable:
lastAssetStatus
remains unused and is redundant in its current form. Since assets are always registered with a status oftrue
, you might not need this variable at all.Asset Status Logic: In
assetRegistration
, the asset status is not explicitly set totrue
when a new asset is created. Given your struct definition, it would be clearer to set this explicitly, even though the default boolean value isfalse
.Direct Struct Update: In
updateAsset
, instead of creating a newAsset
instance, you could directly update the fields of the existing asset in the mapping. This can be more gas-efficient.Input Validation: While you check for negative asset values in
assetRegistration
, similar validation inupdateAsset
could be beneficial, especially if the asset value shouldn't decrease.Documentation and Comments: While your comments are helpful, expanding them to explain function behaviors and expected inputs would enhance code readability and maintenance.
Overall
The contract shows a good understanding of Solidity fundamentals, including struct usage, mappings, error handling, and function creation. It's well-suited for a practice project at your stage of learning. As you continue to develop in Solidity, focus on aspects like gas optimization, security considerations (like preventing overflow/underflow), and more nuanced state management.
You've made significant progress, and this contract is a solid step in your learning journey. Keep practicing and exploring more complex scenarios and functionalities!
Last updated