Here's an example of how to create a basic bank in Solidity that allows users to deposit, withdraw, and check their balance. This example also includes some additional features such as interest calculation and ownership.
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
contract Bank {
address public owner;
uint256 public interestRate; // Interest rate in percentage (e.g., 5 means 5%)
mapping(address => uint256) private balances;
mapping(address => uint256) private depositTimestamps;
event Deposit(address indexed account, uint256 amount);
event Withdraw(address indexed account, uint256 amount);
event InterestRateChanged(uint256 newInterestRate);
constructor(uint256 initialInterestRate) {
owner = msg.sender;
interestRate = initialInterestRate;
}
modifier onlyOwner() {
require(msg.sender == owner, "Only the owner can perform this action");
_;
}
function setInterestRate(uint256 newInterestRate) external onlyOwner {
interestRate = newInterestRate;
emit InterestRateChanged(newInterestRate);
}
function deposit() external payable {
require(msg.value > 0, "Deposit amount must be greater than 0");
// Apply interest before updating balance
uint256 interest = calculateInterest(msg.sender);
balances[msg.sender] += interest;
balances[msg.sender] += msg.value;
depositTimestamps[msg.sender] = block.timestamp;
emit Deposit(msg.sender, msg.value);
}
function withdraw(uint256 amount) external {
require(amount <= balances[msg.sender], "Insufficient balance");
// Apply interest before withdrawing
uint256 interest = calculateInterest(msg.sender);
balances[msg.sender] += interest;
balances[msg.sender] -= amount;
depositTimestamps[msg.sender] = block.timestamp;
payable(msg.sender).transfer(amount);
emit Withdraw(msg.sender, amount);
}
function getBalance() external view returns (uint256) {
uint256 interest = calculateInterest(msg.sender);
return balances[msg.sender] + interest;
}
function calculateInterest(address account) internal view returns (uint256) {
uint256 timeElapsed = block.timestamp - depositTimestamps[account];
uint256 interest = (balances[account] * interestRate * timeElapsed) / (100 * 365 days);
return interest;
}
}
-
Owner: The contract has an
owner
who can set the interest rate. This is controlled through theonlyOwner
modifier. -
Interest Rate: The bank contract includes a simple interest calculation based on the time elapsed since the last deposit or withdrawal. The interest rate can be set by the owner.
-
Deposit and Withdrawal:
- Users can deposit Ether into the contract using the
deposit()
function. - Users can withdraw Ether using the
withdraw()
function, which checks if they have enough balance. - Before depositing or withdrawing, the contract calculates any interest that has accumulated and updates the user's balance accordingly.
- Users can deposit Ether into the contract using the
-
Events: The contract emits events for deposits, withdrawals, and interest rate changes, which can be useful for tracking and monitoring on the blockchain.
-
Interest Calculation: Interest is calculated based on the time elapsed since the user's last transaction. It uses a simple interest formula, assuming the rate is annualized.
-
Compile the Contract: Use the Solidity compiler (e.g.,
solc
) or an IDE like Remix to compile the contract. -
Deploy: Deploy the contract on an Ethereum test network or the main network using tools like Remix, Truffle, or Hardhat.
-
Interact with the Contract: Once deployed, users can interact with the contract by depositing Ether, withdrawing Ether, and checking their balance, which will reflect any interest accrued.
- Security: Ensure proper security measures, such as reentrancy guards (using
nonReentrant
from OpenZeppelin) and validations on inputs. - Interest Calculation: This example uses a simple interest model. Depending on your needs, you might want to implement a more sophisticated interest mechanism.
- Testing: Thoroughly test the contract, particularly the interest calculations, to ensure they work as expected over various time periods.