Skip to content

Commit 8462a80

Browse files
authored
chore: use event definitions from library to expand version compatibility (#285)
Signed-off-by: Luis Mastrangelo <luis@swirldslabs.com>
1 parent cb61561 commit 8462a80

File tree

21 files changed

+441
-348
lines changed

21 files changed

+441
-348
lines changed

.github/workflows/test.yml

Lines changed: 33 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -284,7 +284,35 @@ jobs:
284284
slug: hashgraph/hedera-forking
285285

286286
foundry-example-tests:
287-
name: 'Foundry example tests w/mainnet'
287+
name: 'Foundry example tests'
288+
strategy:
289+
fail-fast: false
290+
matrix:
291+
solc: [
292+
# Ensures we use the `override` specifier
293+
# https://soliditylang.org/blog/2021/09/27/solidity-0.8.8-release-announcement/
294+
'0.8.7',
295+
296+
# Ensures we do not use `string.concat`
297+
# > General: string.concat now properly takes strings as arguments and returns string memory.
298+
# > It was accidentally introduced as a copy of bytes.concat before.
299+
# https://soliditylang.org/blog/2022/02/16/solidity-0.8.12-release-announcement/
300+
'0.8.11',
301+
302+
# Ensures we do not overload/use free functions
303+
# https://soliditylang.org/blog/2022/03/16/solidity-0.8.13-release-announcement/
304+
'0.8.12',
305+
306+
# Ensures we do not use "named parameters in mapping types"
307+
# See _Language Features_ https://soliditylang.org/blog/2023/02/01/solidity-0.8.18-release-announcement/
308+
'0.8.17',
309+
310+
# Ensures we do not use "qualified access to events from other contracts"
311+
# See _Qualified access to foreign events_ https://soliditylang.org/blog/2023/07/19/solidity-0.8.21-release-announcement/
312+
'0.8.19',
313+
314+
'0.8.24',
315+
]
288316
runs-on: smart-contracts-linux-medium
289317
steps:
290318
- name: Harden Runner
@@ -305,6 +333,9 @@ jobs:
305333
- name: Run Forge build on Foundry HTS example
306334
run: forge build
307335
working-directory: examples/foundry-hts
336+
env:
337+
# https://book.getfoundry.sh/reference/config/solidity-compiler#solc_version
338+
FOUNDRY_SOLC_VERSION: ${{ matrix.solc }}
308339

309340
- name: Run Forge HTS example tests using remote network with a pinned block number
310341
run: forge test -vv --fork-url mainnet --fork-block-number 72433403
@@ -393,7 +424,7 @@ jobs:
393424
working-directory: examples/foundry-hts
394425

395426
- name: Run Foundry script on local node
396-
run: forge script scripts/CreateToken.s.sol -vvv --rpc-url localnode --skip-simulation --broadcast
427+
run: forge script script/CreateToken.s.sol -vvv --rpc-url localnode --skip-simulation --broadcast
397428
working-directory: examples/foundry-hts
398429

399430
# https://book.getfoundry.sh/guides/scripting-with-solidity

README.md

Lines changed: 14 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -70,17 +70,17 @@ This is necessary because
7070
> - On Windows, it uses `Invoke-WebRequest` and `Start-Process` in PowerShell for a similar effect.
7171
7272
To activate HTS emulation in your tests, you need to add the following setup code in your test files.
73-
Import our wrapper function to deploy HTS emulation and enable cheat codes for it.
73+
Import our System Contracts `library` to deploy HTS emulation and enable cheat codes for it.
7474

7575
```solidity
76-
import {htsSetup} from "hedera-forking/contracts/htsSetup.sol";
76+
import {Hsc} from "hedera-forking/Hsc.sol";
7777
```
7878

7979
and then invoke it in your [test setup](https://book.getfoundry.sh/forge/writing-tests)
8080

8181
```solidity
8282
function setUp() public {
83-
htsSetup();
83+
Hsc.htsSetup();
8484
}
8585
```
8686

@@ -89,12 +89,12 @@ and then invoke it in your [test setup](https://book.getfoundry.sh/forge/writing
8989
Now you can use Hedera Token Services and remote tokens as if they were deployed locally when fork testing.
9090
For example
9191

92-
```solidity examples/foundry-hts/src/USDC.t.sol
92+
```solidity examples/foundry-hts/test/USDC.t.sol
9393
// SPDX-License-Identifier: Apache-2.0
9494
pragma solidity ^0.8.0;
9595
9696
import {Test} from "forge-std/Test.sol";
97-
import {htsSetup} from "hedera-forking/htsSetup.sol";
97+
import {Hsc} from "hedera-forking/Hsc.sol";
9898
import {IERC20} from "hedera-forking/IERC20.sol";
9999
import {IHederaTokenService} from "hedera-forking/IHederaTokenService.sol";
100100
import {HederaResponseCodes} from "hedera-forking/HederaResponseCodes.sol";
@@ -106,7 +106,7 @@ contract USDCExampleTest is Test {
106106
address private user1;
107107
108108
function setUp() external {
109-
htsSetup();
109+
Hsc.htsSetup();
110110
111111
user1 = makeAddr("user1");
112112
deal(USDC_mainnet, user1, 1000 * 10e8);
@@ -148,17 +148,17 @@ forge test --fork-url https://mainnet.hashio.io/api --fork-block-number 72433403
148148

149149
You can use all the tools and cheatcodes Foundry provides, _e.g._, `console.log`
150150

151-
```solidity examples/foundry-hts/src/USDCConsole.t.sol
151+
```solidity examples/foundry-hts/test/USDCConsole.t.sol
152152
// SPDX-License-Identifier: Apache-2.0
153153
pragma solidity ^0.8.0;
154154
155155
import {Test, console} from "forge-std/Test.sol";
156-
import {htsSetup} from "hedera-forking/htsSetup.sol";
156+
import {Hsc} from "hedera-forking/Hsc.sol";
157157
import {IERC20} from "hedera-forking/IERC20.sol";
158158
159159
contract USDCConsoleExampleTest is Test {
160160
function setUp() external {
161-
htsSetup();
161+
Hsc.htsSetup();
162162
}
163163
164164
function test_using_console_log() view external {
@@ -186,29 +186,27 @@ To enable Foundry Scripts to work with HTS, you can use `htsSetup()` as describe
186186
You can include
187187
For example
188188

189-
````solidity examples/foundry-hts/scripts/CreateToken.s.sol
189+
```solidity examples/foundry-hts/script/CreateToken.s.sol
190190
// SPDX-License-Identifier: Apache-2.0
191191
pragma solidity ^0.8.0;
192192
193193
import {Script, console} from "forge-std/Script.sol";
194194
import {HTS_ADDRESS} from "hedera-forking/HtsSystemContract.sol";
195195
import {IHederaTokenService} from "hedera-forking/IHederaTokenService.sol";
196196
import {HederaResponseCodes} from "hedera-forking/HederaResponseCodes.sol";
197-
import {htsSetup} from "hedera-forking/htsSetup.sol";
197+
import {Hsc} from "hedera-forking/Hsc.sol";
198198
199199
/**
200200
* Given how Foundry script works, the flag `--skip-simulation` is necessary.
201201
* For example
202202
*
203-
* ```
204203
* forge script scripts/CreateToken.s.sol -vvv --rpc-url testnet --skip-simulation --broadcast
205-
* ```
206204
*/
207205
contract CreateTokenScript is Script {
208206
uint256 PRIVATE_KEY = vm.envUint("PRIVATE_KEY");
209207
210208
function run() public {
211-
htsSetup();
209+
Hsc.htsSetup();
212210
213211
address signer = vm.addr(PRIVATE_KEY);
214212
console.log("Signer address %s", signer);
@@ -241,7 +239,7 @@ contract CreateTokenScript is Script {
241239
vm.stopBroadcast();
242240
}
243241
}
244-
````
242+
```
245243

246244
where `testnet` is an [RPC endpoint](https://book.getfoundry.sh/reference/config/testing#rpc_endpoints) declared in `foundry.toml`.
247245
For example
@@ -604,7 +602,7 @@ This allow us to ensure that all examples and tables are never outdated (if we c
604602
Code fences that contains a file name after the language definition, _e.g._,
605603

606604
````markdown
607-
```solidity examples/foundry-hts/src/USDC.t.sol
605+
```solidity examples/foundry-hts/test/USDC.t.sol
608606
```
609607
````
610608

contracts/Hsc.sol

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
// SPDX-License-Identifier: Apache-2.0
2+
pragma solidity ^0.8.0;
3+
4+
import {Vm} from "forge-std/Vm.sol";
5+
6+
import {HtsSystemContractJson, HTS_ADDRESS} from "./HtsSystemContractJson.sol";
7+
import {MirrorNode} from "./MirrorNode.sol";
8+
import {MirrorNodeFFI} from "./MirrorNodeFFI.sol";
9+
10+
/**
11+
* Library to deploy and setup System Contracts.
12+
*/
13+
library Hsc {
14+
Vm private constant vm = Vm(address(uint160(uint256(keccak256("hevm cheat code")))));
15+
16+
/**
17+
* @notice Sets up the HTS emulation contract.
18+
* The HTS emulation contract will be deployed at `0x167` address using `vm.etch`.
19+
*
20+
* Remember to enable [`ffi`](https://book.getfoundry.sh/cheatcodes/ffi)
21+
* in your Foundry project to use HTS contract in your tests.
22+
* You can do this by adding the following lines to your `.toml` file
23+
*
24+
* ```toml
25+
* [profile.default]
26+
* ffi = true
27+
* ```
28+
*
29+
* Alternatively, you can include the `--ffi` flag when running `forge`.
30+
*
31+
* This is necessary because our library uses `ffi` to fetch remote state from the Mirror Node.
32+
*
33+
* > DISCLAIMER
34+
* > The HTS emulation contract **SHOULD BE ONLY** used to ease development workflow when working with Hedera Tokens.
35+
* > The HTS emulation contract **DOES NOT** replicate Hedera Token Services fully.
36+
* > That is, behavior might differ when switching from local development to a real Hedera network.
37+
* > **Always test your contracts against a real Hedera network before launching your contracts.**
38+
*/
39+
function htsSetup() internal {
40+
htsSetup(new MirrorNodeFFI());
41+
}
42+
43+
function htsSetup(MirrorNode mirrorNode) internal {
44+
_deployCodeTo("HtsSystemContractJson.sol", HTS_ADDRESS);
45+
HtsSystemContractJson(HTS_ADDRESS).setMirrorNodeProvider(mirrorNode);
46+
vm.allowCheatcodes(HTS_ADDRESS);
47+
}
48+
49+
/**
50+
* @dev Taken from `StdCheats.sol:deployCodeTo`.
51+
* This is to avoid inheriting from `StdCheats`, and such simplifying usage.
52+
*/
53+
function _deployCodeTo(string memory what, address where) private {
54+
bytes memory creationCode = vm.getCode(what);
55+
vm.etch(where, creationCode);
56+
(bool success, bytes memory runtimeBytecode) = where.call("");
57+
require(success, "__deployCodeTo(string,address): Failed to create runtime bytecode.");
58+
vm.etch(where, runtimeBytecode);
59+
}
60+
}

0 commit comments

Comments
 (0)