-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathS01E10-EcMul.t.sol
153 lines (119 loc) · 5.39 KB
/
S01E10-EcMul.t.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
// SPDX-License-Identifier: UNLICENSED
pragma solidity 0.8.16;
import "forge-std/Test.sol";
import "./lib/YulDeployer.sol";
import "./lib/VyperDeployer.sol";
import "./lib/HuffDeployer.sol";
import "src/interfaces/IEcMul.sol";
contract EcMulTestBase is Test {
IEcMul internal ecMul;
// prime number defining the finite field for secp256k1
uint256 constant p = 2 ** 256 - 2 ** 32 - 977;
// generator point for secp256k1 used for calculating the public keys from the private key
uint256[2] G = [
0x79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798,
0x483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8
];
function deploy() internal virtual returns (address addr) {
// first: get the bytecode from the environment if it exists
bytes memory empty = new bytes(0);
bytes memory bytecode = vm.envOr("BYTECODE", empty);
if (bytecode.length > 0) {
assembly {
addr := create(0, add(bytecode, 0x20), mload(bytecode))
}
return addr;
}
}
function setUp() public {
ecMul = IEcMul(deploy());
}
function test_s01e10_sanity() public {
// G * 0 = 0
uint256[2] memory userResult = ecMul.ecMul(G, 0);
assertEq(userResult[0], 0);
assertEq(userResult[1], 0);
// G * 1 = G
userResult = ecMul.ecMul(G, 1);
assertEq(userResult[0], G[0]);
assertEq(userResult[1], G[1]);
}
/// forge-config: default.fuzz.runs = 16
function test_s01e10_fuzz(bytes memory x) public {
vm.pauseGasMetering();
// get private key and public keys (points on the secp256k1 curve)
Vm.Wallet memory wallet = vm.createWallet(uint256(keccak256(x)));
uint256 pKey = wallet.privateKey;
uint256[2] memory P = [wallet.publicKeyX, wallet.publicKeyY];
vm.resumeGasMetering();
// we multiply the private key with the generator point to get the public key
uint256[2] memory userResult = ecMul.ecMul(G, pKey);
// calculated public key should be the same as the one generated by vm.createWallet
assertEq(P[0], userResult[0]);
assertEq(P[1], userResult[1]);
}
/// forge-config: default.fuzz.runs = 16
function test_s01e10_gas(bytes memory x) public {
vm.pauseGasMetering();
// get private key
Vm.Wallet memory wallet = vm.createWallet(uint256(keccak256(x)));
uint256 pKey = wallet.privateKey;
vm.resumeGasMetering();
// we multiply the private key with the generator point to get the public key
ecMul.ecMul(G, pKey);
}
function test_s01e10_size() public {
console2.log("Contract size:", address(ecMul).code.length);
}
}
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* SOLIDITY */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
contract EcMulTestSol is EcMulTestBase {
function deploy() internal override returns (address addr) {
// The string array input variable used by ffi
string[] memory deployCommand = new string[](4);
// We get the bytecode of the Solidity contract with
// forge inspect <contract> bytecode
deployCommand[0] = "forge";
deployCommand[1] = "inspect";
deployCommand[2] = "EcMul";
deployCommand[3] = "bytecode";
// A local variable to hold the output bytecode
bytes memory compiledByteCode = vm.ffi(deployCommand);
// A local variable to hold the address of the deployed Solidity contract
address deployAddr;
// Inline assembly code to deploy a contract using bytecode
assembly {
deployAddr := create(0, add(compiledByteCode, 0x20), mload(compiledByteCode))
}
return deployAddr;
}
}
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* YUL */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
contract EcMulTestYul is EcMulTestBase {
YulDeployer yulDeployer = new YulDeployer();
function deploy() internal override returns (address addr) {
return yulDeployer.deployContract("S01E10-EcMul");
}
}
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* VYPER */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
contract EcMulTestVyper is EcMulTestBase {
VyperDeployer vyperDeployer = new VyperDeployer();
function deploy() internal override returns (address addr) {
return vyperDeployer.deployContract("S01E10-EcMul");
}
}
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* HUFF */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
contract EcMulTestHuff is EcMulTestBase {
function deploy() internal override returns (address addr) {
HuffDeployer huffDeployer = new HuffDeployer();
return huffDeployer.deployContract("S01E10-EcMul");
}
}