all files / contracts/ Base.sol

100% Statements 20/20
100% Branches 14/14
100% Functions 7/7
100% Lines 24/24
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104                          1378× 1377×       1376×       1374×   1374×   1374×   1374×   1374×       3054× 3054× 2998×               3457×   3456× 3456× 3264×       7616×             139×                   6668×   6668×       6668×                 6662×                   69× 68×              
// SPDX-License-Identifier: GPL-2.0-or-later
 
pragma solidity ^0.8.0;
//import "hardhat/console.sol"; // DEV_MODE
 
import "./Storage.sol";
import "./Events.sol";
import "./Proxy.sol";
 
abstract contract Base is Storage, Events {
    // Modules
 
    function _createProxy(uint proxyModuleId) internal returns (address) {
        require(proxyModuleId != 0, "e/create-proxy/invalid-module");
        require(proxyModuleId <= MAX_EXTERNAL_MODULEID, "e/create-proxy/internal-module");
 
        // If we've already created a proxy for a single-proxy module, just return it:
 
        if (proxyLookup[proxyModuleId] != address(0)) return proxyLookup[proxyModuleId];
 
        // Otherwise create a proxy:
 
        address proxyAddr = address(new Proxy());
 
        if (proxyModuleId <= MAX_EXTERNAL_SINGLE_PROXY_MODULEID) proxyLookup[proxyModuleId] = proxyAddr;
 
        trustedSenders[proxyAddr] = TrustedSenderInfo({ moduleId: uint32(proxyModuleId), moduleImpl: address(0) });
 
        emit ProxyCreated(proxyAddr, proxyModuleId);
 
        return proxyAddr;
    }
 
    function callInternalModule(uint moduleId, bytes memory input) internal returns (bytes memory) {
        (bool success, bytes memory result) = moduleLookup[moduleId].delegatecall(input);
        if (!success) revertBytes(result);
        return result;
    }
 
 
 
    // Modifiers
 
    modifier nonReentrant() {
        require(reentrancyLock == REENTRANCYLOCK__UNLOCKED, "e/reentrancy");
 
        reentrancyLock = REENTRANCYLOCK__LOCKED;
        _;
        reentrancyLock = REENTRANCYLOCK__UNLOCKED;
    }
 
    modifier reentrantOK() { // documentation only
        _;
    }
 
    // Used to flag functions which do not modify storage, but do perform a delegate call
    // to a view function, which prohibits a standard view modifier. The flag is used to
    // patch state mutability in compiled ABIs and interfaces.
    modifier staticDelegate() {
        _;
    }
 
    // WARNING: Must be very careful with this modifier. It resets the free memory pointer
    // to the value it was when the function started. This saves gas if more memory will
    // be allocated in the future. However, if the memory will be later referenced
    // (for example because the function has returned a pointer to it) then you cannot
    // use this modifier.
 
    modifier FREEMEM() {
        uint origFreeMemPtr;
 
        assembly {
            origFreeMemPtr := mload(0x40)
        }
 
        _;
 
        /*
        assembly { // DEV_MODE: overwrite the freed memory with garbage to detect bugs
            let garbage := 0xDEADBEEFDEADBEEFDEADBEEFDEADBEEFDEADBEEFDEADBEEFDEADBEEFDEADBEEF
            for { let i := origFreeMemPtr } lt(i, mload(0x40)) { i := add(i, 32) } { mstore(i, garbage) }
        }
        */
 
        assembly {
            mstore(0x40, origFreeMemPtr)
        }
    }
 
 
 
    // Error handling
 
    function revertBytes(bytes memory errMsg) internal pure {
        if (errMsg.length > 0) {
            assembly {
                revert(add(32, errMsg), mload(errMsg))
            }
        }
 
        revert("e/empty-error");
    }
}