0

I am unable to compile a contract that references a local variable in in-line assembly.

Here is the code:

pragma solidity ^0.5.0;

/**
 * @dev Contract module that helps prevent reentrant calls to a function.
 *
 * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier
 * available, which can be applied to functions to make sure there are no nested
 * (reentrant) calls to them.
 *
 * Note that because there is a single `nonReentrant` guard, functions marked as
 * `nonReentrant` may not call one another. This can be worked around by making
 * those functions `private`, and then adding `external` `nonReentrant` entry
 * points to them.
 *
 * TIP: If you would like to learn more about reentrancy and alternative ways
 * to protect against it, check out our blog post
 * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].
 *
 * _Since v2.5.0:_ this module is now much more gas efficient, given net gas
 * metering changes introduced in the Istanbul hardfork.
 */
contract ReentrancyGuard {
    /// Address of lock flag variable.
    /// Flag is placed at random memory location to not interfere with Storage contract.
    uint constant private LOCK_FLAG_ADDRESS = 0x8e94fed44239eb2314ab7a406345e6c5a8f0ccedf3b600de3d004e672c33abf4; // keccak256("ReentrancyGuard") - 1;

    function initializeReentrancyGuard () internal {
        // Storing an initial non-zero value makes deployment a bit more
        // expensive, but in exchange the refund on every call to nonReentrant
        // will be lower in amount. Since refunds are capped to a percetange of
        // the total transaction's gas, it is best to keep them low in cases
        // like this one, to increase the likelihood of the full refund coming
        // into effect.
        assembly { sstore(LOCK_FLAG_ADDRESS, 1) }
    }

    /**
     * @dev Prevents a contract from calling itself, directly or indirectly.
     * Calling a `nonReentrant` function from another `nonReentrant`
     * function is not supported. It is possible to prevent this from happening
     * by making the `nonReentrant` function external, and make it call a
     * `private` function that does the actual work.
     */
    modifier nonReentrant() {
        bool notEntered;
        assembly { notEntered := sload(LOCK_FLAG_ADDRESS) }

        // On the first call to nonReentrant, _notEntered will be true
        require(notEntered, "ReentrancyGuard: reentrant call");

        // Any calls to nonReentrant after this point will fail
        assembly { sstore(LOCK_FLAG_ADDRESS, 0) }

        _;

        // By storing the original value once again, a refund is triggered (see
        // https://eips.ethereum.org/EIPS/eip-2200)
        assembly { sstore(LOCK_FLAG_ADDRESS, 1) }
    }
}

I get the following error:

use experimental features on live deployments.
pragma experimental ABIEncoderV2;
^-------------------------------^

IEIP1271.sol:13:3: TypeError: Function overload clash during conversion to external types for arguments.
  function isValidSignature(
  ^ (Relevant source part starts here and spans across multiple lines).

generated/ReentrancyGuard.sol:34:27: TypeError: Constant variables not supported by inline assembly.
        assembly { sstore(LOCK_FLAG_ADDRESS, 1) }
                          ^---------------^

generated/ReentrancyGuard.sol:46:40: TypeError: Constant variables not supported by inline assembly.
        assembly { notEntered := sload(LOCK_FLAG_ADDRESS) }
                                       ^---------------^

generated/ReentrancyGuard.sol:52:27: TypeError: Constant variables not supported by inline assembly.
        assembly { sstore(LOCK_FLAG_ADDRESS, 0) }
                          ^---------------^

generated/ReentrancyGuard.sol:58:27: TypeError: Constant variables not supported by inline assembly.
        assembly { sstore(LOCK_FLAG_ADDRESS, 1) }
                          ^---------------^

dev-contracts/generated/ReentrancyGuard.sol:34:27: TypeError: Constant variables not supported by inline assembly.
        assembly { sstore(LOCK_FLAG_ADDRESS, 1) }
                          ^---------------^

dev-contracts/generated/ReentrancyGuard.sol:46:40: TypeError: Constant variables not supported by inline assembly.
        assembly { notEntered := sload(LOCK_FLAG_ADDRESS) }
                                       ^---------------^

dev-contracts/generated/ReentrancyGuard.sol:52:27: TypeError: Constant variables not supported by inline assembly.
        assembly { sstore(LOCK_FLAG_ADDRESS, 0) }
                          ^---------------^

dev-contracts/generated/ReentrancyGuard.sol:58:27: TypeError: Constant variables not supported by inline assembly.
        assembly { sstore(LOCK_FLAG_ADDRESS, 1) }
                          ^---------------^

Error: Compilation failed
    at processOutput (/Users/samueldare/Documents/Code/brave/zksync/contracts/node_modules/@ethereum-waffle/compiler/dist/cjs/compiler.js:36:15)
    at compileAndSave (/Users/samueldare/Documents/Code/brave/zksync/contracts/node_modules/@ethereum-waffle/compiler/dist/cjs/compiler.js:17:11)

I would appreciate any pointers.

3
  • Your contract compiles fine on solc 0.6.12. Oct 6, 2020 at 18:31
  • And also on 0.5.13. Oct 6, 2020 at 18:33
  • Thanks!! The issue is that 0.5.0 does not allow access local variables from in line assembly. Bumped it up to 0.5.11 and it works
    – 0xsegfault
    Oct 6, 2020 at 18:45

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Browse other questions tagged or ask your own question.