-
Notifications
You must be signed in to change notification settings - Fork 358
/
Copy pathtest-precompile-over-pov.ts
206 lines (183 loc) · 6.99 KB
/
test-precompile-over-pov.ts
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
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
import "@moonbeam-network/api-augment";
import {
describeSuite,
expect,
beforeAll,
deployCreateCompiledContract,
fetchCompiledContract,
} from "@moonwall/cli";
import { HeavyContract, deployHeavyContracts, expectEVMResult } from "../../../../helpers";
import { Abi, encodeFunctionData } from "viem";
import { ALITH_ADDRESS, PRECOMPILE_BATCH_ADDRESS, createEthersTransaction } from "@moonwall/util";
describeSuite({
id: "D012804",
title: "PoV precompile test - gasLimit",
foundationMethods: "dev",
testCases: ({ context, log, it }) => {
let contracts: HeavyContract[];
const MAX_CONTRACTS = 50;
const EXPECTED_POV_ROUGH = 1_000_000; // bytes
let batchAbi: Abi;
let proxyAbi: Abi;
let proxyAddress: `0x${string}`;
let callData: `0x${string}`;
beforeAll(async function () {
const { contractAddress: contractAdd1, abi } = await deployCreateCompiledContract(
context,
"CallForwarder"
);
proxyAddress = contractAdd1;
proxyAbi = abi;
contracts = await deployHeavyContracts(context, 6000, 6000 + MAX_CONTRACTS);
// Get the interface for Batch precompile
batchAbi = fetchCompiledContract("Batch").abi;
callData = encodeFunctionData({
abi: batchAbi,
functionName: "batchAll",
args: [
[proxyAddress],
[],
[
encodeFunctionData({
abi: proxyAbi,
functionName: "callRange",
args: [contracts[0].account, contracts[MAX_CONTRACTS].account],
}),
],
[],
],
});
});
it({
id: "T01",
title: "gas cost should have increased with POV",
test: async function () {
// Previously this tx cost was ~500K gas -> now it is about 5M due to POV.
// We pass 1M, so it should fail.
const rawSigned = await createEthersTransaction(context, {
to: PRECOMPILE_BATCH_ADDRESS,
data: callData,
gasLimit: 1_000_000,
txnType: "eip1559",
});
const { result, block } = await context.createBlock(rawSigned);
// With 1M gas we are allowed to use ~250k of POV, so verify the range.
// The tx is still included in the block because it contains the failed tx,
// so POV is included in the block as well.
expect(block.proofSize).to.be.at.least(230_000);
expect(block.proofSize).to.be.at.most(290_000);
expect(result?.successful).to.equal(true);
expectEVMResult(result!.events, "Error", "OutOfGas");
},
});
it({
id: "T02",
title: "should be able to create a block using the estimated amount of gas",
test: async function () {
const gasEstimate = await context.viem().estimateGas({
account: ALITH_ADDRESS,
to: PRECOMPILE_BATCH_ADDRESS,
data: callData,
});
const rawSigned = await createEthersTransaction(context, {
to: PRECOMPILE_BATCH_ADDRESS,
data: callData,
gasLimit: gasEstimate,
txnType: "eip1559",
});
const { result, block } = await context.createBlock(rawSigned);
expect(block.proofSize).to.be.at.least(EXPECTED_POV_ROUGH / 1.3);
expect(block.proofSize).to.be.at.most(EXPECTED_POV_ROUGH * 1.3);
expect(result?.successful).to.equal(true);
expectEVMResult(result!.events, "Succeed", "Returned");
},
});
it({
id: "T03",
title: "should allow to call a precompile tx with enough gas limit to cover PoV",
test: async function () {
const rawSigned = await createEthersTransaction(context, {
to: PRECOMPILE_BATCH_ADDRESS,
data: callData,
gasLimit: 6_000_000,
txnType: "eip1559",
});
const { result, block } = await context.createBlock(rawSigned);
expect(block.proofSize).to.be.at.least(EXPECTED_POV_ROUGH / 1.3);
expect(block.proofSize).to.be.at.most(EXPECTED_POV_ROUGH * 1.3);
expect(result?.successful).to.equal(true);
expectEVMResult(result!.events, "Succeed", "Returned");
},
});
},
});
// describeDevMoonbeam("PoV precompile test - PoV Limit (3.5Mb in Dev)", (context) => {
// let contractProxy: Contract;
// let contracts: HeavyContract[];
// let proxyInterface: Interface;
// let batchInterface: Interface;
// before("Deploy the contracts from range 6000-XXXX", async function () {
// // Deploy the CallForwarder contract
// const creation = await createContract(context, "CallForwarder");
// contractProxy = creation.contract;
// await context.createBlock(creation.rawTx);
// // Get the CallForwarder contract interface
// proxyInterface = new ethers.utils.Interface(getCompiled("CallForwarder").contract.abi);
// // Deploy heavy contracts (test won't use more than what is needed for reaching max pov)
// contracts = await deployHeavyContracts(
// context,
// 6000,
// Number(6000n + MAX_ETH_POV_PER_TX / 24_000n + 1n)
// );
// // Get the interface for Batch precompile
// batchInterface = new ethers.utils.Interface(
// getCompiled("precompiles/batch/Batch").contract.abi
// );
// });
// it("should allow to produce block under the PoV Limit with precompile tx", async function () {
// const max_contracts = MAX_ETH_POV_PER_TX / 24_000n - 1n;
// const { result, block } = await context.createBlock(
// createTransaction(context, {
// to: PRECOMPILE_BATCH_ADDRESS,
// data: batchInterface.encodeFunctionData("batchAll", [
// [contractProxy.options.address],
// [],
// [
// proxyInterface.encodeFunctionData("callRange", [
// contracts[0].account,
// contracts[Number(max_contracts)].account,
// ]),
// ],
// [],
// ]),
// gas: 13_000_000,
// })
// );
// expect(block.proofSize).to.be.at.least(Number(MAX_ETH_POV_PER_TX - 20_000n));
// expect(block.proofSize).to.be.at.most(Number(MAX_ETH_POV_PER_TX - 1n));
// expect(result.successful).to.equal(true);
// });
// it("should prevent a tx reaching just over the PoV with a precompile tx", async function () {
// const max_contracts = MAX_ETH_POV_PER_TX / 24_000n;
// const { result, block } = await context.createBlock(
// createTransaction(context, {
// to: PRECOMPILE_BATCH_ADDRESS,
// data: batchInterface.encodeFunctionData("batchAll", [
// [contractProxy.options.address],
// [],
// [
// proxyInterface.encodeFunctionData("callRange", [
// contracts[0].account,
// contracts[Number(max_contracts)].account,
// ]),
// ],
// [],
// ]),
// gas: 15_000_000,
// })
// );
// // Empty blocks usually do not exceed 10kb, picking 50kb as a safe limit
// expect(block.proofSize).to.be.at.most(50_000);
// expect(result.successful).to.equal(false);
// });
// });