Skip to content

Solidity

Versiune

Rulează pe Solidity v0.8.34 via Foundry și Forge Std v1.15.0 (preinstalat în lib/forge-std/).

Limbi suportate

Solidity

Framework de testare

Foundry (forge test) cu forge-std/Test.sol. Testele sunt scrise în Solidity, nu în JavaScript.

Structura proiectului

challenge/
├── foundry.toml            # configurare compiler + evm_version
├── Main.s.sol              # punct de intrare runCode (script Foundry)
├── src/                    # contractele tale
│   └── HelloWorld.sol
├── tests/                  # fișiere de test *.t.sol
│   └── HelloWorld.t.sol
├── lib/forge-std/          # preinstalat, gata de import
└── node_modules/           # pachete npm instalate de utilizator (OpenZeppelin etc.)

Recomandări speciale și detalii de implementare

Contract (src/HelloWorld.sol)

solidity
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.34;

contract HelloWorld {
    function helloWorld() public pure returns (string memory) {
        return "Hello World!";
    }
}

Test (tests/HelloWorld.t.sol)

solidity
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.34;

import "forge-std/Test.sol";
import "../src/HelloWorld.sol";

contract HelloWorldTest is Test {
    HelloWorld helloWorld;

    function setUp() public {
        helloWorld = new HelloWorld();
    }

    /// Should return "Hello World!"
    function testReturnsHelloWorld() public view {
        assertEq(helloWorld.helloWorld(), "Hello World!");
    }
}

Note despre teste:

  • Numele fișierului trebuie să se termine cu .t.sol.
  • Contractul de test trebuie să extindă Test din forge-std/Test.sol.
  • Numele funcțiilor de test trebuie să înceapă cu test. Folosește testFuzz* pentru intrări fuzzed, testFail* pentru teste de la care se așteaptă să eșueze (revert).
  • Un comentariu pe o singură linie (// …, /// … sau NatSpec /// @notice … / /// @dev …) scris direct deasupra fiecărei funcții de test devine eticheta lizibilă afișată în panoul de rezultate. Fără acesta, va fi afișat numele brut al funcției.

Scriptul Run Code (Main.s.sol în rădăcina proiectului)

solidity
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.34;

import "forge-std/Script.sol";
import "forge-std/console.sol";
import "./src/HelloWorld.sol";

contract Main is Script {
    function run() external {
        HelloWorld instance = new HelloWorld();
        console.log(instance.helloWorld());
    }
}

forge script rulează run() pe un EVM în memorie; orice output de la console.log este capturat în panoul de consolă Run Code. Nu este necesar un nod local (anvil) pentru interacțiuni simple de citire/implementare (deploy).

Depanare

console.log

Importă forge-std/console.sol și apelează console.log(...) de oriunde — inclusiv din funcții pure și view. Logurile apar în panoul de output Run Code (în timpul rulării forge script) și în panoul Tests (în timpul rulării forge test).

solidity
import "forge-std/console.sol";

function helloWorld() public pure returns (string memory) {
    console.log("helloWorld() was called");
    return "Hello World!";
}

Tipuri suportate: string, uint, int, bool, address, bytes, bytes32. Folosește console.logInt / console.logBytes atunci când rezoluția supraîncărcării (overload resolution) este ambiguă.

Cheatcodes

Din forge-std/Test.sol:

  • vm.prank(addr) — următoarea apelare este efectuată ca fiind addr.
  • vm.warp(ts) / vm.roll(bn) — călătorie în timp / suprascrierea numărului blocului.
  • vm.expectRevert() / vm.expectRevert("reason") — verifică (assert) dacă următorul apel eșuează (revert).
  • vm.expectEmit() — verifică dacă va fi emis un eveniment.
  • vm.deal(addr, amount) — setează soldul de ETH.

Aserțiuni

  • assertEq, assertTrue, assertFalse
  • assertGt, assertGe, assertLt, assertLe
  • assertApproxEqAbs(a, b, tolerance) / assertApproxEqRel(a, b, maxDelta)

Gestionarea pachetelor

Provocările Solidity suportă pachete bazate pe npm. Panoul Dependencies caută în registrul npm; instalează ceva precum @openzeppelin/contracts, alege o versiune, iar aceasta este adăugată în node_modules/. foundry.toml declară libs = ["lib", "node_modules"] cu auto_detect_remappings = true, astfel încât forge scanează ambele căi și generează automat remappări precum @openzeppelin/contracts/=node_modules/@openzeppelin/contracts/ la momentul compilării (build time).

solidity
import "@openzeppelin/contracts/utils/Strings.sol";

contract HelloWorld {
    using Strings for uint256;

    function helloWorld() public pure returns (string memory) {
        return string.concat("Hello World! ", uint256(42).toString());
    }
}

Nu este necesar remappings.txt — forge parcurge node_modules/ și generează automat remappările la momentul compilării.

Biblioteci incluse