Ethereum Archives - Justin Silver https://www.justinsilver.com/tag/ethereum/ Technology, Travel, and Pictures Wed, 07 Aug 2024 20:12:58 +0000 en-US hourly 1 https://wordpress.org/?v=6.8.1 https://www.justinsilver.com/wp-content/uploads/2013/06/cropped-apple-touch-icon-160x160.png Ethereum Archives - Justin Silver https://www.justinsilver.com/tag/ethereum/ 32 32 Slither & Echidna + Remappings https://www.justinsilver.com/technology/blockchain/slither-echidna-remappings/?utm_source=rss&utm_medium=rss&utm_campaign=slither-echidna-remappings https://www.justinsilver.com/technology/blockchain/slither-echidna-remappings/#comments Mon, 09 Jan 2023 19:16:00 +0000 https://www.justinsilver.com/?p=5357 While testing a project using hardhat and Echidna I was able to run all tests in the project with echidna-test . but was not able to run tests in a specific contract that imported...

The post Slither & Echidna + Remappings appeared first on Justin Silver.

]]>
AmpedSense.OptimizeAdSpot('AP'); AmpedSense.OptimizeAdSpot('IL'); AmpedSense.OptimizeAdSpot('IR');

While testing a project using hardhat and Echidna I was able to run all tests in the project with echidna-test . but was not able to run tests in a specific contract that imported contracts using NPM and the node_modules directory, such as @openzeppelin. When running echidna-test the following error would be returned

> echidna-test path/to/my/Contract.sol --contract Contract

echidna-test: Couldn't compile given file
stdout:
stderr:
ERROR:CryticCompile:Invalid solc compilation Error: Source "@openzeppelin/contracts/utils/Address.sol" not found: File not found. Searched the following locations: "".
 --> path/to/my/Contract.sol:4:1:
  |
4 | import {Address} from '@openzeppelin/contracts/utils/Address.sol';
  | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

To fix this, I added Solc Remappings for Slither and Echidna.

Install Echidna (and Slither)

Make sure that you have Slither and Echidna installed. Follow the install instructions on their site, or on OSX with Homebrew run brew install echidna

Slither Remapping Config

Create a Slither JSON config file – named slither.config.json – to use filter_paths to exclude some directories and provide remappings for node_modules to solc.

{
  "filter_paths": "(mocks/|test/|@openzeppelin/)",
  "solc_remaps": "@=node_modules/@"
}

Slither will pick up the config file automatically.

slither path/to/my/Contract.sol

For multiple remappings using an array of strings for solc_remaps.

{
  "filter_paths": "(mocks/|test/|@openzeppelin/)",
  "solc_remaps": [
    "@openzeppelin/contracts/=node_modules/@openzeppelin/contracts/",
    "@openzeppelin/contracts-upgradeable/=node_modules/@openzeppelin/contracts-upgradeable/"
  ]
}

Note that if you are using Hardhat or similar for your projects, slither will use it for the compile if a configuration can be found.

slither .

To force a particular compiler, specify it with the command.

slither --compile-force-framework solc ./contracts

Echidna Remapping Config

For Echidna we can create a YAML config file and pass the solc remappings to crytic-compile via cryticArgs.

# provide solc remappings to crytic-compile
cryticArgs: ['--solc-remaps', '@=node_modules/@']

When running echidna-test we can use the --config option to specify the YAML config file and pick up our remappings (and other settings).

echidna-test --config echidna.yaml path/to/my/Contract.sol --contract Contract

Bonus Mythril Remapping Config!

{
  "remappings": ["@openzeppelin/=node_modules/@openzeppelin/"]
}
myth analyze --solc-json mythril.solc.json path/to/my/Contract.sol

The post Slither & Echidna + Remappings appeared first on Justin Silver.

]]>
https://www.justinsilver.com/technology/blockchain/slither-echidna-remappings/feed/ 2
UnsafeMath for Solidity 0.8.0+ https://www.justinsilver.com/technology/programming/unsafemath-for-solidity-0-8-0/?utm_source=rss&utm_medium=rss&utm_campaign=unsafemath-for-solidity-0-8-0 https://www.justinsilver.com/technology/programming/unsafemath-for-solidity-0-8-0/#respond Thu, 21 Jul 2022 14:18:17 +0000 https://www.justinsilver.com/?p=5107 UPDATE: Check out the @0xdoublesharp/unsafe-math module available on NPM for an easy to use, prepackaged, and tested version of this library! UnsafeMath is a Solidity library used to perform unchecked, or “unsafe”, math operations....

The post UnsafeMath for Solidity 0.8.0+ appeared first on Justin Silver.

]]>
AmpedSense.OptimizeAdSpot('AP'); AmpedSense.OptimizeAdSpot('IL'); AmpedSense.OptimizeAdSpot('IR');

UPDATE: Check out the @0xdoublesharp/unsafe-math module available on NPM for an easy to use, prepackaged, and tested version of this library!

UnsafeMath is a Solidity library used to perform unchecked, or “unsafe”, math operations. Prior to version 0.8.0 all math was unchecked meaning that subtracting 1 from 0 would underflow and result in the max uint256 value. This behavior led many contracts to use the OpenZeppelin SafeMath library to performed checked math – using the prior example subtracting 1 from 0 would throw an exception as a uint256 is unsigned and therefore cannot be negative. In Solidity 0.8.0+ all math operations became checked, but at a cost of more gas used per operation.

Unchecked Math Library

The UnsafeMath library allows you to perform unchecked math operations where you are confident the result will not be an underflow or an overflow of the uint256 space – saving gas in your contracts where checked math is not needed.

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

// solhint-disable func-name-mixedcase

library UnsafeMath {
    function unsafe_add(uint256 a, uint256 b) internal pure returns (uint256) {
        unchecked {
            return a + b;
        }
    }

    function unsafe_sub(uint256 a, uint256 b) internal pure returns (uint256) {
        unchecked {
            return a - b;
        }
    }

    function unsafe_div(uint256 a, uint256 b) internal pure returns (uint256) {
        unchecked {
            uint256 result;
            // solhint-disable-next-line no-inline-assembly
            assembly {
                result := div(a, b)
            }
            return result;
        }
    }

    function unsafe_mul(uint256 a, uint256 b) internal pure returns (uint256) {
        unchecked {
            return a * b;
        }
    }

    function unsafe_increment(uint256 a) internal pure returns (uint256) {
        unchecked {
            return ++a;
        }
    }

    function unsafe_decrement(uint256 a) internal pure returns (uint256) {
        unchecked {
            return --a;
        }
    }
}

Gas Usage Tests

This test contract uses the UnsafeMath.unsafe_decrement() and Unsafe.unsafe_decrement() functions alongside their checked counterparts to test the difference in gas used between the different methods.

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

import './UnsafeMath.sol';

contract TestUnsafeMath {
    using UnsafeMath for uint256;

    uint256 private _s_foobar;

    function safeDecrement(uint256 count) public {
        for (uint256 i = count; i > 0; --i) {
            _s_foobar = i;
        }
    }

    function safeIncrement(uint256 count) public {
        for (uint256 i = 0; i < count; ++i) {
            _s_foobar = i;
        }
    }

    function unsafeDecrement(uint256 count) public {
        for (uint256 i = count; i > 0; i = i.unsafe_decrement()) {
            _s_foobar = i;
        }
    }

    function unsafeIncrement(uint256 count) public {
        for (uint256 i = 0; i < count; i = i.unsafe_increment()) {
            _s_foobar = i;
        }
    }
}

Using a simple Mocha setup, our tests will call each of the contract functions with an argument for 100 iterations.

import { ethers } from 'hardhat';
import { ContractFactory } from '@ethersproject/contracts';
import { TestUnsafeMath } from '../sdk/types';

describe('UnsafeMath', () => {
  let testUnsafeMathDeploy: ContractFactory, testUnsafeMathContract: TestUnsafeMath;

  beforeEach(async () => {
    testUnsafeMathDeploy = await ethers.getContractFactory('TestUnsafeMath', {});
    testUnsafeMathContract = (await testUnsafeMathDeploy.deploy()) as TestUnsafeMath;
  });

  describe('Gas Used', async () => {
    it('safeDecrement gas used', async () => {
      const tx = await testUnsafeMathContract.safeDecrement(100);
      // const receipt = await tx.wait();
      // console.log(receipt.gasUsed.toString(), 'gasUsed');
    });
    
    it('safeIncrement gas used', async () => {
      const tx = await testUnsafeMathContract.safeIncrement(100);
      // const receipt = await tx.wait();
      // console.log(receipt.gasUsed.toString(), 'gasUsed');
    });
    
    it('unsafeDecrement gas used', async () => {
      const tx = await testUnsafeMathContract.unsafeDecrement(100);
      // const receipt = await tx.wait();
      // console.log(receipt.gasUsed.toString(), 'gasUsed');
    });
    
    it('unsafeIncrement gas used', async () => {
      const tx = await testUnsafeMathContract.unsafeIncrement(100);
      // const receipt = await tx.wait();
      // console.log(receipt.gasUsed.toString(), 'gasUsed');
    });
  });
});

The results show that a checked incrementing loop used 60276 gas, checked decrementing used 59424 gas, unchecked incrementing used 58117 gas, and unchecked decrementing came in at 57473 gas.

That’s a savings of 2803 gas on a 100 iteration loop, or 4.55% of the total gas used.


  UnsafeMath
    Gas Used
      ✓ safeDecrement gas used
      ✓ safeIncrement gas used
      ✓ unsafeDecrement gas used
      ✓ unsafeIncrement gas used

·--------------------------------------|---------------------------|----------------|-----------------------------·
|         Solc version: 0.8.15         ·  Optimizer enabled: true  ·  Runs: 999999  ·  Block limit: 30000000 gas  │
·······································|···························|················|······························
|  Methods                                                                                                        │
···················|···················|·············|·············|················|···············|··············
|  Contract        ·  Method           ·  Min        ·  Max        ·  Avg           ·  # calls      ·  usd (avg)  │
···················|···················|·············|·············|················|···············|··············
|  TestUnsafeMath  ·  safeDecrement    ·          -  ·          -  ·         59424  ·            1  ·          -  │
···················|···················|·············|·············|················|···············|··············
|  TestUnsafeMath  ·  safeIncrement    ·          -  ·          -  ·         60276  ·            1  ·          -  │
···················|···················|·············|·············|················|···············|··············
|  TestUnsafeMath  ·  unsafeDecrement  ·          -  ·          -  ·         57473  ·            1  ·          -  │
···················|···················|·············|·············|················|···············|··············
|  TestUnsafeMath  ·  unsafeIncrement  ·          -  ·          -  ·         58117  ·            1  ·          -  │
···················|···················|·············|·············|················|···············|··············
|  Deployments                         ·                                            ·  % of limit   ·             │
·······································|·············|·············|················|···············|··············
|  TestUnsafeMath                      ·          -  ·          -  ·        188806  ·        0.6 %  ·          -  │
·--------------------------------------|-------------|-------------|----------------|---------------|-------------·

  4 passing (2s)

The post UnsafeMath for Solidity 0.8.0+ appeared first on Justin Silver.

]]>
https://www.justinsilver.com/technology/programming/unsafemath-for-solidity-0-8-0/feed/ 0