### Direct import examples Source: https://docs.soliditylang.org/en/v0.8.37/path-resolution.html Shows various direct import statements that do not start with './' or '../'. Each import path becomes the source unit name directly, including paths with leading slashes, package-style names, and URLs. ```solidity import "/project/lib/util.sol"; // source unit name: /project/lib/util.sol import "lib/util.sol"; // source unit name: lib/util.sol import "@openzeppelin/address.sol"; // source unit name: @openzeppelin/address.sol import "https://example.com/token.sol"; // source unit name: https://example.com/token.sol ``` -------------------------------- ### Install Solidity via Homebrew Source: https://docs.soliditylang.org/en/v0.8.37/installing-solidity.html Updates Homebrew, adds the Ethereum tap, and installs the latest Solidity compiler. Pre-built bottles are not supported; this builds from source. ```bash brew update brew upgrade brew tap ethereum/ethereum brew install solidity ``` -------------------------------- ### Install specific Solidity version from Homebrew formula Source: https://docs.soliditylang.org/en/v0.8.37/installing-solidity.html Unlinks the current Solidity installation and installs a specific version from the local formula file. The example installs version 0.4.8. ```bash brew unlink solidity # eg. Install 0.4.8 brew install solidity.rb ``` -------------------------------- ### Yul example of memory tracking and compile-time Keccak256 Source: https://docs.soliditylang.org/en/v0.8.37/internals/optimizer.html This Yul example shows how to the same example as the assembly version, showing the equivalent Yul code with inline comments, and optimized compiler can evaluate. This is the equivalent Yul code from the source. ```yul let x := calldataload(0) mstore(x, 100) let value := keccak256(x, 32) ``` -------------------------------- ### Install development version of solc via snap (edge) Source: https://docs.soliditylang.org/en/v0.8.37/installing-solidity.html Installs the latest development version of Solidity with the most recent changes using the snap package's edge channel. ```bash sudo snap install solc --edge ``` -------------------------------- ### Build Solidity with build.sh on Linux/macOS Source: https://docs.soliditylang.org/en/v0.8.37/installing-solidity.html Easier build script for Linux and macOS that installs the solc and soltest binaries to usr/local/bin. Requires external dependencies to be installed first. ```bash #note: this will install binaries solc and soltest at usr/local/bin ./scripts/build.sh ``` -------------------------------- ### Install latest stable solc via snap Source: https://docs.soliditylang.org/en/v0.8.37/installing-solidity.html Installs the latest stable version of the Solidity compiler using the snap package. The snap uses strict confinement, limiting file access to /home and /media directories. ```bash sudo snap install solc ``` -------------------------------- ### Call a contract with abi.encodeWithSignature and require success Source: https://docs.soliditylang.org/en/v0.8.37/types.html Use to call a contract that does not adhere to the ABI or to get more direct control over encoding. The call returns a success condition and the returned data. The example encodes a function call with abi.encodeWithSignature and requires success. ```solidity bytes memory payload = abi.encodeWithSignature("register(string)", "MyName"); (bool success, bytes memory returnData) = address(nameReg).call(payload); require(success); ``` -------------------------------- ### Query balance and send Ether with transfer Source: https://docs.soliditylang.org/en/v0.8.37/types.html Shows how to query the balance of an address and send Ether to a payable address using the transfer function. The example declares a payable address and a regular address, then checks balances before transferring 10 wei. ```solidity address payable x = payable(0x123); address myAddress = address(this); if (x.balance < 10 && myAddress.balance >= 10) x.transfer(10); ``` -------------------------------- ### Relative import examples with non-normalized paths Source: https://docs.soliditylang.org/en/v0.8.37/path-resolution.html Shows how relative imports resolve when the import paths are not normalized, using the importing file lib/src/../contract.sol. The examples illustrate the effect of . and .. segments and multiple slashes on the resolved source unit name. ```solidity import "./util/./util.sol"; // source unit name: lib/src/../util/util.sol import "./util//util.sol"; // source unit name: lib/src/../util/util.sol import "../util/../array/util.sol"; // source unit name: lib/src/array/util.sol import "../.././../util.sol"; // source unit name: util.sol import "../../.././../util.sol"; // source unit name: util.sol ``` -------------------------------- ### Yul Object Example with Sub-objects and Data Source: https://docs.soliditylang.org/en/v0.8.37/yul.html Shows a complete Yul object with constructor code, a deployed sub-object, and embedded data. Demonstrates using datasize, dataoffset, and datacopy to access sub-objects and data. The example includes a factory contract pattern and a data table. ```yul // A contract consists of a single object with sub-objects representing // the code to be deployed or other contracts it can create. // The single "code" node is the executable code of the object. // Every (other) named object or data section is serialized and // made accessible to the special built-in functions datacopy / dataoffset / datasize // The current object, sub-objects and data items inside the current object // are in scope. object "Contract1" { // This is the constructor code of the contract. code { function allocate(size) -> ptr { ptr := mload(0x40) // Note that Solidity generated IR code reserves memory offset ``0x60`` as well, but a pure Yul object is free to use memory as it chooses. if iszero(ptr) { ptr := 0x60 } mstore(0x40, add(ptr, size)) } // first create "Contract2" let size := datasize("Contract2") let offset := allocate(size) // This will turn into codecopy for EVM datacopy(offset, dataoffset("Contract2"), size) // constructor parameter is a single number 0x1234 mstore(add(offset, size), 0x1234) pop(create(0, offset, add(size, 32))) // now return the runtime object (the currently // executing code is the constructor code) size := datasize("Contract1_deployed") offset := allocate(size) // This will turn into a codecopy for EVM datacopy(offset, dataoffset("Contract1_deployed"), size) return(offset, size) } data "Table2" hex"4123" object "Contract1_deployed" { code { function allocate(size) -> ptr { ptr := mload(0x40) // Note that Solidity generated IR code reserves memory offset ``0x60`` as well, but a pure Yul object is free to use memory as it chooses. if iszero(ptr) { ptr := 0x60 } mstore(0x40, add(ptr, size)) } // runtime code mstore(0, "Hello, World!") return(0, 0x20) } } // Embedded object. Use case is that the outside is a factory contract, // and Contract2 is the code to be created by the factory object "Contract2" { code { // code here ... } object "Contract2_deployed" { code { // code here ... } } data "Table1" hex"4123" } } ``` -------------------------------- ### External function types example (Oracle) Source: https://docs.soliditylang.org/en/v0.8.37/types.html Example using external function types. The Oracle contract stores a callback function in a struct and invokes it in reply(). OracleUser passes this.oracleResponse as the callback and restricts calls to the known Oracle address. ```solidity // SPDX-License-Identifier: GPL-3.0 pragma solidity >=0.4.22 <0.9.0; contract Oracle { struct Request { bytes data; function(uint) external callback; } Request[] private requests; event NewRequest(uint); function query(bytes memory data, function(uint) external callback) public { requests.push(Request(data, callback)); emit NewRequest(requests.length - 1); } function reply(uint requestID, uint response) public { // Here goes the check that the reply comes from a trusted source requests[requestID].callback(response); } } contract OracleUser { Oracle constant private ORACLE_CONST = Oracle(address(0x00000000219ab540356cBB839Cbe05303d7705Fa)); // known contract uint private exchangeRate; function buySomething() public { ORACLE_CONST.query("USD", this.oracleResponse); } function oracleResponse(uint response) public { require( msg.sender == address(ORACLE_CONST), "Only oracle can call this." ); exchangeRate = response; } } ``` -------------------------------- ### Delete operator example contract Source: https://docs.soliditylang.org/en/v0.8.37/types.html Example contract demonstrating the use of the delete operator on state variables and arrays in Solidity. The contract declares a uint and a dynamic array, which are the targets for delete operations described in the surrounding documentation. ```solidity // SPDX-License-Identifier: GPL-3.0 pragma solidity >=0.4.0 <0.9.0; contract DeleteExample { uint data; uint[] dataArray; ``` -------------------------------- ### MappingExample contract using _allowances Source: https://docs.soliditylang.org/en/v0.8.37/types.html Example contract that uses a nested mapping `_allowances` to record how much someone else is allowed to withdraw from your account. It implements `allowance`, `transferFrom`, `approve`, and an internal `_transfer` function with ERC20-style checks and events. ```solidity // SPDX-License-Identifier: GPL-3.0 pragma solidity >=0.4.22 <0.9.0; contract MappingExample { mapping(address => uint256) private _balances; mapping(address => mapping(address => uint256)) private _allowances; event Transfer(address indexed from, address indexed to, uint256 value); event Approval(address indexed owner, address indexed spender, uint256 value); function allowance(address owner, address spender) public view returns (uint256) { return _allowances[owner][spender]; } function transferFrom(address sender, address recipient, uint256 amount) public returns (bool) { require(_allowances[sender][msg.sender] >= amount, "ERC20: Allowance not high enough."); _allowances[sender][msg.sender] -= amount; _transfer(sender, recipient, amount); return true; } function approve(address spender, uint256 amount) public returns (bool) { require(spender != address(0), "ERC20: approve to the zero address"); _allowances[msg.sender][spender] = amount; emit Approval(msg.sender, spender, amount); return true; } function _transfer(address sender, address recipient, uint256 amount) internal { require(sender != address(0), "ERC20: transfer from the zero address"); require(recipient != address(0), "ERC20: transfer to the zero address"); require(_balances[sender] >= amount, "ERC20: Not enough funds."); _balances[sender] -= amount; _balances[recipient] += amount; emit Transfer(sender, recipient, amount); } } ``` -------------------------------- ### Define and use structs in a CrowdFunding contract Source: https://docs.soliditylang.org/en/v0.8.37/types.html Defines structs both outside and inside a contract, and shows how to use storage references to initialize and update struct fields. The example avoids assigning a memory struct that contains a mapping directly to storage. ```solidity // SPDX-License-Identifier: GPL-3.0 pragma solidity >=0.6.2 <0.9.0; // Defines a new type with two fields. // Declaring a struct outside of a contract allows // it to be shared by multiple contracts. // Here, this is not really needed. struct Funder { address addr; uint amount; } contract CrowdFunding { // Structs can also be defined inside contracts, which makes them // visible only there and in derived contracts. struct Campaign { address payable beneficiary; uint fundingGoal; uint numFunders; uint amount; mapping(uint => Funder) funders; } uint numCampaigns; mapping(uint => Campaign) campaigns; function newCampaign(address payable beneficiary, uint goal) public returns (uint campaignID) { campaignID = numCampaigns++; // campaignID is return variable // We cannot use "campaigns[campaignID] = Campaign(beneficiary, goal, 0, 0)" // because the right hand side creates a memory-struct "Campaign" that contains a mapping. Campaign storage c = campaigns[campaignID]; c.beneficiary = beneficiary; c.fundingGoal = goal; } function contribute(uint campaignID) public payable { Campaign storage c = campaigns[campaignID]; // Creates a new temporary memory struct, initialised with the given values // and copies it over to storage. // Note that you can also use Funder(msg.sender, msg.value) to initialise. c.funders[c.numFunders++] = Funder({addr: msg.sender, amount: msg.value}); c.amount += msg.value; } } ``` -------------------------------- ### Solidity storage and memory array data location example Source: https://docs.soliditylang.org/en/v0.8.37/types.html Shows how storage and memory arrays behave in Solidity: assigning a storage pointer, copying a memory array to storage, and passing storage references to internal functions. The commented lines illustrate operations that are not allowed, such as assigning a memory array to a storage local variable or deleting a storage pointer. ```solidity // The data location of memoryArray is memory. function f(uint[] memory memoryArray) public { x = memoryArray; // works, copies the whole array to storage uint[] storage y = x; // works, assigns a pointer, data location of y is storage y[7]; // fine, returns the 8th element y.pop(); // fine, modifies x through y delete x; // fine, clears the array, also modifies y // The following does not work; it would need to create a new temporary / // unnamed array in storage, but storage is "statically" allocated: // y = memoryArray; // Similarly, "delete y" is not valid, as assignments to local variables // referencing storage objects can only be made from existing storage objects. // It would "reset" the pointer, but there is no sensible location it could point to. // For more details see the documentation of the "delete" operator. // delete y; g(x); // calls g, handing over a reference to x h(x); // calls h and creates an independent, temporary copy in memory } function g(uint[] storage) internal pure {} function h(uint[] memory) public pure {} } ``` -------------------------------- ### Adjust gas with call{gas: 1000000} Source: https://docs.soliditylang.org/en/v0.8.37/types.html Adjust the supplied gas for a low-level call using the gas modifier. The example sets a gas limit of 1000000. ```solidity address(nameReg).call{gas: 1000000}(abi.encodeWithSignature("register(string)", "MyName")); ``` -------------------------------- ### Using external function type members (address and selector) Source: https://docs.soliditylang.org/en/v0.8.37/types.html Shows how to use the address and selector members of external function types. The contract Example defines a payable function f and uses this.f.address and this.f.selector to access the function's address and selector. The function g demonstrates calling f with explicit gas and value using the {gas: 10, value: 800} syntax, which replaced the deprecated .gas() and .value() members. ```solidity // SPDX-License-Identifier: GPL-3.0 pragma solidity >=0.6.4 <0.9.0; contract Example { function f() public payable returns (bytes4) { assert(this.f.address == address(this)); return this.f.selector; } function g() public { this.f{gas: 10, value: 800}(); } } ``` -------------------------------- ### checkGoalReached function in crowdfunding contract Source: https://docs.soliditylang.org/en/v0.8.37/types.html Part of a crowdfunding contract example. Uses a storage reference to a struct to check if the funding goal is reached and send the funds to the beneficiary. Demonstrates that assigning a struct to a local variable with storage location does not copy but references the state. ```solidity function checkGoalReached(uint campaignID) public returns (bool reached) { Campaign storage c = campaigns[campaignID]; if (c.amount < c.fundingGoal) return false; uint amount = c.amount; c.amount = 0; (bool success, ) = c.beneficiary.call{value: amount}(""); return success; } } ``` -------------------------------- ### Control Ether value with call{value: 1 ether} Source: https://docs.soliditylang.org/en/v0.8.37/types.html Control the supplied Ether value for a low-level call using the value modifier. The example sends 1 ether. ```solidity address(nameReg).call{value: 1 ether}(abi.encodeWithSignature("register(string)", "MyName")); ``` -------------------------------- ### Relative import examples for /project/lib/math.sol Source: https://docs.soliditylang.org/en/v0.8.37/path-resolution.html Shows how relative imports resolve when the importing file is /project/lib/math.sol. The first import resolves to /project/lib/util.sol and the second to /project/token.sol. ```solidity import "./util.sol" as util; // source unit name: /project/lib/util.sol import "../token.sol" as token; // source unit name: /project/token.sol ``` -------------------------------- ### Relative import examples for lib/math.sol Source: https://docs.soliditylang.org/en/v0.8.37/path-resolution.html Shows how relative imports resolve when the importing file is lib/math.sol. The first import resolves to lib/util.sol and the second to token.sol. ```solidity import "./util.sol" as util; // source unit name: lib/util.sol import "../token.sol" as token; // source unit name: token.sol ``` -------------------------------- ### Build Solidity on Windows command line (Release) Source: https://docs.soliditylang.org/en/v0.8.37/installing-solidity.html Builds Solidity on Windows from the command line using the Release configuration. Run after configuring with the Visual Studio generator. ```bash cmake --build . --config Release ``` -------------------------------- ### Type information JSON example Source: https://docs.soliditylang.org/en/v0.8.37/internals/layout_in_storage.html Example of a type entry in the storage layout, showing the fields encoding, label, and numberOfBytes. ```json { "encoding": "inplace", "label": "uint256", "numberOfBytes": "32" } ``` -------------------------------- ### Install Windows dependencies with helper script Source: https://docs.soliditylang.org/en/v0.8.37/installing-solidity.html Run this PowerShell script to install all required external dependencies (boost and cmake) into the deps subdirectory. ```powershell scripts\install_deps.ps1 ``` -------------------------------- ### Basic import remapping with solc and Solidity import Source: https://docs.soliditylang.org/en/v0.8.37/path-resolution.html Sets up a remapping so imports from github.com/ethereum/dapp-bin/ are redirected to dapp-bin/. The compiler looks for the file in the VFS under dapp-bin/library/math.sol; if not found, the Host Filesystem Loader searches /project/dapp-bin/library/math.sol. Remapping information is stored in contract metadata, so changes affect bytecode. ```bash solc github.com/ethereum/dapp-bin/=dapp-bin/ --base-path /project source.sol ``` ```solidity import "github.com/ethereum/dapp-bin/library/math.sol"; // source unit name: dapp-bin/library/math.sol ``` -------------------------------- ### Install solcjs with npm Source: https://docs.soliditylang.org/en/v0.8.37/installing-solidity.html Installs the solcjs Solidity compiler globally via npm. The command-line executable is named solcjs and its options are not compatible with solc. ```bash npm install --global solc ```