VPP dApp v0.2.0 is a sample implementation of a simplified decentralized virtual power plant. It is powered by smart contracts governing fund deposits, energy-trading/arbitrage, and settlement in the form of investor dividends. It - allows users to deposit eth into a pooled group investment fund; creates the ability to manage battery assets via purchases using pooled funds; determines energy transactions based on market pricing; distributes dividends based on fund performance. This implementation also includes a sample web interface to connect with the smart contracts.
VPP-dApp is a Truffle project that contains all necessary contract, library, migration and test files. To start the demo, start the command line:
-
Clone the repo to your directory.
$ git clone https://github.com/yan-man/virtual-power-plant.git
-
a) In a separate terminal, start ganache development blockchain on port 7545. Create 10 funded accounts.
Terminal 2: $ ganache-cli -p 7545
OR
b) start ganache application (in MacOS)
-
In the first terminal, navigate to the project directory. Test the contract functions via
JavaScript
tests.Terminal 1: $ truffle test
-
Migrate and compile the Truffle contract to generate the ABI and deploy the contract to the dev blockchain.
$ truffle migrate --reset
-
Make sure
MetaMask
is installed. OpenMetaMask
in your Chrome browser and set the network connection toCustom RPC
and the target RPC url tohttp://127.0.0.1:7545
to access theganache-cli
accounts. Only one address is required to test the dApp.
-
Log in to
MetaMask
viaimport using Secret Recovery Phrase
- copy seed phrase from Ganache. -
Start the front end server and navigate to
http://localhost:3000/
:$ npm run dev
The first development account is used to deploy the parent contract VirtualPowerPlant.sol
. Only one development account is required for the demo.
To test the dApp, follow instructions on the http://localhost:3000/
page.
Metamask
prompt should open. Allow access on your account. If successful, contract and user address details should be updated on the page. Confirm that "My Address" and "My Balance" fields match address and balance shown inMetamask
.
- Start by investing some amount of
eth
(around ~5 Eth should be sufficient) into the battery. Fill in field in Step 1. AcceptMetamask
prompt; if successful, "Total Amount Invested" and "Remaining Amount Left" should be updated.
- Once the transaction has been accepted, you can start adding batteries to the fleet. Sample battery options are listed and available, select a few to add by clicking
Add to array
under each battery panel. "Number of Batteries" field should be incremented; new carousel should pop up with green background showing newly add battery in fleet.
Install the following packages. The dApp was developed in the following versions in a Ubuntu64 18.04 environment.
- Solidity v0.5.0 (solc-js)
- Truffle v5.0.2 (core: 5.0.2) & web3.js v1.6.1
- Ganache CLI v6.2.3 (ganache-core: 2.3.1)
- npm v3.5.2 / Node v8.10.0
- React v17.x & next.js v12.x
- MetaMask (in browser)
If contracts have been compiled and migrated properly, there should be JSON contract files in the /build/contracts/
directory.
- In JavaScript, you can access contracts via
web3.js
implementation. Load theweb3Contracts.js
class:
import web3Contracts from "../api/web3Contracts";
- Initialize
web3Contracts
instance, connect toMetamask
as provider, and initialize smart contracts withTruffle
:
const Web3Contracts = new web3Contracts();
await Web3Contracts.init();
You can then begin to interact with its contract functions directly via JS. Make sure there are sufficient funds invested before adding batteries to the array.
- Contract methods can be accessed with:
Web3Contracts.contracts.VirtualPowerPlant.deployed.someFunction(
parameter1,
parameter2,
...{
from: "0xuserAddress",
value: Web3Contracts.web3.utils.toWei(amount, "ether"),
}
);
Metamask
account addresses can be found in:Web3Contracts.accounts
Otherwise, interact with the dApp via the app, which will allow you to invest funds, and add batteries to fleet.
admin
users are the only ones allowed to perform crucial functions. The initial account that deploys VirtualPowerPlant.sol
is the owner
and the first admin
, and is able to set up other admins
. admins
are responsible for performing two main functions:
- Managing batteries: This consists of adding batteries to the fleet and decommissioning them when necessary.
- Managing investments: triggering dividends to pay investors, and distributing the dividends into withdrawal pools for investors to withdraw from.
Investors are composed of any other accounts that want to contribute eth to the fund. Anyone can be an investor, and investors are eligible for dividends that are paid in proportion to the amount of funds invested.
-
A very simple threshold was used to determine whether energy should be purchased or sold, ie if prices were more expensive than the battery's threshold, energy was sold to the grid. Otherwise, energy was purchased.
-
The real time energy price was hardcoded to simplify the transaction process. Ideally, it would be connected to an outside Oracle to report the actual, fluctuating real time energy rate.
-
The actual energy transaction was simplified. Whereas in reality, a separate contract might have to be implemented to manage energy transactions between the grid and outside suppliers, in this dApp energy was assumed to be traded instantaneously and available immediately.
-
Batteries were assumed to have charged instantaneously, with minimal restrictions on battery performance. In reality, charge frequency and other factors would add vastly more constraints.
-
Decisions on whether to purchase or sell energy were based on a simple threshold. If energy prices are expensive (ie greater than the battery's price threshold), sell energy to the grid to make a profit. Otherwise purchase energy to charge the battery.
-
isAdmin
: check address is an admin user -
setAdmin
: set admin to active or inactive -
toggleContractActive
: to implement circuit breaker design -
addBattery
: add Battery struct to fleet, composed of multiple battery characteristics. Battery -
decommissionBattery
: render battery inactive (no charging/discharging) -
chargeBattery
: charge battery, ie alter battery state based on amount charged/discharged -
changeBatteryThreshold
: alter battery threshold characteristics (affects decision making on energy purchases)
Battery info getter functions:
getRelevantBatteryInfo
getBatteryChargeRate
getBatteryMapIndex
updateRemainingInvestment
: update amount of remaining eth in fundinvestMoney
: ensure Eth is attached when calling this functiontriggerDividend
: admins can implement a dividend to send payment to investorswithdraw
: for investors to retrieve their dividend withdrawalgetInvestorInvestment
: getter function to retrieve investment amount for particular investor
checkBatteryEnergy
: loop over batches of batteries, check transaction circumstances for each. Transact energy as required, update the investment fund with profits/energy purchases.getRealTimeEnergyPrice
: hardcoded for this demo. Retrieves the current energy rate on the real time market.energyDecisionAlgorithm
: determines whether to purchase energy or sell it to the grid, based on a simple threshold.
...check deployed contract addresses are correct
: Check deployment of the parentVirtualPowerPlant.sol
contract, which in turn deploysBatteryEnergy.sol
andBatteryInvestment.sol
contracts....check BatteryInvestment public vars are set properly
...check BatteryInvestment updateRemainingInvestment
...check BatteryInvestment investMoney & getInvestorInvestment
...check BatteryInvestment triggerDividend
...check BatteryInvestment addPendingWithdrawals
...check BatteryInvestment withdraw
- SafeMath: Use battle tested math functions to avoid overflow errors, etc
- Math: Other basic math functions
- Ownable: Inherit ownership properties
Although customers typically pay a flat energy rate for electricity throughout the day, energy prices in actuality fluctuate drastically depending on real time aggregate energy demand. Due to the unpredictability of real time demand, along with insufficient implementation and availability of large scale energy storage resources, energy response must be managed on a minute by minute basis. Electricity generators respond by activating so-called "Peaker" plants, which are convenient for short term energy generation but are also typically the most environmentally damaging.
With the increasing availability of flexible energy resources such as batteries, energy can be stored when real time energy demand is low, and discharged to the grid when demand, and prices, are high. This serves to effectively smooth the aggregated energy demand throughout the day, improving grid efficiency and stability as well as creating profit through energy trading.
However, given the high number of transactions per second (TPS) required to trade electricity, which is typically produced and consumed instantly, many blockchain networks are insufficient to handle such load - particularly for small quantities given high gas fees. Perhaps large entities, trading maybe MWh blocks for futures, would be open to using blockchain technologies to transact.
The Battery Investment smart contract retains utility to manage pooled funds and trigger dividends, and the Virtual Power Plant contract effectively manages a ledger of a fleet of batteries. However, the Battery Energy contract is impractical at the moment as a fully decentralized component.
-
Oraclize: There are two obvious ways to improve this contract implementation -
-
Run energy transactions every hour or on a regular time interval. This removes the manual component of transactions. This requires implementation of a regularly scheduled CRON job.
-
Find the actual real time energy price during each transaction. Currently this energy rate was hard coded to a sample value. Pulling real rates requires oracle data off-chain.
-
-
Energy optimization algorithm: A very basic threshold was used to determine energy transactions - whether energy prices had reached a certain prescribed threshold. In reality, energy prices in the context of the market demand and recent history are more important. A more robust optimization algorithm is required for practical use.
-
Battery modeling: battery characteristics were simplified and modeled in an elementary manner. Charging/discharging was assumed to be instantaneous, and internal battery chemistry and hardware constraints were not accounted for.
-
Energy trading: energy was assumed to have just appeared out of thin air. The actual energy transaction needs to be implemented to allow for trading back and forth between grid and battery.
- expand testing for other contracts; add testing for more BatteryInvestment functionality
- extend SafeMath to all contracts
- refactor react front end; improve UI/UX design
© 2022 Yan Man