Skip to content

This smart contract allows a specified beneficiary to withdraw its balance when the owner has not checked in for at least a full day. This smart contract, as well as its tests, was developed with Hardhat.

License

Notifications You must be signed in to change notification settings

allenlooplee/open-piggy-legacy

Repository files navigation

Open Piggy Legacy

This smart contract allows a specified beneficiary to withdraw its balance when the owner has not checked in for at least a full day. This smart contract, as well as its tests, was developed with Hardhat.

Contract Design

Use Cases

  1. Lump Sum Legacy: The owner deploys the smart contract with the initial funds and a beneficiary address. They then regularly check in every day. The beneficiary can view the balance and the owner's last check-in time. If the owner misses a check-in, the beneficiary can withdraw the funds the next day.
  2. Regular Savings Legacy: The owner deploys the smart contract with a beneficiary address. They regularly check in daily, with an additional fund transfer on Mondays. The beneficiary can view the balance and the owner's last check-in time. If the owner misses a check-in, the beneficiary can withdraw the funds the next day.
  3. Legacy with Withdrawal Delay Period: The owner deploys the smart contract with the initial funds, a beneficiary address, and a one-day withdrawal delay period. They regularly check in every day. One day, they miss a check-in. The beneficiary can withdraw the funds the day after the next day.

Contract Members

  1. owner public variable: The person or entity that deploys the smart contract and initially funds it.
  2. beneficiary public variable: The person or entity designated by the owner as eligible to inherit the funds.
  3. withdrawalDelayPeriod private variable: This variable specifies the time period (in seconds) that the beneficiary must wait before withdrawing the balance after the owner has not checked in within a day. If set to 0, the beneficiary can withdraw at 00:00:00 on the day after the first missed check-in date. Otherwise, the beneficiary must wait for the specified number of seconds starting from 00:00:00 on the day after the first missed check-in date.
  4. lastCheckInTime public variable: The timestamp of the last check-in. This is a Unix timestamp.
  5. isActive public variable: This boolean variable is initially set to true and remains true until the owner calls the terminate function to terminate the smart contract. All other functions in the smart contract require this variable to be true to execute successfully.
  6. checkIn external payable function: This function allows the owner to check in every day, updating the lastCheckInTime variable and optionally sending additional funds.
  7. canWithdraw public view function: This function returns whether the beneficiary is allowed to withdraw the balance, considering the current time in relation to the lastCheckInTime and the withdrawalDelayPeriod. This is a view function that allows the beneficiary to determine if they can withdraw without incurring gas costs.
  8. withdraw external function: This function allows the beneficiary to retrieve the balance of the smart contract if canWithdraw function returns true, indicating that the owner has not checked in for at least a full day.
  9. terminate external function: This function allows the owner to terminate the contract at any time, revoking the beneficiary's inheritance eligibility and returning the remaining balance to the owner.

References

  1. external vs public best practices
  2. What is the time zone of the Ethereum block chain?
  3. How do you work with Date and time on Ethereum platform
  4. Units and Globally Available Variables
  5. What is selfdestruct in Solidity?
  6. How to Understand tx.origin and msg.sender in Solidity

Unit Testing

Test Cases

To run the tests, navigate to your project folder in the terminal and execute npm run test.

  1. Deployment
    • It should deploy and set the state when the owner deploys the smart contract.
      • Expect the owner variable to be the address of the owner.
      • Expect the beneficiary variable to be the address of the beneficiary.
      • Expect the lastCheckInTime variable to match today's date.
      • Expect the canWithdraw function to return false.
      • Expect the balance of the smart contract to be the amount sent by the owner initially.
  2. Checking in
    • It should check in tomorrow when the owner calls the checkIn function tomorrow (T + 1).
      • Expect the lastCheckInTime variable to match tomorrow's date (T + 1).
      • Expect the canWithdraw function to return false.
      • Expect the balance of the smart contract to be the same as what was there beforehand.
    • It should check in and receive the funds tomorrow when the owner calls the checkIn function with new funds tomorrow (T + 1).
      • Expect the lastCheckInTime variable to match tomorrow's date (T + 1).
      • Expect the canWithdraw function to return false.
      • Expect the balance of the smart contract to be the same as what was there beforehand plus any new funds that have been received.
    • It should revert when non-owner checks in.
      • Expect the call to the checkIn function to be reverted.
      • Expect the lastCheckInTime variable to be unchanged.
      • Expect the balance of the smart contract to be unchanged.
  3. Withdrawal
    • It should withdraw the balance of the smart contract the day after tomorrow (T + 2) when the owner misses a check-in tomorrow (T + 1).
      • Expect the lastCheckInTime variable to match today's date (T).
      • Expect the canWithdraw function to return true.
      • Expect the balance of the smart contract to be added to the balance of beneficiary.
      • Expect the balance of the smart contract to be zero.
    • It should revert the withdrawal tomorrow (T + 1) when the owner checks in today (T).
      • Expect the lastCheckInTime variable to match today's date (T).
      • Expect the canWithdraw function to return false.
      • Expect the call to the withdraw function to be reverted.
      • Expect the balance of the smart contract to be unchanged.
    • It should withdraw the balance of the smart contract two days after tomorrow (T + 3) when the owner misses a check-in tomorrow (T + 1) with a one-day withdrawal delay period.
      • Expect the lastCheckInTime variable to match today's date (T).
      • Expect the canWithdraw function to return true.
      • Expect the balance of the smart contract to be added to the balance of beneficiary.
      • Expect the balance of the smart contract to be zero.
    • It should revert the withdrawal the day after tomorrow (T + 2) when the owner misses a check-in tomorrow (T + 1) with a one-day withdrawal delay period.
      • Expect the lastCheckInTime variable to match today's date (T).
      • Expect the canWithdraw function to return false.
      • Expect the call to the withdraw function to be reverted.
      • Expect the balance of the smart contract to be unchanged.
    • It should revert the withdrawal two days after tomorrow (T + 3) when the owner misses a check-in tomorrow (T + 1) but re-checks in the day after tomorrow (T + 2) with a one-day withdrawal delay period.
      • Expect the lastCheckInTime variable to match today's date (T).
      • Expect the lastCheckInTime variable after re-checking in to match the day after tomorrow's date (T + 2).
      • Expect the canWithdraw function to return false.
      • Expect the call to the withdraw function to be reverted.
      • Expect the balance of the smart contract to be unchanged.
    • It should revert when non-beneficiary withdraws.
      • Expect the call to the withdraw function to be reverted.
      • Expect the balance of the smart contract to be unchanged.
  4. Termination
    • It should revoke the smart contract when the owner terminates it.
      • Expect the balance of the smart contract to be added to the balance of owner.
      • Expect the isActive variable to be false.
      • Expect the balance of the smart contract to be zero.
      • Expect the call to the checkIn function by the owner to be reverted.
      • Expect the call to the terminate function by the owner to be reverted.
      • Expect the call to the canWithdraw function by the beneficiary to be reverted.
      • Expect the call to the withdraw function by the beneficiary to be reverted.
    • It should revert when non-owner terminates it.
      • Expect the call to the terminate function to be reverted.
      • Expect the isActive variable to be true.
      • Expect the balance of the smart contract to be unchanged.

Implementation Considerations

  1. Use loadFixture to maintain the state of the network before each test.
  2. Use Luxon to convert Unix timestamp to UTC DateTime.
  3. Use ethers.provider.getBalance() to get the current balance of the owner and the beneficiary.
  4. Use time.increaseTo() from Hardhat Network Helpers to move time forward.
  5. Use .to.be.revertedWith() to assert a revert happens with the specified message.
  6. Use .to.changeEtherBalance() to assert a balance change on the specified account.
  7. Use .connect() to call a function with a different account.

References

  1. Time-dependent tests with Hardhat?
  2. Testing contracts
  3. Chai-Luxon
  4. Hardhat Chai Matchers

Deployment

Hardhat Ignition

When deploying the PiggyLegacy contract with Hardhat Ignition, follow the below steps:

  1. Open ./ignition/modules/PiggyLegacy.js file.
  2. Change the values of beneficiary, withdrawalPeriod and initialAmount in the module and save the changes.
  3. Navigate to your project folder in the terminal and execute npm run deploy.

This will deploy the smart contract to an in-memory instance of Hardhat Network on your local machine.

To deploy the smart contract to a live network, follow Hardhat documentation or simply paste the code into Remix IDE for easy deployment.

References

  1. Quick start
  2. Deploying your contracts
  3. Deploying to a live network
  4. Configuration variables

About

This smart contract allows a specified beneficiary to withdraw its balance when the owner has not checked in for at least a full day. This smart contract, as well as its tests, was developed with Hardhat.

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published