Home

Awesome

Proxy Factory

CircleCI License: AGPL v3

DISCLAIMER: Please do not use in production without taking the appropriate steps to ensure maximum security.

Overview

Set of base contracts to deploy and manage proxied contracts and implementation versions on chain, designed to be minimally opinionated, extensible and gas-efficient. These contracts were built to provide the necessary features to be reused across multiple projects, both within Maple and externally.

See maple-labs/maple-proxy-factory for an example on how to inherit and use for custom applications for factories and proxies.

Features

Contracts

ProxyFactory.sol

Responsible for deploying new Proxy instances and triggering initialization and migration logic atomically. NOTE: All factories that inherit ProxyFactory MUST also inherit IDefaultImplementationBeacon and implement defaultImplementation if the CREATE2 functionality of _newInstance is to be used.

contract ProxyFactory {

    /// @dev Deploys a new proxy for some version, with some initialization arguments, using `create` (i.e. factory's nonce determines the address).
    function _newInstance(uint256 version_, bytes memory arguments_) internal virtual returns (bool success_, address proxy_);

    /// @dev Deploys a new proxy, with some initialization arguments, using `create2` (i.e. salt determines the address).
    ///      This factory needs to be IDefaultImplementationBeacon, since the proxy will pull its implementation from it.
    function _newInstance(bytes memory arguments_, bytes32 salt_) internal virtual returns (bool success_, address proxy_);

    /// @dev Registers an implementation for some version.
    function _registerImplementation(uint256 version_, address implementation_) internal virtual returns (bool success_);

    /// @dev Registers a migrator for between two versions. If `fromVersion_ == toVersion_`, migrator is an initializer.
    function _registerMigrator(uint256 fromVersion_, uint256 toVersion_, address migrator_) internal virtual returns (bool success_);

    /// @dev Upgrades a proxy to a new version of an implementation, with some migration arguments.
    ///      Inheritor should revert on `success_ = false`, since proxy can be set to new implementation, but failed to migrate.
    function _upgradeInstance(address proxy_, uint256 toVersion_, bytes memory arguments_) internal virtual returns (bool success_);

    /// @dev Returns the deterministic address of a proxy given some salt.
    function _getDeterministicProxyAddress(bytes32 salt_) internal virtual view returns (address deterministicProxyAddress_);

    /// @dev Returns whether the account is currently a contract.
    function _isContract(address account_) internal view returns (bool isContract_);

}

SlotManipulatable.sol

Helper contract that can manually modify storage when necessary (i.e., during a initialization/migration process)

contract SlotManipulatable {

   /// @dev Returns the value stored at the given slot.
   function _getSlotValue(bytes32 slot_) internal view returns (bytes32 value_);

   /// @dev Sets the value stored at the given slot.
   function _setSlotValue(bytes32 slot_, bytes32 value_) internal;

   // @dev Returns the storage slot for a reference type.
   function _getReferenceTypeSlot(bytes32 slot_, bytes32 key_) internal pure returns (bytes32 value_);

}

Proxied.sol

Contract that must be inherited by all implementation contracts in order for them to function properly with proxies.

contract Proxied {

   /// @dev Delegatecalls to a migrator contract to manipulate storage during an initialization or migration.
   function _migrate(address migrator_, bytes calldata arguments_) internal virtual returns (bool success_);

   /// @dev Sets the factory address in storage.
   function _setFactory(address factory_) internal virtual returns (bool success_);

   /// @dev Sets the implementation address in storage.
   function _setImplementation(address implementation_) internal virtual returns (bool success_);

   /// @dev Returns the factory address.
   function _factory() internal view virtual returns (address factory_);

   /// @dev Returns the implementation address.
   function _implementation() internal view virtual returns (address implementation_)

}

Setup

This project was built using dapptools.

git clone git@github.com:maple-labs/proxy-factory.git
cd proxy-factory
dapp update

Running Tests

Security

The code is designed to be highly flexible and extensible, meaning that logic that is usually part of these functions (e.g., access controls) was not included. Therefore it is strongly advised that these contracts be implemented with proper sanity checks, access controls and any extra logic necessary for security.

Audit Reports

AuditorReport link
Trail of BitsToB - Dec 28, 2021
Code 4renaC4 - Jan 5, 2022

Bug Bounty

For all information related to the ongoing bug bounty for these contracts run by Immunefi, please visit this site.

About Maple

Maple is a decentralized corporate credit market. Maple provides capital to institutional borrowers through globally accessible fixed-income yield opportunities.

For all technical documentation related to the Maple protocol, please refer to the GitHub wiki.


<p align="center"> <img src="https://user-images.githubusercontent.com/44272939/196706799-fe96d294-f700-41e7-a65f-2d754d0a6eac.gif" height="100" /> </p>