-
Notifications
You must be signed in to change notification settings - Fork 7
/
Copy pathEnergyTokenLib.sol
189 lines (163 loc) · 8.99 KB
/
EnergyTokenLib.sol
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.1;
import "./IEnergyToken.sol";
import "./ClaimVerifier.sol";
import "./AbstractDistributor.sol";
/**
* This library contains functionality that contains the EnergyToken contract.
*/
library EnergyTokenLib {
struct EnergyDocumentation {
IdentityContract documentingMeteringAuthority;
uint256 value;
bool corrected;
bool generated;
bool entered;
}
struct ForwardKindOfGenerationPlant {
IEnergyToken.TokenKind forwardKind;
bool set;
}
struct TokenFamilyProperties {
uint64 balancePeriod;
address generationPlant;
uint248 previousTokenFamilyBase;
}
// When stating criteria, make sure to set the value field correctly.
// EQUALITY COMPARISON VIA eq IS PERFORMED ON A BYTE LEVEL.
// THIS MEANS THAT NUMBERS IN CLAIMS ARE TREATED AS UTF-8 STRINGS.
// Example: If a field is supposed to be set to 300000000, you can use
// this JS code to compute the value of the value field to give to web3:
// '0x' + Buffer.from('300000000', 'utf8').toString('hex')
enum Operator {eq, leq, geq}
struct Criterion {
uint256 topicId;
string fieldName;
Operator operator;
bytes fieldValue;
}
// ########################
// # Public support functions
// ########################
/**
* | Bit (rtl) | Meaning |
* |-----------+-------------------------------------------------|
* | 0 | Genus (Generation-based 0; Consumption-based 1) |
* | 1 | Genus (Absolute 0; Relative 1) |
* | 2 | Family (Forwards 0; Certificates 1) |
* | 3 | Order (Simple forwards 0; Property Forwards 1) |
* | 4 | |
* | 5 | |
* | 6 | |
* | 7 | |
*
* Bits are zero unless specified otherwise.
*/
function tokenKind2Number(IEnergyToken.TokenKind _tokenKind) public pure returns (uint8 __number) {
if(_tokenKind == IEnergyToken.TokenKind.AbsoluteForward) {
return 0;
}
if(_tokenKind == IEnergyToken.TokenKind.GenerationBasedForward) {
return 2;
}
if(_tokenKind == IEnergyToken.TokenKind.ConsumptionBasedForward) {
return 3;
}
if(_tokenKind == IEnergyToken.TokenKind.Certificate) {
return 4;
}
if(_tokenKind == IEnergyToken.TokenKind.PropertyForward) {
return 8;
}
// Invalid TokenKind.
require(false, "Invalid TokenKind.");
}
function number2TokenKind(uint8 _number) public pure returns (IEnergyToken.TokenKind __tokenKind) {
if(_number == 0) {
return IEnergyToken.TokenKind.AbsoluteForward;
}
if(_number == 2) {
return IEnergyToken.TokenKind.GenerationBasedForward;
}
if(_number == 3) {
return IEnergyToken.TokenKind.ConsumptionBasedForward;
}
if(_number == 4) {
return IEnergyToken.TokenKind.Certificate;
}
if(_number == 8) {
return IEnergyToken.TokenKind.PropertyForward;
}
// Invalid number.
require(false, "Invalid number.");
}
function tokenKindFromTokenId(uint256 _id) public pure returns(IEnergyToken.TokenKind __tokenKind) {
__tokenKind = number2TokenKind(uint8(_id >> 248));
}
/**
* Checks all claims required for the particular given transfer regarding the sending side.
*/
function checkClaimsForTransferSending(IdentityContract marketAuthority, mapping(uint256 => AbstractDistributor) storage id2Distributor,
address payable _from, string memory _realWorldPlantId, uint256 _id) public view {
IEnergyToken.TokenKind tokenKind = tokenKindFromTokenId(_id);
uint256 balanceClaimId = ClaimVerifier.getClaimOfType(marketAuthority, _from, _realWorldPlantId, ClaimCommons.ClaimType.BalanceClaim);
require(balanceClaimId != 0, "Invalid BalanceClaim.");
require(ClaimVerifier.getClaimOfType(marketAuthority, _from, _realWorldPlantId, ClaimCommons.ClaimType.ExistenceClaim) != 0, "Invalid ExistenceClaim.");
require(ClaimVerifier.getClaimOfType(marketAuthority, _from, _realWorldPlantId, ClaimCommons.ClaimType.MeteringClaim) != 0, "Invalid MeteringClaim.");
if(tokenKind != IEnergyToken.TokenKind.Certificate) {
(, , address balanceAuthoritySender, , ,) = IdentityContract(_from).getClaim(balanceClaimId);
AbstractDistributor distributor = id2Distributor[_id];
require(ClaimVerifier.getClaimOfTypeByIssuer(marketAuthority, address(distributor), ClaimCommons.ClaimType.AcceptedDistributorClaim, balanceAuthoritySender) != 0, "Invalid AcceptedDistributorClaim.");
}
}
/**
* Checks all claims required for the particular given transfer regarding the reception side.
*/
function checkClaimsForTransferReception(IdentityContract marketAuthority, mapping(uint256 => AbstractDistributor) storage id2Distributor,
address payable _to, string memory _realWorldPlantId, uint256 _id) public view {
IEnergyToken.TokenKind tokenKind = tokenKindFromTokenId(_id);
uint256 balanceClaimId = ClaimVerifier.getClaimOfType(marketAuthority, _to, _realWorldPlantId, ClaimCommons.ClaimType.BalanceClaim);
require(balanceClaimId != 0, "Invalid BalanceClaim.");
require(ClaimVerifier.getClaimOfType(marketAuthority, _to, _realWorldPlantId, ClaimCommons.ClaimType.ExistenceClaim) != 0, "Invalid ExistenceClaim." );
require(ClaimVerifier.getClaimOfType(marketAuthority, _to, _realWorldPlantId, ClaimCommons.ClaimType.MeteringClaim) != 0, "Invalid MeteringClaim.");
if (tokenKind == IEnergyToken.TokenKind.ConsumptionBasedForward) {
require(ClaimVerifier.getClaimOfType(marketAuthority, _to, _realWorldPlantId, ClaimCommons.ClaimType.MaxPowerConsumptionClaim) != 0, "Invalid 1MaxPowerConsumptionClaim.");
}
if(tokenKind != IEnergyToken.TokenKind.Certificate) {
(, , address balanceAuthorityReceiver, , ,) = IdentityContract(_to).getClaim(balanceClaimId);
AbstractDistributor distributor = id2Distributor[_id];
require(ClaimVerifier.getClaimOfTypeByIssuer(marketAuthority, address(distributor), ClaimCommons.ClaimType.AcceptedDistributorClaim, balanceAuthorityReceiver) != 0,
"Invalid AcceptedDistributorClaim.");
}
}
// ########################
// # Internal functions
// ########################
function getPlantGenerationCapability(IdentityContract marketAuthority, address _plant, string memory _realWorldPlantId) public view returns (uint256 __maxGen) {
uint256 maxPowerGenerationClaimId = ClaimVerifier.getClaimOfType(marketAuthority, _plant, _realWorldPlantId, ClaimCommons.ClaimType.MaxPowerGenerationClaim);
(, , , , bytes memory claimData, ) = IdentityContract(_plant).getClaim(maxPowerGenerationClaimId);
__maxGen = ClaimVerifier.getUint256Field("maxGen", claimData);
}
function getPlantConsumptionCapability(IdentityContract marketAuthority, address _plant, string memory _realWorldPlantId) internal view returns (uint256 __maxCon) {
uint256 maxPowerConsumptionClaimId = ClaimVerifier.getClaimOfType(marketAuthority, _plant, _realWorldPlantId, ClaimCommons.ClaimType.MaxPowerConsumptionClaim);
if (maxPowerConsumptionClaimId == 0)
return 0;
(, , , , bytes memory claimData, ) = IdentityContract(_plant).getClaim(maxPowerConsumptionClaimId);
__maxCon = ClaimVerifier.getUint256Field("maxCon", claimData);
}
function setId2Distributor(mapping(uint256 => AbstractDistributor) storage id2Distributor, uint256 _id, AbstractDistributor _distributor) public {
if(id2Distributor[_id] == _distributor)
return;
if(id2Distributor[_id] != AbstractDistributor(address(0)))
require(false, "Distributor _id already used.");
id2Distributor[_id] = _distributor;
}
function setForwardKindOfGenerationPlant(mapping(uint64 => mapping(address => ForwardKindOfGenerationPlant)) storage forwardKindOfGenerationPlant, uint64 _balancePeriod, address _generationPlant, IEnergyToken.TokenKind _forwardKind) public {
if(!forwardKindOfGenerationPlant[_balancePeriod][_generationPlant].set) {
forwardKindOfGenerationPlant[_balancePeriod][_generationPlant].forwardKind = _forwardKind;
forwardKindOfGenerationPlant[_balancePeriod][_generationPlant].set = true;
} else {
require(_forwardKind == forwardKindOfGenerationPlant[_balancePeriod][_generationPlant].forwardKind, "Cannot set _forwardKind.");
}
}
}