This document provides comprehensive API documentation for the PiggyBank smart contract, including all functions, events, and usage patterns.
The PiggyBank contract is a decentralized time-locked savings solution that enforces disciplined ETH deposits. Key features include:
- Time-locked withdrawals: Funds can only be withdrawn after a specified unlock time
- Multi-user deposits: Anyone can deposit ETH into the contract
- Single-owner withdrawals: Only the contract owner can withdraw funds
- Pause functionality: Emergency pause/unpause for security incidents
- Ownership transfer: Ability to transfer contract ownership
constructor(uint256 _unlockTime) payableParameters:
_unlockTime(uint256): Timestamp (in seconds) when the contract becomes unlocked
Description: Initializes the PiggyBank contract with the specified unlock time. The deployer becomes the initial owner. Can optionally receive ETH during deployment.
Events Emitted:
OwnershipTransferred(address(0), msg.sender)
function deposit() external payableDescription: Allows anyone to deposit ETH into the contract. The function is payable and accepts any positive ETH amount.
Requirements:
- Contract must not be paused
- Deposit amount must be > 0
Events Emitted:
Deposited(msg.sender, msg.value)
Error Conditions:
Contract is paused: If called when contract is pausedMust deposit something: If deposit amount is 0
Example Usage:
// Using ethers.js
await contract.deposit({ value: ethers.utils.parseEther("1.0") });function withdraw() externalDescription: Allows the contract owner to withdraw all ETH from the contract after the unlock time has passed.
Requirements:
- Contract must not be paused
- Current timestamp must be >= unlockTime
- Caller must be the contract owner
Events Emitted:
Withdrawn(msg.sender, amount)
Error Conditions:
Contract is paused: If called when contract is pausedPiggyBank: Still locked: If called before unlock timePiggyBank: Not owner: If called by non-ownerTransfer failed: If ETH transfer fails
Example Usage:
// Using ethers.js
await contract.withdraw();function getBalance() external view returns (uint256)Returns:
uint256: Current ETH balance of the contract in wei
Description: Returns the current ETH balance held by the contract.
Example Usage:
const balance = await contract.getBalance();
console.log(`Contract balance: ${ethers.utils.formatEther(balance)} ETH`);function getUnlockTime() external view returns (uint256)Returns:
uint256: Unlock timestamp in seconds since epoch
Description: Returns the timestamp when the contract becomes unlocked for withdrawals.
Example Usage:
const unlockTime = await contract.getUnlockTime();
console.log(`Unlock time: ${new Date(unlockTime * 1000)}`);function isUnlocked() external view returns (bool)Returns:
bool: true if contract is unlocked, false otherwise
Description: Returns whether the current timestamp is >= the unlock time.
Example Usage:
const isUnlocked = await contract.isUnlocked();
console.log(`Contract is ${isUnlocked ? 'unlocked' : 'locked'}`);function owner() external view returns (address)Returns:
address: Current owner address
Description: Returns the address of the current contract owner.
Example Usage:
const owner = await contract.owner();
console.log(`Contract owner: ${owner}`);function paused() external view returns (bool)Returns:
bool: true if contract is paused, false otherwise
Description: Returns whether the contract is currently paused.
Example Usage:
const isPaused = await contract.paused();
console.log(`Contract is ${isPaused ? 'paused' : 'active'}`);function pause() externalDescription: Pauses the contract, disabling deposits and withdrawals. Can only be called by the owner when the contract is not already paused.
Requirements:
- Caller must be the contract owner
- Contract must not already be paused
Events Emitted:
Paused(msg.sender)
Error Conditions:
Not owner: If called by non-ownerContract is not paused: If contract is already paused
Example Usage:
await contract.pause();function unpause() externalDescription: Unpauses the contract, re-enabling deposits and withdrawals. Can only be called by the owner when the contract is paused.
Requirements:
- Caller must be the contract owner
- Contract must be paused
Events Emitted:
Unpaused(msg.sender)
Error Conditions:
Not owner: If called by non-ownerContract is not paused: If contract is not paused
Example Usage:
await contract.unpause();function transferOwnership(address newOwner) externalParameters:
newOwner(address): Address to transfer ownership to
Description: Transfers ownership of the contract to a new address.
Requirements:
- Caller must be the current owner
- newOwner must not be the zero address
Events Emitted:
OwnershipTransferred(owner, newOwner)
Error Conditions:
Not owner: If called by non-ownerNew owner is zero address: If newOwner is address(0)
Example Usage:
await contract.transferOwnership("0xNewOwnerAddress");event Deposited(address indexed depositor, uint256 amount)Parameters:
depositor(address): Address that made the depositamount(uint256): Amount of ETH deposited in wei
Description: Emitted when ETH is successfully deposited into the contract.
event Withdrawn(address indexed withdrawer, uint256 amount)Parameters:
withdrawer(address): Address that initiated the withdrawalamount(uint256): Amount of ETH withdrawn in wei
Description: Emitted when ETH is successfully withdrawn from the contract.
event Paused(address account)Parameters:
account(address): Address that paused the contract
Description: Emitted when the contract is paused by the owner.
event Unpaused(address account)Parameters:
account(address): Address that unpaused the contract
Description: Emitted when the contract is unpaused by the owner.
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner)Parameters:
previousOwner(address): Previous owner addressnewOwner(address): New owner address
Description: Emitted when ownership of the contract is transferred.
The contract uses descriptive error messages for common failure conditions:
| Error Message | Condition |
|---|---|
Contract is paused |
Function called when contract is paused |
Contract is not paused |
Pause/unpause function called in wrong state |
Must deposit something |
Deposit called with 0 ETH |
PiggyBank: Still locked |
Withdraw called before unlock time |
PiggyBank: Not owner |
Owner-only function called by non-owner |
New owner is zero address |
Transfer ownership called with zero address |
Not owner |
Owner-only function called by non-owner |
Transfer failed |
ETH transfer fails during withdrawal |
// Connect to contract
const contract = new ethers.Contract(contractAddress, abi, signer);
// 1. Check contract status
const [balance, unlockTime, isUnlocked, owner] = await Promise.all([
contract.getBalance(),
contract.getUnlockTime(),
contract.isUnlocked(),
contract.owner()
]);
console.log(`Contract Status:
Balance: ${ethers.utils.formatEther(balance)} ETH
Unlock Time: ${new Date(unlockTime * 1000)}
Is Unlocked: ${isUnlocked}
Owner: ${owner}
`);
// 2. Deposit ETH
await contract.deposit({ value: ethers.utils.parseEther("1.0") });
console.log("Deposit successful!");
// 3. Check if unlocked and withdraw (if owner)
if (isUnlocked && (await signer.getAddress()) === owner) {
await contract.withdraw();
console.log("Withdrawal successful!");
}// Pause the contract (owner only)
await contract.pause();
console.log("Contract paused");
// Transfer ownership
const newOwner = "0xNewOwnerAddress";
await contract.transferOwnership(newOwner);
console.log(`Ownership transferred to ${newOwner}`);
// Unpause the contract
await contract.unpause();
console.log("Contract unpaused");- Always verify contract address: Ensure you're interacting with the correct contract address
- Check contract state: Verify
pausedstatus before making deposits or withdrawals - Validate unlock time: Confirm
isUnlocked()before attempting withdrawals - Use proper error handling: Handle transaction reverts gracefully in your frontend
- Batch view calls: Use multicall patterns to fetch multiple view function results in one call
- Event listening: Use event listeners for real-time updates instead of polling
- Proper transaction monitoring: Track transaction states (pending, success, failure)
- Test with small amounts: Always test with small ETH amounts first
- Verify unlock time: Ensure the unlock time is set correctly for your use case
- Test pause functionality: Verify that pause/unpause works as expected
- Test ownership transfer: Confirm ownership transfer works properly
This comprehensive API documentation should help developers understand and integrate with the PiggyBank smart contract effectively.