Smart Deployer

Smart Deployer is a universal architecture for organizing and managing paid smart contract deployments.

This solution allows developers to:

  • Create their own Smart Deployer (DeployManager.sol)
  • Create & connect utility contracts using template
  • Monetize the deployment of utility contracts

The repository is currently under development. We are building it as part of the Solidity University Bootcamp program.

👉 More details: bootcamp.solidity.university

Contents

DeployManager

Git Source

Inherits: IDeployManager, Ownable, ERC165

Author: Solidity University

Allows users to deploy utility contracts by cloning registered templates.

Uses OpenZeppelin's Clones and Ownable; assumes templates implement IUtilityContract.

State Variables

deployedContracts

mapping(address => address[]) public deployedContracts;

contractsData

mapping(address => ContractInfo) public contractsData;

Functions

constructor

constructor() payable Ownable(msg.sender);

deploy

Deploys a new utility contract

Emits NewDeployment event

function deploy(address _utilityContract, bytes calldata _initData) external payable override returns (address);

Parameters

NameTypeDescription
_utilityContractaddressThe address of the utility contract template
_initDatabytesThe initialization data for the utility contract

Returns

NameTypeDescription
<none>addressThe address of the deployed utility contract

addNewContract

function addNewContract(address _contractAddress, uint256 _fee, bool _isActive) external override onlyOwner;

updateFee

function updateFee(address _contractAddress, uint256 _newFee) external override onlyOwner;

deactivateContract

function deactivateContract(address _address) external override onlyOwner;

activateContract

function activateContract(address _address) external override onlyOwner;

supportsInterface

function supportsInterface(bytes4 interfaceId) public view virtual override(IERC165, ERC165) returns (bool);

Structs

ContractInfo

struct ContractInfo {
    uint256 fee;
    bool isActive;
    uint256 registredAt;
}

IDeployManager

Git Source

Inherits: IERC165

Author: Solidity Univesity

This interface defines the functions, errors and events for the DeployManager contract.

Functions

deploy

Deploys a new utility contract

Emits NewDeployment event

function deploy(address _utilityContract, bytes calldata _initData) external payable returns (address);

Parameters

NameTypeDescription
_utilityContractaddressThe address of the utility contract template
_initDatabytesThe initialization data for the utility contract

Returns

NameTypeDescription
<none>addressThe address of the deployed utility contract

addNewContract

function addNewContract(address _contractAddress, uint256 _fee, bool _isActive) external;

updateFee

function updateFee(address _contractAddress, uint256 _newFee) external;

deactivateContract

function deactivateContract(address _contractAddress) external;

activateContract

function activateContract(address _contractAddress) external;

Events

NewContractAdded

Emitted when a new utility contract template is registered.

event NewContractAdded(address indexed _contractAddress, uint256 _fee, bool _isActive, uint256 _timestamp);

Parameters

NameTypeDescription
_contractAddressaddressAddress of the registered utility contract template.
_feeuint256Fee (in wei) required to deploy a clone of this contract.
_isActiveboolWhether the contract is active and deployable.
_timestampuint256Timestamp when the contract was added.

ContractFeeUpdated

event ContractFeeUpdated(address indexed _contractAddress, uint256 _oldFee, uint256 _newFee, uint256 _timestamp);

ContractStatusUpdated

event ContractStatusUpdated(address indexed _contractAddress, bool _isActive, uint256 _timestamp);

NewDeployment

event NewDeployment(address indexed _deployer, address indexed _contractAddress, uint256 _fee, uint256 _timestamp);

Errors

ContractNotActive

Reverts if the contract is not active

error ContractNotActive();

NotEnoughtFunds

Not enough funds to deploy the contract

error NotEnoughtFunds();

ContractDoesNotRegistered

Reverts if the contract is not registered

error ContractDoesNotRegistered();

InitializationFailed

Reverts if the .initialize() function fails

error InitializationFailed();

ContractIsNotUtilityContract

Reverts if the contract is not a utility contract

error ContractIsNotUtilityContract();

Contents

ERC1155Airdroper

Git Source

Inherits: AbstractUtilityContract, Ownable

State Variables

MAX_AIRDROP_BATCH_SIZE

uint256 public constant MAX_AIRDROP_BATCH_SIZE = 10;

token

IERC1155 public token;

treasury

address public treasury;

Functions

constructor

constructor() payable Ownable(msg.sender);

airdrop

function airdrop(address[] calldata receivers, uint256[] calldata amounts, uint256[] calldata tokenIds)
    external
    onlyOwner;

initialize

function initialize(bytes memory _initData) external override notInitialized returns (bool);

getInitData

function getInitData(address _deployManager, address _token, address _treasury, address _owner)
    external
    pure
    returns (bytes memory);

Errors

ReceiversLengthMismatch

error ReceiversLengthMismatch();

AmountsLengthMismatch

error AmountsLengthMismatch();

BatchSizeExceeded

error BatchSizeExceeded();

NeedToApproveTokens

error NeedToApproveTokens();

Contents

ERC20Airdroper

Git Source

Inherits: AbstractUtilityContract, Ownable

Author: Solidity University

This contract allows the owner to airdrop ERC20 tokens to multiple addresses.

Inherits from AbstractUtilityContract and Ownable

State Variables

MAX_AIRDROP_BATCH_SIZE

uint256 public constant MAX_AIRDROP_BATCH_SIZE = 300;

token

IERC20 public token;

amount

uint256 public amount;

treasury

address public treasury;

Functions

constructor

constructor() payable Ownable(msg.sender);

airdrop

function airdrop(address[] calldata receivers, uint256[] calldata amounts) external onlyOwner;

initialize

function initialize(bytes memory _initData) external override notInitialized returns (bool);

getInitData

function getInitData(address _deployManager, address _token, uint256 _amount, address _treasury, address _owner)
    external
    pure
    returns (bytes memory);

Errors

ArraysLengthMismatch

error ArraysLengthMismatch();

NotEnoughApprovedTokens

error NotEnoughApprovedTokens();

TransferFailed

error TransferFailed();

BatchSizeExceeded

error BatchSizeExceeded();

Contents

ERC721Airdroper

Git Source

Inherits: AbstractUtilityContract, Ownable

State Variables

MAX_AIRDROP_BATCH_SIZE

uint256 public constant MAX_AIRDROP_BATCH_SIZE = 300;

token

IERC721 public token;

treasury

address public treasury;

Functions

constructor

constructor() payable Ownable(msg.sender);

airdrop

function airdrop(address[] calldata receivers, uint256[] calldata tokenIds) external onlyOwner;

initialize

function initialize(bytes memory _initData) external override notInitialized returns (bool);

getInitData

function getInitData(address _deployManager, address _token, address _treasury, address _owner)
    external
    pure
    returns (bytes memory);

Errors

ArraysLengthMismatch

error ArraysLengthMismatch();

NeedToApproveTokens

error NeedToApproveTokens();

BatchSizeExceeded

error BatchSizeExceeded();

Contents

AbstractUtilityContract

Git Source

Inherits: IUtilityContract, ERC165

Author: Solidity University

This abstract contract provides a base implementation for utility contracts.

Utility contracts should inherit from this contract and implement the initialize function.

State Variables

initialized

bool public initialized;

deployManager

address public deployManager;

Functions

notInitialized

modifier notInitialized();

initialize

function initialize(bytes memory _initData) external virtual override returns (bool);

setDeployManager

function setDeployManager(address _deployManager) internal virtual;

validateDeployManager

function validateDeployManager(address _deployManager) internal view returns (bool);

getDeployManager

function getDeployManager() external view virtual override returns (address);

supportsInterface

function supportsInterface(bytes4 interfaceId) public view virtual override(IERC165, ERC165) returns (bool);

IUtilityContract

Git Source

Inherits: IERC165

Author: Solidity University

This interface defines the functions and events for utility contracts.

Utility contracts should implement this interface to be compatible with the DeployManager.

Functions

initialize

Initializes the utility contract with the provided data

This function should be called by the DeployManager after deploying the contract

function initialize(bytes memory _initData) external returns (bool);

Parameters

NameTypeDescription
_initDatabytesThe initialization data for the utility contract

Returns

NameTypeDescription
<none>boolTrue if the initialization was successful

getDeployManager

function getDeployManager() external view returns (address);

Errors

DeployManagerCannotBeZero

Reverts if the deploy manager is not set or is invalid

error DeployManagerCannotBeZero();

NotDeployManager

error NotDeployManager();

FailedToDeployManager

error FailedToDeployManager();

AlreadyInitialized

error AlreadyInitialized();

Contents

IVesting

Git Source

Provides a standard interface for token vesting contracts

Functions

claim

Claims all tokens currently available for the caller according to their vesting schedule

function claim() external;

startVesting

Creates a new vesting schedule for a beneficiary

function startVesting(VestingParams calldata params) external;

Parameters

NameTypeDescription
paramsVestingParamsStruct containing the parameters for the new vesting schedule

vestedAmount

Returns the total amount of tokens vested for a beneficiary at the current time

function vestedAmount(address _claimer) external view returns (uint256);

Parameters

NameTypeDescription
_claimeraddressAddress of the beneficiary

Returns

NameTypeDescription
<none>uint256Amount of tokens vested

claimableAmount

Returns the amount of tokens that can currently be claimed by a beneficiary

function claimableAmount(address _claimer) external view returns (uint256);

Parameters

NameTypeDescription
_claimeraddressAddress of the beneficiary

Returns

NameTypeDescription
<none>uint256Amount of tokens claimable

withdrawUnallocated

Withdraws all unallocated tokens from the contract to the specified address

function withdrawUnallocated(address _to) external;

Parameters

NameTypeDescription
_toaddressAddress to receive the withdrawn tokens

getVestingInfo

Returns the information about a vesting schedule for a beneficiary

function getVestingInfo(address _claimer) external view returns (VestingInfo memory);

Parameters

NameTypeDescription
_claimeraddressAddress of the beneficiary

Returns

NameTypeDescription
<none>VestingInfoVestingInfo struct containing the vesting information

getInitData

Returns the ABI-encoded initialization data for the contract

function getInitData(address _deployManager, address _token, address _owner) external view returns (bytes memory);

Parameters

NameTypeDescription
_deployManageraddressAddress of the deploy manager
_tokenaddressAddress of the ERC20 token
_owneraddressAddress of the contract owner

Returns

NameTypeDescription
<none>bytesABI-encoded initialization data

Events

VestingCreated

Emitted when a new vesting schedule is created

event VestingCreated(address indexed beneficiary, uint256 amount, uint256 creationTime);

Parameters

NameTypeDescription
beneficiaryaddressAddress of the beneficiary
amountuint256Total number of tokens to be vested
creationTimeuint256Timestamp when the vesting schedule was created

TokensWithdrawn

Emitted when tokens are withdrawn from the contract

event TokensWithdrawn(address indexed to, uint256 amount);

Parameters

NameTypeDescription
toaddressAddress receiving the withdrawn tokens
amountuint256Number of tokens withdrawn

Claim

Emitted when a beneficiary claims vested tokens

event Claim(address indexed beneficiary, uint256 amount, uint256 timestamp);

Parameters

NameTypeDescription
beneficiaryaddressAddress of the beneficiary
amountuint256Number of tokens claimed
timestampuint256Timestamp when the claim was made

Errors

VestingNotFound

Reverts if the vesting schedule does not exist for the beneficiary

error VestingNotFound();

ClaimNotAvailable

Reverts if the claim is not yet available

error ClaimNotAvailable(uint256 blockTimestamp, uint256 availableFrom);

Parameters

NameTypeDescription
blockTimestampuint256Current block timestamp
availableFromuint256Timestamp when the claim becomes available

NothingToClaim

Reverts if there are no tokens available to claim

error NothingToClaim();

InfsufficientBalance

Reverts if the contract does not have enough tokens to allocate

error InfsufficientBalance(uint256 availableBalance, uint256 totalAmount);

Parameters

NameTypeDescription
availableBalanceuint256Number of tokens currently available in the contract
totalAmountuint256Number of tokens required for vesting

VestingAlreadyExist

Reverts if a vesting schedule already exists for the beneficiary

error VestingAlreadyExist();

AmountCantBeZero

Reverts if the specified amount is zero

error AmountCantBeZero();

StartTimeShouldBeFuture

Reverts if the vesting start time is not in the future

error StartTimeShouldBeFuture(uint256 startTime, uint256 blockTimestamp);

Parameters

NameTypeDescription
startTimeuint256The specified start time
blockTimestampuint256The current block timestamp

DurationCantBeZero

Reverts if the vesting duration is zero

error DurationCantBeZero();

CooldownCantBeLongerThanDuration

Reverts if the claim cooldown period is longer than the vesting duration

error CooldownCantBeLongerThanDuration();

InvalidBeneficiary

Reverts if the beneficiary address is invalid

error InvalidBeneficiary();

BelowMinimalClaimAmount

Reverts if the claimable amount is less than the minimum claim amount

error BelowMinimalClaimAmount(uint256 minClaimAmount, uint256 claimable);

Parameters

NameTypeDescription
minClaimAmountuint256The minimum claimable amount
claimableuint256The actual claimable amount

CooldownNotPassed

Reverts if the required cooldown period between claims has not passed

error CooldownNotPassed(uint256 blockTimestamp, uint256 lastClaimTime);

Parameters

NameTypeDescription
blockTimestampuint256The current block timestamp
lastClaimTimeuint256The timestamp of the last claim

NothingToWithdraw

Reverts if there are no tokens available to withdraw

error NothingToWithdraw();

Structs

VestingInfo

Information about a beneficiary's vesting schedule

struct VestingInfo {
    uint256 totalAmount;
    uint256 startTime;
    uint256 cliff;
    uint256 duration;
    uint256 claimed;
    uint256 lastClaimTime;
    uint256 claimCooldown;
    uint256 minClaimAmount;
    bool created;
}

Properties

NameTypeDescription
totalAmountuint256Total number of tokens to be vested
startTimeuint256Timestamp when vesting begins
cliffuint256Duration of the cliff period in seconds
durationuint256Total duration of the vesting period in seconds
claimeduint256Amount of tokens already claimed
lastClaimTimeuint256Timestamp of the last claim
claimCooldownuint256Minimum time interval between claims in seconds
minClaimAmountuint256Minimum amount that can be claimed in a single transaction
createdboolIndicates whether the vesting schedule has been created

VestingParams

Parameters for creating a new vesting schedule in startVesting function

struct VestingParams {
    address beneficiary;
    uint256 totalAmount;
    uint256 startTime;
    uint256 cliff;
    uint256 duration;
    uint256 claimCooldown;
    uint256 minClaimAmount;
}

Properties

NameTypeDescription
beneficiaryaddressAddress that will receive vested tokens
totalAmountuint256Total number of tokens to be vested
startTimeuint256Timestamp when vesting begins
cliffuint256Duration of the cliff period in seconds
durationuint256Total duration of the vesting period in seconds
claimCooldownuint256Minimum time interval between claims in seconds
minClaimAmountuint256Minimum amount that can be claimed in a single transaction

Vesting

Git Source

Inherits: IVesting, AbstractUtilityContract, Ownable

Manages token vesting schedules for beneficiaries

Inherits IVesting, AbstractUtilityContract, Ownable

State Variables

token

The ERC20 token that is being vested

IERC20 public token;

allocatedTokens

The total amount of tokens that have been allocated for vesting

uint256 public allocatedTokens;

vestings

A mapping of beneficiary addresses to their vesting information

mapping(address => IVesting.VestingInfo) public vestings;

Functions

constructor

Initializes the contract with deploy manager, token, and owner

constructor() payable Ownable(msg.sender);

claim

Claims all tokens currently available for the caller according to their vesting schedule

function claim() public;

startVesting

Creates a new vesting schedule for a beneficiary

function startVesting(IVesting.VestingParams calldata params) external onlyOwner;

Parameters

NameTypeDescription
paramsIVesting.VestingParamsStruct containing the parameters for the new vesting schedule

withdrawUnallocated

Withdraws all unallocated tokens from the contract to the specified address

function withdrawUnallocated(address _to) external onlyOwner;

Parameters

NameTypeDescription
_toaddressAddress to receive the withdrawn tokens

initialize

function initialize(bytes memory _initData) external override notInitialized returns (bool);

vestedAmount

Returns the total amount of tokens vested for a beneficiary at the current time

function vestedAmount(address _claimer) public view returns (uint256);

Parameters

NameTypeDescription
_claimeraddressAddress of the beneficiary

Returns

NameTypeDescription
<none>uint256Amount of tokens vested

claimableAmount

Returns the amount of tokens that can currently be claimed by a beneficiary

function claimableAmount(address _claimer) public view returns (uint256);

Parameters

NameTypeDescription
_claimeraddressAddress of the beneficiary

Returns

NameTypeDescription
<none>uint256Amount of tokens claimable

getVestingInfo

Returns the information about a vesting schedule for a beneficiary

function getVestingInfo(address _claimer) public view returns (IVesting.VestingInfo memory);

Parameters

NameTypeDescription
_claimeraddressAddress of the beneficiary

Returns

NameTypeDescription
<none>IVesting.VestingInfoVestingInfo struct containing the vesting information

getInitData

Returns the ABI-encoded initialization data for the contract

function getInitData(address _deployManager, address _token, address _owner) external pure returns (bytes memory);

Parameters

NameTypeDescription
_deployManageraddressAddress of the deploy manager
_tokenaddressAddress of the ERC20 token
_owneraddressAddress of the contract owner

Returns

NameTypeDescription
<none>bytesABI-encoded initialization data

VestingLib

Git Source

Provides utility functions for calculating vested and claimable token amounts

Functions

vestedAmount

Calculates the total amount of tokens vested for a given vesting schedule at the current time

function vestedAmount(IVesting.VestingInfo storage v) internal view returns (uint256);

Parameters

NameTypeDescription
vIVesting.VestingInfoThe vesting information struct

Returns

NameTypeDescription
<none>uint256The total amount of tokens vested

claimableAmount

Calculates the amount of tokens currently claimable by the beneficiary

function claimableAmount(IVesting.VestingInfo storage v) internal view returns (uint256);

Parameters

NameTypeDescription
vIVesting.VestingInfoThe vesting information struct

Returns

NameTypeDescription
<none>uint256The amount of tokens that can be claimed

ERC20Mock

Git Source

Inherits: ERC20

Functions

constructor

constructor(address recipient) payable ERC20("MyToken", "MTK");