Skip to content
This repository was archived by the owner on Nov 20, 2024. It is now read-only.

Commit fcbcf5e

Browse files
committed
first draft HIP0
1 parent 72ce159 commit fcbcf5e

35 files changed

Lines changed: 12838 additions & 172 deletions

contracts/mock/HermezV2.sol renamed to contracts/hermez/future_versions/HermezV2.sol

Lines changed: 45 additions & 162 deletions
Large diffs are not rendered by default.
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
// SPDX-License-Identifier: AGPL-3.0
2+
3+
pragma solidity ^0.6.12;
4+
5+
/**
6+
* @dev Define interface verifier
7+
*/
8+
interface VerifierRollupInterface {
9+
function verifyProof(
10+
uint256[2] calldata proofA,
11+
uint256[2][2] calldata proofB,
12+
uint256[2] calldata proofC,
13+
uint256[1] calldata input
14+
) external view returns (bool);
15+
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
// SPDX-License-Identifier: AGPL-3.0
2+
3+
pragma solidity ^0.6.12;
4+
5+
/**
6+
* @dev Define interface verifier
7+
*/
8+
interface VerifierWithdrawInterface {
9+
function verifyProof(
10+
uint256[2] calldata proofA,
11+
uint256[2][2] calldata proofB,
12+
uint256[2] calldata proofC,
13+
uint256[1] calldata input
14+
) external view returns (bool);
15+
}
Lines changed: 319 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,319 @@
1+
// SPDX-License-Identifier: AGPL-3.0
2+
3+
pragma solidity ^0.6.12;
4+
5+
import "@openzeppelin/contracts-upgradeable/proxy/Initializable.sol";
6+
7+
/**
8+
* @dev Rollup helper functions
9+
*/
10+
contract HermezHelpersV2 is Initializable {
11+
uint256 private constant _WORD_SIZE = 32;
12+
13+
// bytes32 public constant EIP712DOMAIN_HASH =
14+
// keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)")
15+
bytes32
16+
public constant EIP712DOMAIN_HASH = 0x8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f;
17+
// bytes32 public constant NAME_HASH =
18+
// keccak256("Hermez Network")
19+
bytes32
20+
public constant NAME_HASH = 0xbe287413178bfeddef8d9753ad4be825ae998706a6dabff23978b59dccaea0ad;
21+
// bytes32 public constant VERSION_HASH =
22+
// keccak256("1")
23+
bytes32
24+
public constant VERSION_HASH = 0xc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc6;
25+
// bytes32 public constant AUTHORISE_TYPEHASH =
26+
// keccak256("Authorise(string Provider,string Authorisation,bytes32 BJJKey)");
27+
bytes32
28+
public constant AUTHORISE_TYPEHASH = 0xafd642c6a37a2e6887dc4ad5142f84197828a904e53d3204ecb1100329231eaa;
29+
// bytes32 public constant HERMEZ_NETWORK_HASH = keccak256(bytes("Hermez Network")),
30+
bytes32
31+
public constant HERMEZ_NETWORK_HASH = 0xbe287413178bfeddef8d9753ad4be825ae998706a6dabff23978b59dccaea0ad;
32+
// bytes32 public constant ACCOUNT_CREATION_HASH = keccak256(bytes("Account creation")),
33+
bytes32
34+
public constant ACCOUNT_CREATION_HASH = 0xff946cf82975b1a2b6e6d28c9a76a4b8d7a1fd0592b785cb92771933310f9ee7;
35+
36+
/**
37+
* @dev Decode half floating precision.
38+
* Max value encoded with this codification: 0x1f8def8800cca870c773f6eb4d980000000 (aprox 137 bits)
39+
* @param float Float half precision encode number
40+
* @return Decoded floating half precision
41+
*/
42+
function _float2Fix(uint40 float) internal pure returns (uint256) {
43+
uint256 m = float & 0x7FFFFFFFF;
44+
uint256 e = float >> 35;
45+
46+
// never overflow, max "e" value is 32
47+
uint256 exp = 10**e;
48+
49+
// never overflow, max "fix" value is 1023 * 10^32
50+
uint256 fix = m * exp;
51+
52+
return fix;
53+
}
54+
55+
/**
56+
* @dev Retrieve the DOMAIN_SEPARATOR hash
57+
* @return domainSeparator hash used for sign messages
58+
*/
59+
function DOMAIN_SEPARATOR() public view returns (bytes32 domainSeparator) {
60+
return
61+
keccak256(
62+
abi.encode(
63+
EIP712DOMAIN_HASH,
64+
NAME_HASH,
65+
VERSION_HASH,
66+
getChainId(),
67+
address(this)
68+
)
69+
);
70+
}
71+
72+
/**
73+
* @return chainId The current chainId where the smarctoncract is executed
74+
*/
75+
function getChainId() public pure returns (uint256 chainId) {
76+
assembly {
77+
chainId := chainid()
78+
}
79+
}
80+
81+
/**
82+
* @dev Retrieve ethereum address from a (defaultMessage + babyjub) signature
83+
* @param babyjub Public key babyjubjub represented as point: sign + (Ay)
84+
* @param r Signature parameter
85+
* @param s Signature parameter
86+
* @param v Signature parameter
87+
* @return Ethereum address recovered from the signature
88+
*/
89+
function _checkSig(
90+
bytes32 babyjub,
91+
bytes32 r,
92+
bytes32 s,
93+
uint8 v
94+
) internal view returns (address) {
95+
// from https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/cryptography/ECDSA.sol#L46
96+
// EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature
97+
// unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines
98+
// the valid range for s in (281): 0 < s < secp256k1n ÷ 2 + 1, and for v in (282): v ∈ {27, 28}. Most
99+
// signatures from current libraries generate a unique signature with an s-value in the lower half order.
100+
//
101+
// If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value
102+
// with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or
103+
// vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept
104+
// these malleable signatures as well.
105+
require(
106+
uint256(s) <=
107+
0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0,
108+
"HermezHelpers::_checkSig: INVALID_S_VALUE"
109+
);
110+
111+
bytes32 encodeData = keccak256(
112+
abi.encode(
113+
AUTHORISE_TYPEHASH,
114+
HERMEZ_NETWORK_HASH,
115+
ACCOUNT_CREATION_HASH,
116+
babyjub
117+
)
118+
);
119+
120+
bytes32 messageDigest = keccak256(
121+
abi.encodePacked("\x19\x01", DOMAIN_SEPARATOR(), encodeData)
122+
);
123+
124+
address ethAddress = ecrecover(messageDigest, v, r, s);
125+
126+
require(
127+
ethAddress != address(0),
128+
"HermezHelpers::_checkSig: INVALID_SIGNATURE"
129+
);
130+
131+
return ethAddress;
132+
}
133+
134+
/**
135+
* @dev return information from specific call data info
136+
* @param posParam parameter number relative to 0 to extract the info
137+
* @return ptr ptr to the call data position where the actual data starts
138+
* @return len Length of the data
139+
*/
140+
function _getCallData(uint256 posParam)
141+
internal
142+
pure
143+
returns (uint256 ptr, uint256 len)
144+
{
145+
assembly {
146+
let pos := add(4, mul(posParam, 32))
147+
ptr := add(calldataload(pos), 4)
148+
len := calldataload(ptr)
149+
ptr := add(ptr, 32)
150+
}
151+
}
152+
153+
/**
154+
* @dev This package fills at least len zeros in memory and a maximum of len+31
155+
* @param ptr The position where it starts to fill zeros
156+
* @param len The minimum quantity of zeros it's added
157+
*/
158+
function _fillZeros(uint256 ptr, uint256 len) internal pure {
159+
assembly {
160+
let ptrTo := ptr
161+
ptr := add(ptr, len)
162+
for {
163+
164+
} lt(ptrTo, ptr) {
165+
ptrTo := add(ptrTo, 32)
166+
} {
167+
mstore(ptrTo, 0)
168+
}
169+
}
170+
}
171+
172+
/**
173+
* @dev Copy 'len' bytes from memory address 'src', to address 'dest'.
174+
* From https://github.com/GNSPS/solidity-bytes-utils/blob/master/contracts/BytesLib.sol
175+
* @param _preBytes bytes storage
176+
* @param _postBytes Bytes array memory
177+
*/
178+
function _concatStorage(bytes storage _preBytes, bytes memory _postBytes)
179+
internal
180+
{
181+
assembly {
182+
// Read the first 32 bytes of _preBytes storage, which is the length
183+
// of the array. (We don't need to use the offset into the slot
184+
// because arrays use the entire slot.)
185+
let fslot := sload(_preBytes_slot)
186+
// Arrays of 31 bytes or less have an even value in their slot,
187+
// while longer arrays have an odd value. The actual length is
188+
// the slot divided by two for odd values, and the lowest order
189+
// byte divided by two for even values.
190+
// If the slot is even, bitwise and the slot with 255 and divide by
191+
// two to get the length. If the slot is odd, bitwise and the slot
192+
// with -1 and divide by two.
193+
let slength := div(
194+
and(fslot, sub(mul(0x100, iszero(and(fslot, 1))), 1)),
195+
2
196+
)
197+
let mlength := mload(_postBytes)
198+
let newlength := add(slength, mlength)
199+
// slength can contain both the length and contents of the array
200+
// if length < 32 bytes so let's prepare for that
201+
// v. http://solidity.readthedocs.io/en/latest/miscellaneous.html#layout-of-state-variables-in-storage
202+
switch add(lt(slength, 32), lt(newlength, 32))
203+
case 2 {
204+
// Since the new array still fits in the slot, we just need to
205+
// update the contents of the slot.
206+
// uint256(bytes_storage) = uint256(bytes_storage) + uint256(bytes_memory) + new_length
207+
sstore(
208+
_preBytes_slot,
209+
// all the modifications to the slot are inside this
210+
// next block
211+
add(
212+
// we can just add to the slot contents because the
213+
// bytes we want to change are the LSBs
214+
fslot,
215+
add(
216+
mul(
217+
div(
218+
// load the bytes from memory
219+
mload(add(_postBytes, 0x20)),
220+
// zero all bytes to the right
221+
exp(0x100, sub(32, mlength))
222+
),
223+
// and now shift left the number of bytes to
224+
// leave space for the length in the slot
225+
exp(0x100, sub(32, newlength))
226+
),
227+
// increase length by the double of the memory
228+
// bytes length
229+
mul(mlength, 2)
230+
)
231+
)
232+
)
233+
}
234+
case 1 {
235+
// The stored value fits in the slot, but the combined value
236+
// will exceed it.
237+
// get the keccak hash to get the contents of the array
238+
mstore(0x0, _preBytes_slot)
239+
let sc := add(keccak256(0x0, 0x20), div(slength, 32))
240+
241+
// save new length
242+
sstore(_preBytes_slot, add(mul(newlength, 2), 1))
243+
244+
// The contents of the _postBytes array start 32 bytes into
245+
// the structure. Our first read should obtain the `submod`
246+
// bytes that can fit into the unused space in the last word
247+
// of the stored array. To get this, we read 32 bytes starting
248+
// from `submod`, so the data we read overlaps with the array
249+
// contents by `submod` bytes. Masking the lowest-order
250+
// `submod` bytes allows us to add that value directly to the
251+
// stored value.
252+
253+
let submod := sub(32, slength)
254+
let mc := add(_postBytes, submod)
255+
let end := add(_postBytes, mlength)
256+
let mask := sub(exp(0x100, submod), 1)
257+
258+
sstore(
259+
sc,
260+
add(
261+
and(
262+
fslot,
263+
0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00
264+
),
265+
and(mload(mc), mask)
266+
)
267+
)
268+
269+
for {
270+
mc := add(mc, 0x20)
271+
sc := add(sc, 1)
272+
} lt(mc, end) {
273+
sc := add(sc, 1)
274+
mc := add(mc, 0x20)
275+
} {
276+
sstore(sc, mload(mc))
277+
}
278+
279+
mask := exp(0x100, sub(mc, end))
280+
281+
sstore(sc, mul(div(mload(mc), mask), mask))
282+
}
283+
default {
284+
// get the keccak hash to get the contents of the array
285+
mstore(0x0, _preBytes_slot)
286+
// Start copying to the last used word of the stored array.
287+
let sc := add(keccak256(0x0, 0x20), div(slength, 32))
288+
289+
// save new length
290+
sstore(_preBytes_slot, add(mul(newlength, 2), 1))
291+
292+
// Copy over the first `submod` bytes of the new data as in
293+
// case 1 above.
294+
let slengthmod := mod(slength, 32)
295+
let mlengthmod := mod(mlength, 32)
296+
let submod := sub(32, slengthmod)
297+
let mc := add(_postBytes, submod)
298+
let end := add(_postBytes, mlength)
299+
let mask := sub(exp(0x100, submod), 1)
300+
301+
sstore(sc, add(sload(sc), and(mload(mc), mask)))
302+
303+
for {
304+
sc := add(sc, 1)
305+
mc := add(mc, 0x20)
306+
} lt(mc, end) {
307+
sc := add(sc, 1)
308+
mc := add(mc, 0x20)
309+
} {
310+
sstore(sc, mload(mc))
311+
}
312+
313+
mask := exp(0x100, sub(mc, end))
314+
315+
sstore(sc, mul(div(mload(mc), mask), mask))
316+
}
317+
}
318+
}
319+
}

0 commit comments

Comments
 (0)