Secure Smart Contract library for Solidity with upgradeable implementations of standards like ERC20 and ERC721, flexible role-based permissioning schemes, and reusable components for building custom contracts and complex decentralized systems.
—
Quality
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Core upgradeability infrastructure including the Initializable base contract and UUPS upgrade pattern for implementing upgradeable smart contracts with secure state preservation.
Foundational contract that controls the initialization of upgradeable contracts.
/**
* @dev Helper to support initializer functions
*/
abstract contract Initializable {
/**
* @dev Triggered when the contract has been initialized or reinitialized
*/
event Initialized(uint64 version);
/**
* @dev Modifier used by the initializer function of a contract
*/
modifier initializer();
/**
* @dev Modifier used by reinitializer functions
*/
modifier reinitializer(uint64 version);
/**
* @dev Modifier that restricts functions to the initializing phase
*/
modifier onlyInitializing();
/**
* @dev Locks the contract, preventing any future reinitialization
*/
function _disableInitializers() internal;
/**
* @dev Returns the highest version that has been initialized
*/
function _getInitializedVersion() internal view returns (uint64);
/**
* @dev Returns true if the contract is currently initializing
*/
function _isInitializing() internal view returns (bool);
}Universal Upgradeable Proxy Standard implementation that allows contracts to upgrade themselves.
/**
* @dev Implementation of the UUPS (Universal Upgradeable Proxy Standard) pattern
*/
abstract contract UUPSUpgradeable {
function __UUPSUpgradeable_init() internal onlyInitializing;
/**
* @dev The version of the upgrade interface of the contract
*/
string constant UPGRADE_INTERFACE_VERSION = "5.0.0";
/**
* @dev Storage slot with the address of the current implementation
*/
bytes32 internal constant IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;
/**
* @dev Upgrade the implementation of the proxy to newImplementation and call a function on the new implementation
*/
function upgradeToAndCall(address newImplementation, bytes memory data) external payable;
/**
* @dev Returns the current implementation address
*/
function proxiableUUID() external view returns (bytes32);
/**
* @dev Function that should revert when msg.sender is not authorized to upgrade the contract
*/
function _authorizeUpgrade(address newImplementation) internal virtual;
/**
* @dev Returns the current implementation address
*/
function _getImplementation() internal view returns (address);
/**
* @dev Stores a new address in the EIP-1967 implementation slot
*/
function _setImplementation(address newImplementation) private;
}
// Events
event Upgraded(address indexed implementation);All upgradeable contracts use ERC-7201 namespaced storage to prevent storage collisions:
// Example storage pattern used in upgradeable contracts
struct ContractNameStorage {
// Contract state variables
mapping(address => uint256) _balances;
uint256 _totalSupply;
string _name;
string _symbol;
}
// Storage location calculation
bytes32 private constant ContractNameStorageLocation =
keccak256(abi.encode(uint256(keccak256("openzeppelin.storage.ContractName")) - 1)) & ~bytes32(uint256(0xff));
function _getContractNameStorage() private pure returns (ContractNameStorage storage $) {
assembly {
$.slot := ContractNameStorageLocation
}
}Standard initialization pattern for upgradeable contracts:
// Internal initialization functions
function __ContractName_init(/* parameters */) internal onlyInitializing {
__ContractName_init_unchained(/* parameters */);
}
function __ContractName_init_unchained(/* parameters */) internal onlyInitializing {
ContractNameStorage storage $ = _getContractNameStorage();
// Initialize contract state
}import {Initializable} from "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol";
import {UUPSUpgradeable} from "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol";
import {OwnableUpgradeable} from "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol";
contract MyUpgradeableContract is Initializable, UUPSUpgradeable, OwnableUpgradeable {
uint256 public value;
/// @custom:oz-upgrades-unsafe-allow constructor
constructor() {
_disableInitializers();
}
function initialize(address initialOwner, uint256 initialValue) initializer public {
__Ownable_init(initialOwner);
__UUPSUpgradeable_init();
value = initialValue;
}
function setValue(uint256 newValue) public onlyOwner {
value = newValue;
}
function _authorizeUpgrade(address newImplementation) internal override onlyOwner {}
}import {ERC20Upgradeable} from "@openzeppelin/contracts-upgradeable/token/ERC20/ERC20Upgradeable.sol";
import {UUPSUpgradeable} from "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol";
import {OwnableUpgradeable} from "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol";
contract UpgradeableToken is ERC20Upgradeable, UUPSUpgradeable, OwnableUpgradeable {
/// @custom:oz-upgrades-unsafe-allow constructor
constructor() {
_disableInitializers();
}
function initialize(
string memory name,
string memory symbol,
address initialOwner,
uint256 initialSupply
) initializer public {
__ERC20_init(name, symbol);
__Ownable_init(initialOwner);
__UUPSUpgradeable_init();
if (initialSupply > 0) {
_mint(initialOwner, initialSupply);
}
}
function mint(address to, uint256 amount) public onlyOwner {
_mint(to, amount);
}
function _authorizeUpgrade(address newImplementation) internal override onlyOwner {}
}// Upgraded version of the contract with new functionality
contract MyUpgradeableContractV2 is MyUpgradeableContract {
uint256 public newFeature;
function initializeV2(uint256 newFeatureValue) reinitializer(2) public {
newFeature = newFeatureValue;
}
function setNewFeature(uint256 newValue) public onlyOwner {
newFeature = newValue;
}
function getVersion() public pure returns (string memory) {
return "2.0.0";
}
}// Example deployment script for upgradeable contracts
import {ERC1967Proxy} from "@openzeppelin/contracts/proxy/ERC1967/ERC1967Proxy.sol";
contract DeployUpgradeable {
function deploy() external returns (address) {
// Deploy implementation
MyUpgradeableContract implementation = new MyUpgradeableContract();
// Encode initializer call
bytes memory data = abi.encodeCall(
MyUpgradeableContract.initialize,
(msg.sender, 100) // initialOwner, initialValue
);
// Deploy proxy
ERC1967Proxy proxy = new ERC1967Proxy(address(implementation), data);
return address(proxy);
}
}Always disable initializers in the constructor to prevent initialization of the implementation contract:
/// @custom:oz-upgrades-unsafe-allow constructor
constructor() {
_disableInitializers();
}For contracts that may be inherited, consider adding storage gaps:
// Reserve storage slots for future variables
uint256[50] private __gap;Always implement proper authorization for upgrades:
function _authorizeUpgrade(address newImplementation) internal override onlyOwner {
// Additional upgrade validation logic can be added here
}Install with Tessl CLI
npx tessl i tessl/npm-openzeppelin--contracts-upgradeable