1+ pragma solidity ^ 0.5.10 ;
2+
3+ import "@openzeppelin/contracts/token/ERC20/ERC20.sol " ;
4+ // import "@hq20/contracts/contracts/access/Whitelist.sol";
5+ import "./../../../access/Whitelist.sol " ;
6+
7+
8+ /**
9+ * @title Energy Market
10+ * @notice Implements a simple energy market, using ERC20 and Whitelist.
11+ * ERC20 is used to enable payments from the consumers to the distribution
12+ * network, represented by this contract, and from the distribution network
13+ * to the producers. Whitelist is used to keep a list of compliant smart
14+ * meters that communicate the production and consumption of energy.
15+ */
16+ contract EnergyMarket is ERC20 , Whitelist {
17+
18+ event EnergyProduced (address producer , uint256 time );
19+ event EnergyConsumed (address consumer , uint256 time );
20+
21+ // uint128 is used here to facilitate the price formula
22+ // Casting between uint128 and int256 never overflows
23+ // int256(uint128) - int256(uint128) never overflows
24+ mapping (uint256 => uint128 ) public consumption;
25+ mapping (uint256 => uint128 ) public production;
26+ uint128 public basePrice;
27+
28+ /**
29+ * @dev The constructor initializes the underlying currency token and the
30+ * smart meter whitelist. The constructor also mints the requested amount
31+ * of the underlying currency token to fund the network load. Also sets the
32+ * maximum energy price, used for calculating prices.
33+ */
34+ constructor (uint256 _initialSupply , uint128 _basePrice )
35+ public
36+ ERC20 ()
37+ Whitelist ()
38+ {
39+ _mint (address (this ), _initialSupply);
40+ basePrice = _basePrice;
41+ }
42+
43+ /**
44+ * @dev The production price for each time slot.
45+ */
46+ function getProductionPrice (uint256 _time ) public view returns (uint256 ) {
47+ return uint256 (
48+ max (
49+ 0 ,
50+ int256 (basePrice) *
51+ (3 + safeSub (production[_time], consumption[_time]))
52+ )
53+ );
54+ }
55+
56+ /**
57+ * @dev The consumption price for each time slot
58+ */
59+ function getConsumptionPrice (uint256 _time ) public view returns (uint256 ) {
60+ return uint256 (
61+ max (
62+ 0 ,
63+ int256 (basePrice) *
64+ (3 + safeSub (consumption[_time], production[_time]))
65+ )
66+ );
67+ }
68+
69+ /**
70+ * @dev Add one energy unit to the distribution network at the specified
71+ * time and be paid the production price. Only whitelisted smart meters can
72+ * call this function.
73+ */
74+ function produce (uint256 _time ) public {
75+ require (isMember (msg .sender ), "Unknown meter. " );
76+ this .transfer (
77+ msg .sender ,
78+ getProductionPrice (_time)
79+ );
80+ production[_time] = production[_time] + 1 ;
81+ emit EnergyProduced (msg .sender , _time);
82+ }
83+
84+ /**
85+ * @dev Take one energy unit from the distribution network at the specified
86+ * time by paying the consumption price. Only whitelisted smart meters can
87+ * call this function.
88+ */
89+ function consume (uint256 _time ) public {
90+ require (isMember (msg .sender ), "Unknown meter. " );
91+ this .transferFrom (
92+ msg .sender ,
93+ address (this ),
94+ getConsumptionPrice (_time)
95+ );
96+ consumption[_time] = consumption[_time] + 1 ;
97+ emit EnergyConsumed (msg .sender , _time);
98+ }
99+
100+ /**
101+ * @dev Returns the largest of two numbers.
102+ */
103+ function max (int256 a , int256 b ) internal pure returns (int256 ) {
104+ return a >= b ? a : b;
105+ }
106+
107+ /**
108+ * @dev Substracts b from a using types safely casting from uint128 to int256.
109+ */
110+ function safeSub (uint128 a , uint128 b ) internal pure returns (int256 ) {
111+ return int256 (a) - int256 (b);
112+ }
113+ }
0 commit comments