@paimaexample/evm-contracts 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +7 -0
- package/deno.json +28 -0
- package/docs/templates/contract.hbs +144 -0
- package/docs/templates/helpers.js +61 -0
- package/docs/templates/page.hbs +7 -0
- package/docs/templates/properties.js +76 -0
- package/hardhat.config.ts +11 -0
- package/index.js +1 -0
- package/mod.ts +0 -0
- package/package.json +13 -0
- package/remappings.txt +1 -0
- package/src/companions/ERC165Contract.json +21 -0
- package/src/companions/ERC165Contract.ts +21 -0
- package/src/companions/ERC20Contract.json +222 -0
- package/src/companions/ERC20Contract.ts +222 -0
- package/src/companions/ERC6551RegistryContract.json +128 -0
- package/src/companions/ERC6551RegistryContract.ts +128 -0
- package/src/companions/ERC721Contract.json +248 -0
- package/src/companions/ERC721Contract.ts +222 -0
- package/src/companions/IERC1155Contract.json +295 -0
- package/src/companions/IERC1155Contract.ts +295 -0
- package/src/companions/OldERC6551RegistryContract.json +133 -0
- package/src/companions/OldERC6551RegistryContract.ts +133 -0
- package/src/companions/PaimaERC721Contract.json +787 -0
- package/src/companions/PaimaERC721Contract.ts +787 -0
- package/src/companions/PaimaL2Contract.json +134 -0
- package/src/companions/PaimaL2Contract.ts +134 -0
- package/src/companions/README.md +5 -0
- package/src/contracts/AnnotatedMintNft.sol +171 -0
- package/src/contracts/BaseState.sol +16 -0
- package/src/contracts/ERC1967.sol +43 -0
- package/src/contracts/Erc20NftSale.sol +186 -0
- package/src/contracts/GenericPayment.sol +60 -0
- package/src/contracts/NativeNftSale.sol +97 -0
- package/src/contracts/PaimaL2Contract.sol +54 -0
- package/src/contracts/Proxy/Erc20NftSaleProxy.sol +79 -0
- package/src/contracts/Proxy/GenericPaymentProxy.sol +64 -0
- package/src/contracts/Proxy/NativeNftSaleProxy.sol +72 -0
- package/src/contracts/Proxy/OrderbookDexProxy.sol +27 -0
- package/src/contracts/README.md +72 -0
- package/src/contracts/State.sol +25 -0
- package/src/contracts/dev/ERC721Dev.sol +13 -0
- package/src/contracts/dev/Erc20Dev.sol +13 -0
- package/src/contracts/dev/NativeNftSaleUpgradeDev.sol +9 -0
- package/src/contracts/dev/NftSaleUpgradeDev.sol +12 -0
- package/src/contracts/dev/NftTypeMapper.sol +38 -0
- package/src/contracts/dev/Token.sol +15 -0
- package/src/contracts/dev/UpgradeDev.sol +10 -0
- package/src/contracts/orderbook/IOrderbookDex.sol +215 -0
- package/src/contracts/orderbook/OrderbookDex.sol +435 -0
- package/src/contracts/token/IERC4906Agnostic.sol +17 -0
- package/src/contracts/token/IInverseAppProjected1155.sol +40 -0
- package/src/contracts/token/IInverseAppProjectedNft.sol +38 -0
- package/src/contracts/token/IInverseBaseProjected1155.sol +25 -0
- package/src/contracts/token/IInverseBaseProjectedNft.sol +29 -0
- package/src/contracts/token/IInverseProjected1155.sol +38 -0
- package/src/contracts/token/IInverseProjectedNft.sol +41 -0
- package/src/contracts/token/ITokenUri.sol +10 -0
- package/src/contracts/token/IUri.sol +13 -0
- package/src/contracts/token/InverseAppProjected1155.sol +218 -0
- package/src/contracts/token/InverseAppProjectedNft.sol +192 -0
- package/src/contracts/token/InverseBaseProjected1155.sol +170 -0
- package/src/contracts/token/InverseBaseProjectedNft.sol +158 -0
- package/src/plugin/common.ts +35 -0
- package/src/plugin/deployment.ts +161 -0
- package/src/plugin/mod.ts +6 -0
- package/src/plugin/paimaL2.ts +202 -0
- package/src/recommendedHardhat.ts +86 -0
- package/test/lib/StdInvariant.sol +96 -0
- package/test/lib/cheatcodes.sol +89 -0
- package/test/lib/console.sol +1884 -0
- package/test/lib/ctest.sol +678 -0
- package/test/src/InverseAppProjected1155.t.sol +207 -0
- package/test/src/InverseAppProjectedNft.t.sol +164 -0
- package/test/src/InverseBaseProjected1155.t.sol +171 -0
- package/test/src/InverseBaseProjectedNft.t.sol +141 -0
- package/test/src/OrderbookDex.t.sol +710 -0
- package/test/src/OrderbookDexInvariant.t.sol +426 -0
- package/test/src/PaimaL2ContractTest.sol +115 -0
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
// import { task, types } from 'hardhat/config';
|
|
2
|
+
// import '@nomicfoundation/hardhat-toolbox-viem';
|
|
3
|
+
// import { getContract, getOrAskString, ownerCheck, paimaScope } from './common.js';
|
|
4
|
+
// import { decodeAbiParameters } from 'viem';
|
|
5
|
+
// import { stringToBytes } from 'viem';
|
|
6
|
+
|
|
7
|
+
// paimaScope
|
|
8
|
+
// .task('PaimaL2Contract:setFee', `Sets the fee of a Paima L2 contract`)
|
|
9
|
+
// .addOptionalParam('contract', `The contracts's address`, undefined, types.string)
|
|
10
|
+
// .addOptionalParam('fee', `The new fee (wei)`, undefined, types.string)
|
|
11
|
+
// .setAction(async (taskArgs, hre) => {
|
|
12
|
+
// const publicClient = await hre.viem.getPublicClient();
|
|
13
|
+
// // Connect to the deployed contract
|
|
14
|
+
// const { signer, account } = await getContract(hre, taskArgs.contract);
|
|
15
|
+
// const contract = await hre.viem.getContractAt('PaimaL2Contract', account);
|
|
16
|
+
|
|
17
|
+
// ownerCheck((await contract.read.owner()) as string, await signer.account!.address);
|
|
18
|
+
|
|
19
|
+
// const newFee = BigInt(await getOrAskString(taskArgs.fee, 'Fee? '));
|
|
20
|
+
// if ((await contract.read.fee()) === newFee) {
|
|
21
|
+
// console.log(`Fee matches existing value "${newFee}". Skipping`);
|
|
22
|
+
// return;
|
|
23
|
+
// }
|
|
24
|
+
// const hash = await contract.write.setFee([newFee]);
|
|
25
|
+
// await publicClient.waitForTransactionReceipt({ hash });
|
|
26
|
+
// const updatedValue = await contract.read.fee();
|
|
27
|
+
// console.log(`The updated value of "fee" is: ${updatedValue}`);
|
|
28
|
+
// });
|
|
29
|
+
// paimaScope
|
|
30
|
+
// .task('PaimaL2Contract:setOwner', `Sets the owner of a Paima L2 contract`)
|
|
31
|
+
// .addOptionalParam('contract', `The contracts's address`, undefined, types.string)
|
|
32
|
+
// .addOptionalParam('owner', `The new owner address`, undefined, types.string)
|
|
33
|
+
// .setAction(async (taskArgs, hre) => {
|
|
34
|
+
// const publicClient = await hre.viem.getPublicClient();
|
|
35
|
+
// // Connect to the deployed contract
|
|
36
|
+
// const { signer, account } = await getContract(hre, taskArgs.contract);
|
|
37
|
+
// const contract = await hre.viem.getContractAt('PaimaL2Contract', account);
|
|
38
|
+
|
|
39
|
+
// ownerCheck((await contract.read.owner()) as string, await signer.account!.address);
|
|
40
|
+
|
|
41
|
+
// if ((await contract.read.owner()) === taskArgs.owner) {
|
|
42
|
+
// console.log(`Owner matches existing value "${taskArgs.owner}". Skipping`);
|
|
43
|
+
// return;
|
|
44
|
+
// }
|
|
45
|
+
// const hash = await contract.write.setOwner([taskArgs.owner]);
|
|
46
|
+
// await publicClient.waitForTransactionReceipt({ hash });
|
|
47
|
+
// const updatedValue = await contract.read.owner();
|
|
48
|
+
// console.log(`The updated value of "owner" is: ${updatedValue}`);
|
|
49
|
+
// });
|
|
50
|
+
|
|
51
|
+
// paimaScope
|
|
52
|
+
// .task('PaimaL2Contract:withdrawFunds', `Withdraws funds out of the Paima L2 contract`)
|
|
53
|
+
// .addOptionalParam('contract', `The contracts's address`, undefined, types.string)
|
|
54
|
+
// .setAction(async (taskArgs, hre) => {
|
|
55
|
+
// const publicClient = await hre.viem.getPublicClient();
|
|
56
|
+
// // Connect to the deployed contract
|
|
57
|
+
// const { signer, account } = await getContract(hre, taskArgs.contract);
|
|
58
|
+
// const contract = await hre.viem.getContractAt('PaimaL2Contract', account);
|
|
59
|
+
|
|
60
|
+
// ownerCheck((await contract.read.owner()) as string, await signer.account!.address);
|
|
61
|
+
|
|
62
|
+
// const currentBalance = await publicClient.getBalance({
|
|
63
|
+
// address: account,
|
|
64
|
+
// });
|
|
65
|
+
// if (currentBalance === 0n) {
|
|
66
|
+
// console.log(`Current balance is "${0n}". Skipping`);
|
|
67
|
+
// return;
|
|
68
|
+
// }
|
|
69
|
+
// const hash = await contract.write.withdrawFunds();
|
|
70
|
+
// await publicClient.waitForTransactionReceipt({ hash });
|
|
71
|
+
// console.log(`Withdrew ${currentBalance} to ${await signer.account!.address}`);
|
|
72
|
+
// });
|
|
73
|
+
|
|
74
|
+
// paimaScope
|
|
75
|
+
// .task('PaimaL2Contract:submitGameInput', `Submit data to the Paima L2 contract`)
|
|
76
|
+
// .addOptionalParam('contract', `The contracts's address`, undefined, types.string)
|
|
77
|
+
// .addOptionalParam(
|
|
78
|
+
// 'data',
|
|
79
|
+
// `The data to submit either hex-encoded (0x...) or Paima concise-encoded`,
|
|
80
|
+
// undefined,
|
|
81
|
+
// types.string
|
|
82
|
+
// )
|
|
83
|
+
// .setAction(async (taskArgs, hre) => {
|
|
84
|
+
// const publicClient = await hre.viem.getPublicClient();
|
|
85
|
+
// // Connect to the deployed contract
|
|
86
|
+
// const { signer, account } = await getContract(hre, taskArgs.contract);
|
|
87
|
+
// const contract = await hre.viem.getContractAt('PaimaL2Contract', account);
|
|
88
|
+
|
|
89
|
+
// const providedData = await getOrAskString(taskArgs.data, 'data? ');
|
|
90
|
+
// const data = providedData.startsWith('0x') ? providedData : stringToBytes(providedData);
|
|
91
|
+
|
|
92
|
+
// const fee = await contract.read.fee();
|
|
93
|
+
// console.log(fee);
|
|
94
|
+
// const hash = await contract.write.paimaSubmitGameInput([data], { value: fee });
|
|
95
|
+
// await publicClient.waitForTransactionReceipt({ hash });
|
|
96
|
+
// console.log(`Submitted data to the contract successfully at ${hash}`);
|
|
97
|
+
// });
|
|
98
|
+
|
|
99
|
+
// paimaScope
|
|
100
|
+
// .task('PaimaL2Contract:recentInputs', `Gets data recently submitted to the Paima L2 contract`)
|
|
101
|
+
// .addOptionalParam('contract', `The contracts's address`, undefined, types.string)
|
|
102
|
+
// .addOptionalParam(
|
|
103
|
+
// 'data',
|
|
104
|
+
// `The data to submit in hex-encoded for (0x...)`,
|
|
105
|
+
// undefined,
|
|
106
|
+
// types.string
|
|
107
|
+
// )
|
|
108
|
+
// .addOptionalParam(
|
|
109
|
+
// 'range',
|
|
110
|
+
// `How far back to get events (default: look back 1000 blocks from tip)`,
|
|
111
|
+
// undefined,
|
|
112
|
+
// types.int
|
|
113
|
+
// )
|
|
114
|
+
// .setAction(async (taskArgs, hre) => {
|
|
115
|
+
// // Connect to the deployed contract
|
|
116
|
+
// const { account } = await getContract(hre, taskArgs.contract);
|
|
117
|
+
|
|
118
|
+
// const publicClient = await hre.viem.getPublicClient();
|
|
119
|
+
|
|
120
|
+
// const contract = await hre.viem.getContractAt('PaimaL2Contract', account);
|
|
121
|
+
|
|
122
|
+
// const toBlock = await publicClient.getBlockNumber();
|
|
123
|
+
// const maxRange = taskArgs.range ?? 10000n;
|
|
124
|
+
// const fromBlock = maxRange > toBlock ? 0n : toBlock - maxRange;
|
|
125
|
+
|
|
126
|
+
// const eventFilter = await contract.createEventFilter.PaimaGameInteraction({
|
|
127
|
+
// fromBlock,
|
|
128
|
+
// toBlock,
|
|
129
|
+
// });
|
|
130
|
+
// const events = await publicClient.getFilterLogs({
|
|
131
|
+
// filter: eventFilter,
|
|
132
|
+
// });
|
|
133
|
+
|
|
134
|
+
// const getData = (rawData: `0x${string}`): string => {
|
|
135
|
+
// const tentativeData = decodeAbiParameters([{ type: 'bytes' }], rawData)[0] as string;
|
|
136
|
+
// const textBuffer = Buffer.from(tentativeData.substring('0x'.length), 'hex');
|
|
137
|
+
// try {
|
|
138
|
+
// const decoded = new TextDecoder('utf-8', { fatal: true }).decode(textBuffer);
|
|
139
|
+
// // check if ASCII data
|
|
140
|
+
// if (/^[\x20-\x7E]*$/.test(decoded)) {
|
|
141
|
+
// return decoded;
|
|
142
|
+
// }
|
|
143
|
+
// // cannot be printed in a terminal
|
|
144
|
+
// return tentativeData;
|
|
145
|
+
// } catch (e) {
|
|
146
|
+
// // not a valid utf8 string
|
|
147
|
+
// return tentativeData;
|
|
148
|
+
// }
|
|
149
|
+
// };
|
|
150
|
+
|
|
151
|
+
// console.log(
|
|
152
|
+
// events.map(event => ({
|
|
153
|
+
// blockHash: event.blockHash,
|
|
154
|
+
// blockNumber: event.blockNumber,
|
|
155
|
+
// transactionHash: event.transactionHash,
|
|
156
|
+
// address: event.address,
|
|
157
|
+
// data: getData(event.data),
|
|
158
|
+
// }))
|
|
159
|
+
// );
|
|
160
|
+
// });
|
|
161
|
+
|
|
162
|
+
// task('genDocs', `Generate documentation for tasks of a given scope`)
|
|
163
|
+
// .addParam('scope', 'The scope to generate documentation for')
|
|
164
|
+
// .setAction(async ({ scope }, hre) => {
|
|
165
|
+
// const scopeContent = hre.scopes[scope];
|
|
166
|
+
// console.log(scopeContent);
|
|
167
|
+
|
|
168
|
+
// console.log(`# ${scopeContent.description ?? scope}`);
|
|
169
|
+
// console.log(
|
|
170
|
+
// `These are all the [hardhat tasks](https://hardhat.org/hardhat-runner/docs/advanced/create-task) available for the scope \`${scope}\`.`
|
|
171
|
+
// );
|
|
172
|
+
// console.log();
|
|
173
|
+
// console.log(`You can call each of these tasks using \`npx hardhat ${scope} task_name\``);
|
|
174
|
+
// for (const [name, definition] of Object.entries(scopeContent.tasks)) {
|
|
175
|
+
// console.log();
|
|
176
|
+
// console.log(`## \`${name}\``);
|
|
177
|
+
// console.log(definition.description ?? 'No description provided');
|
|
178
|
+
// const parameters = Object.values(definition.paramDefinitions);
|
|
179
|
+
// if (parameters.length > 0) {
|
|
180
|
+
// console.log();
|
|
181
|
+
// console.log('Parameters:');
|
|
182
|
+
// for (const param of parameters) {
|
|
183
|
+
// let annotations = [];
|
|
184
|
+
// if (param.isOptional) {
|
|
185
|
+
// annotations.push(`optional`);
|
|
186
|
+
// if (param.defaultValue != null) {
|
|
187
|
+
// annotations.push(`${param.defaultValue}`);
|
|
188
|
+
// }
|
|
189
|
+
// }
|
|
190
|
+
// if (param.type) {
|
|
191
|
+
// annotations.push(`${param.type.name}`);
|
|
192
|
+
// }
|
|
193
|
+
// const annotationText = annotations.length > 0 ? ` *(${annotations.join(', ')})* ` : '';
|
|
194
|
+
// console.log(
|
|
195
|
+
// `- **${param.name}**${annotationText}: ${
|
|
196
|
+
// param.description ?? 'No description provided'
|
|
197
|
+
// }`
|
|
198
|
+
// );
|
|
199
|
+
// }
|
|
200
|
+
// }
|
|
201
|
+
// }
|
|
202
|
+
// });
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import type { HardhatUserConfig } from "hardhat/config";
|
|
2
|
+
import HardhatViem from "@nomicfoundation/hardhat-viem";
|
|
3
|
+
// import "hardhat-interact";
|
|
4
|
+
// import HardhatAbiExporter from "hardhat-abi-exporter";
|
|
5
|
+
|
|
6
|
+
export function defaultHardhatConfig(config: {
|
|
7
|
+
outDir: string;
|
|
8
|
+
}): HardhatUserConfig {
|
|
9
|
+
const defaultConfig: HardhatUserConfig = {
|
|
10
|
+
paths: {
|
|
11
|
+
sources: "./src/contracts",
|
|
12
|
+
tests: "./test/src",
|
|
13
|
+
cache: `${config.outDir}/cache/hardhat`,
|
|
14
|
+
artifacts: `${config.outDir}/artifacts/hardhat`,
|
|
15
|
+
// ignition: "./src/ignition",
|
|
16
|
+
},
|
|
17
|
+
tasks: [],
|
|
18
|
+
plugins: [
|
|
19
|
+
HardhatViem,
|
|
20
|
+
// HardhatAbiExporter,
|
|
21
|
+
],
|
|
22
|
+
solidity: {
|
|
23
|
+
version: "0.8.22",
|
|
24
|
+
dependenciesToCompile: [],
|
|
25
|
+
// remappings: [
|
|
26
|
+
// "remapped/=npm/@openzeppelin/contracts@5.1.0/access/",
|
|
27
|
+
// // This is necessary because most people import forge-std/Test.sol, and not forge-std/src/Test.sol
|
|
28
|
+
// "forge-std/=npm/forge-std@local/src/",
|
|
29
|
+
// ],
|
|
30
|
+
},
|
|
31
|
+
// abiExporter: {
|
|
32
|
+
// path: `${config.outDir}/abi`,
|
|
33
|
+
// runOnCompile: true,
|
|
34
|
+
// tsWrapper: true,
|
|
35
|
+
// clear: true,
|
|
36
|
+
// flat: false,
|
|
37
|
+
// },
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
return defaultConfig;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
// /**
|
|
44
|
+
// * This type comes from hardhat-ignition. It's unfortunately not exported
|
|
45
|
+
// */
|
|
46
|
+
// type IgnitionDeployParameters = {
|
|
47
|
+
// modulePath: string;
|
|
48
|
+
// parameters?: string;
|
|
49
|
+
// deploymentId: string | undefined;
|
|
50
|
+
// defaultSender: string | undefined;
|
|
51
|
+
// reset: boolean;
|
|
52
|
+
// verify: boolean;
|
|
53
|
+
// strategy: string;
|
|
54
|
+
// writeLocalhostDeployment: boolean;
|
|
55
|
+
// };
|
|
56
|
+
|
|
57
|
+
// /**
|
|
58
|
+
// * TODO: this may be replaced by a built-in feature in the future
|
|
59
|
+
// * https://github.com/NomicFoundation/hardhat-ignition/issues/791
|
|
60
|
+
// */
|
|
61
|
+
// export function defaultDeployment(
|
|
62
|
+
// rootDir: string,
|
|
63
|
+
// outDir: string,
|
|
64
|
+
// config: IgnitionDeployParameters
|
|
65
|
+
// ): void {
|
|
66
|
+
// subtask(TASK_NODE_SERVER_READY, async (_, hre, runSuper) => {
|
|
67
|
+
// const result = await runSuper();
|
|
68
|
+
|
|
69
|
+
// await hre.run(
|
|
70
|
+
// {
|
|
71
|
+
// scope: 'ignition',
|
|
72
|
+
// task: 'deploy',
|
|
73
|
+
// },
|
|
74
|
+
// config
|
|
75
|
+
// );
|
|
76
|
+
// await hre.run(
|
|
77
|
+
// {
|
|
78
|
+
// scope: 'paima',
|
|
79
|
+
// task: 'copy-ignition-deployment',
|
|
80
|
+
// },
|
|
81
|
+
// { rootDir, outDir }
|
|
82
|
+
// );
|
|
83
|
+
|
|
84
|
+
// return result;
|
|
85
|
+
// });
|
|
86
|
+
// }
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
// SPDX-License-Identifier: MIT
|
|
2
|
+
pragma solidity >=0.6.2 <0.9.0;
|
|
3
|
+
|
|
4
|
+
pragma experimental ABIEncoderV2;
|
|
5
|
+
|
|
6
|
+
abstract contract StdInvariant {
|
|
7
|
+
struct FuzzSelector {
|
|
8
|
+
address addr;
|
|
9
|
+
bytes4[] selectors;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
address[] private _excludedContracts;
|
|
13
|
+
address[] private _excludedSenders;
|
|
14
|
+
address[] private _targetedContracts;
|
|
15
|
+
address[] private _targetedSenders;
|
|
16
|
+
|
|
17
|
+
string[] private _excludedArtifacts;
|
|
18
|
+
string[] private _targetedArtifacts;
|
|
19
|
+
|
|
20
|
+
FuzzSelector[] private _targetedArtifactSelectors;
|
|
21
|
+
FuzzSelector[] private _targetedSelectors;
|
|
22
|
+
|
|
23
|
+
// Functions for users:
|
|
24
|
+
// These are intended to be called in tests.
|
|
25
|
+
|
|
26
|
+
function excludeContract(address newExcludedContract_) internal {
|
|
27
|
+
_excludedContracts.push(newExcludedContract_);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
function excludeSender(address newExcludedSender_) internal {
|
|
31
|
+
_excludedSenders.push(newExcludedSender_);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
function excludeArtifact(string memory newExcludedArtifact_) internal {
|
|
35
|
+
_excludedArtifacts.push(newExcludedArtifact_);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
function targetArtifact(string memory newTargetedArtifact_) internal {
|
|
39
|
+
_targetedArtifacts.push(newTargetedArtifact_);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
function targetArtifactSelector(FuzzSelector memory newTargetedArtifactSelector_) internal {
|
|
43
|
+
_targetedArtifactSelectors.push(newTargetedArtifactSelector_);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
function targetContract(address newTargetedContract_) internal {
|
|
47
|
+
_targetedContracts.push(newTargetedContract_);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
function targetSelector(FuzzSelector memory newTargetedSelector_) internal {
|
|
51
|
+
_targetedSelectors.push(newTargetedSelector_);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
function targetSender(address newTargetedSender_) internal {
|
|
55
|
+
_targetedSenders.push(newTargetedSender_);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
// Functions for forge:
|
|
59
|
+
// These are called by forge to run invariant tests and don't need to be called in tests.
|
|
60
|
+
|
|
61
|
+
function excludeArtifacts() public view returns (string[] memory excludedArtifacts_) {
|
|
62
|
+
excludedArtifacts_ = _excludedArtifacts;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
function excludeContracts() public view returns (address[] memory excludedContracts_) {
|
|
66
|
+
excludedContracts_ = _excludedContracts;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
function excludeSenders() public view returns (address[] memory excludedSenders_) {
|
|
70
|
+
excludedSenders_ = _excludedSenders;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
function targetArtifacts() public view returns (string[] memory targetedArtifacts_) {
|
|
74
|
+
targetedArtifacts_ = _targetedArtifacts;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
function targetArtifactSelectors()
|
|
78
|
+
public
|
|
79
|
+
view
|
|
80
|
+
returns (FuzzSelector[] memory targetedArtifactSelectors_)
|
|
81
|
+
{
|
|
82
|
+
targetedArtifactSelectors_ = _targetedArtifactSelectors;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
function targetContracts() public view returns (address[] memory targetedContracts_) {
|
|
86
|
+
targetedContracts_ = _targetedContracts;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
function targetSelectors() public view returns (FuzzSelector[] memory targetedSelectors_) {
|
|
90
|
+
targetedSelectors_ = _targetedSelectors;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
function targetSenders() public view returns (address[] memory targetedSenders_) {
|
|
94
|
+
targetedSenders_ = _targetedSenders;
|
|
95
|
+
}
|
|
96
|
+
}
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
// SPDX-License-Identifier: MIT
|
|
2
|
+
pragma solidity ^0.8.7;
|
|
3
|
+
|
|
4
|
+
interface CheatCodes {
|
|
5
|
+
// Set block.timestamp (newTimestamp)
|
|
6
|
+
function warp(uint256) external;
|
|
7
|
+
|
|
8
|
+
// Set block.height (newHeight)
|
|
9
|
+
function roll(uint256) external;
|
|
10
|
+
|
|
11
|
+
// Set block.basefee (newBasefee)
|
|
12
|
+
function fee(uint256) external;
|
|
13
|
+
|
|
14
|
+
// Loads a storage slot from an address (who, slot)
|
|
15
|
+
function load(address, bytes32) external returns (bytes32);
|
|
16
|
+
|
|
17
|
+
// Stores a value to an address' storage slot, (who, slot, value)
|
|
18
|
+
function store(address, bytes32, bytes32) external;
|
|
19
|
+
|
|
20
|
+
// Signs data, (privateKey, digest) => (v, r, s)
|
|
21
|
+
function sign(uint256, bytes32) external returns (uint8, bytes32, bytes32);
|
|
22
|
+
|
|
23
|
+
// Gets address for a given private key, (privateKey) => (address)
|
|
24
|
+
function addr(uint256) external returns (address);
|
|
25
|
+
|
|
26
|
+
// Performs a foreign function call via terminal, (stringInputs) => (result)
|
|
27
|
+
function ffi(string[] calldata) external returns (bytes memory);
|
|
28
|
+
|
|
29
|
+
// Sets the *next* call's msg.sender to be the input address
|
|
30
|
+
function prank(address) external;
|
|
31
|
+
|
|
32
|
+
// Sets all subsequent calls' msg.sender to be the input address until `stopPrank` is called
|
|
33
|
+
function startPrank(address) external;
|
|
34
|
+
|
|
35
|
+
// Sets the *next* call's msg.sender to be the input address, and the tx.origin to be the second input
|
|
36
|
+
function prank(address, address) external;
|
|
37
|
+
|
|
38
|
+
// Sets all subsequent calls' msg.sender to be the input address until `stopPrank` is called, and the tx.origin to be the second input
|
|
39
|
+
function startPrank(address, address) external;
|
|
40
|
+
|
|
41
|
+
// Resets subsequent calls' msg.sender to be `address(this)`
|
|
42
|
+
function stopPrank() external;
|
|
43
|
+
|
|
44
|
+
// Sets an address' balance, (who, newBalance)
|
|
45
|
+
function deal(address, uint256) external;
|
|
46
|
+
|
|
47
|
+
// Sets an address' code, (who, newCode)
|
|
48
|
+
function etch(address, bytes calldata) external;
|
|
49
|
+
|
|
50
|
+
// Expects an error on next call
|
|
51
|
+
function expectRevert(bytes calldata) external;
|
|
52
|
+
|
|
53
|
+
function expectRevert(bytes4) external;
|
|
54
|
+
|
|
55
|
+
function expectRevert() external;
|
|
56
|
+
|
|
57
|
+
// Record all storage reads and writes
|
|
58
|
+
function record() external;
|
|
59
|
+
|
|
60
|
+
// Gets all accessed reads and write slot from a recording session, for a given address
|
|
61
|
+
function accesses(address) external returns (bytes32[] memory reads, bytes32[] memory writes);
|
|
62
|
+
|
|
63
|
+
// Prepare an expected log with (bool checkTopic1, bool checkTopic2, bool checkTopic3, bool checkData).
|
|
64
|
+
// Call this function, then emit an event, then call a function. Internally after the call, we check if
|
|
65
|
+
// logs were emitted in the expected order with the expected topics and data (as specified by the booleans)
|
|
66
|
+
function expectEmit(bool, bool, bool, bool) external;
|
|
67
|
+
|
|
68
|
+
// Mocks a call to an address, returning specified data.
|
|
69
|
+
// Calldata can either be strict or a partial match, e.g. if you only
|
|
70
|
+
// pass a Solidity selector to the expected calldata, then the entire Solidity
|
|
71
|
+
// function will be mocked.
|
|
72
|
+
function mockCall(address, bytes calldata, bytes calldata) external;
|
|
73
|
+
|
|
74
|
+
// Clears all mocked calls
|
|
75
|
+
function clearMockedCalls() external;
|
|
76
|
+
|
|
77
|
+
// Expect a call to an address with the specified calldata.
|
|
78
|
+
// Calldata can either be strict or a partial match
|
|
79
|
+
function expectCall(address, bytes calldata) external;
|
|
80
|
+
|
|
81
|
+
// Gets the code from an artifact file. Takes in the relative path to the json file
|
|
82
|
+
function getCode(string calldata) external returns (bytes memory);
|
|
83
|
+
|
|
84
|
+
// Labels an address in call traces
|
|
85
|
+
function label(address, string calldata) external;
|
|
86
|
+
|
|
87
|
+
// If the condition is false, discard this run's fuzz inputs and generate new ones.
|
|
88
|
+
function assume(bool condition) external pure;
|
|
89
|
+
}
|