PricedRound
Inherits: Credentialed, StateAware, BoardControlled, IPricedRound
Author: Daniel Yamagata
A contract for starting a priced round that emulates traditional priced rounds in Venture Capital financing
Priced rounds are deployed and instantiated by the Equity Financing module. They are deployed via OpenZeppelin Clones (i.e. ERC1167 Minimal Proxies).
Invariants:
The number of '_shares' held by this contract is greater than or equal to the number of shares released
The amount of the '_denominationAsset' held by this contract is greater than or equal to the amount of the denomination asset released*
State Variables
MIN_INVESTOR_ALLOCATION
PricedRoundStorageLocation
Functions
_getPricedRoundStorage
constructor
init
Opens a round and initializes the state variables
Initializer. The shares must be supported by the treasury. Otherwise, this function will revert. The 'controller' of the contract will be the 'initTreasury'
Parameters
__PricedRound_init
unlockStartDate
unlockDuration
Returns the unlock duration in seconds. Shares will be unlocked linearly over this period once claimed via the Token Timelock
unlockCliff
Returns the unlock cliff in seconds. The 'initialUnlock' will be unlocked once this cliff has passed
initialUnlockPercentage
The percentage of shares that will be unlocked initially once the 'unlockCliff' has passed
All percentages are denominated in Constants.PRECISION_FACTOR, which is 100_000
minimumRaise
The minimum amount of funds to be raised for the round for it to be able to be closed. Can be extended with increaseMinimumRaise()
Returns the value in the units of the denomination asset. Must divide by the units on a frontend to get the nominal value
targetRaise
The maximum amount of funds to be raised. Can be extended with extendRound()
Returns the value in the units of the denomination asset. Must divide by the units on a frontend to get the nominal value
shares
The shares used for the round. Transferred to either the Token Timelock or an investor when claimed depending on the unlock arguments
allottedShares
The cumulative amount of shares that have been allotted to investors who have contributed to the round. Allotted shares does not account for allocations
totalSharesForRound
The number of shares allocated to the round
totalRaised
The current total amount of funds raised in the units of the denomination asset
Must divide by the units on a frontend to get the nominal value
denominationAsset
The denomination asset of the round. Used by the investor to invest in the round.
pricePerShare
The price per share of the round in the units of the 'denominationAsset'
Must divide by the units on a frontend to get the nominal value
roundState
Returns the state of the round as a RoundState enum:
0: Open
1: Closed
2: Filled
3: Canceled
increaseMinimumRaise
Increases the minimum raise by 'minimumRaiseExtension'. The new minimum raise must be less than the target raise. This function can only be called if the round is 'Open' or 'Filled'. This function should be used cautiously: the minimum raise cannot be decreased once increased
This function will revert if the sum of 'minimumRaise' and 'minimumRaiseExtension' is greater than type(uint128).max
Parameters
extendRound
Cache
This function will revert if the sum of 'targetRaiseExtension' and 'targetRaise' or the sum of 'totalSharesExtensiion' and 'totalSharesForRound' are greater than uint128, which is extremely unlikely
Parameters
cancelRound
Cache
A round can only be canceled only if it is 'Open' or 'Filled'
closeRound
Cache
A round can only be closed only if it is 'Open' or 'Filled'. The 'totalRaised' must be greater than or equal to the 'minimumRaise'. Otherwise, this function will revert.
setInvestorAllocation
Delete unnecessary vars that are only used when a round is 'open
Once set, an allocation should not be reset using this function. It should be increased or decreased by 'increaseInvestorAllocation' and 'decreaseInvestorAllocation' accordingly. Otherwise, the investor is capable of frontrunning any changes to their allocation via this function.
Parameters
increaseInvestorShareAllocation
Increases the investor's share allocation by the specified amount. Only callable by the 'owner'
Used to avoid race conditions. Repeated use of 'setInvestorAllocation' could lead to exploitation similar to how a malicious actor can exploit 'approve' in place of 'increaseAllowance' for ERC20s
Parameters
decreaseInvestorShareAllocation
Decreases the investor's share allocation by the specified amount. Only callable by the 'owner'
Used to avoid race conditions.
Parameters
investInRound
Transfers the investor's allocation from the investor to this contract. Allots their owed shares accordingly
'expectedDiscountOrPremium' and 'expectedNumberOfShares' is used to avoid frontrunning attacks by the company. Otherwise, the owner can frontrun the investor by calling 'setInvestorAllocation' and increase their premium or number of shares unknowingly
Parameters
claimShares
Calculate the amount of the denom asset to transfer that it will be negligible to the round. However, it is still accounted for Update state
Shares are claimable only if the round is 'Closed'
Returns
revokeInvestment
Sends the caller's investment back to them, forgoing their shares in the round. The round must be 'Open' or 'Filled'
Will revert if the caller does not have an investment
recoupInvestment
Withdraws the investment of the 'investor' for a 'Canceled' round. This function is callable by anyone. Anyone can recoup an investor's investment on their behalf.
Parameters
calculateAdjustedPricePerShare
Returns the adjusted price per share given the 'discountOrPremium'
Parameters
remainingShares
Returns the remaining shares that can be allotted to investors
remainingDenominationAsset
Returns the remaining denomination asset that can be raised
getInvestors
Returns all the investors who have contributed to the round
Returns
getAllocatedAddresses
Returns all addresses that currently have an allocation
Returns
getInvestment
Returns the investment of the 'investor', which includes their investment amount and the shares they are owed
Returns
getAllocation
Returns the allocation of the 'investor', which includes the number of shares they are allocated and their discount or premium
Returns
getInvestmentAmountForAllocation
Returns the implied investment amount in the denomination asset for the allocation of the 'investor'
Returns the value in the units of the denomination asset. Must divide by the units on a frontend to get the nominal value
getImpliedOutstandingValuation
Returns the implied pre-money outstanding valuation of the company in the denomination asset
Returns the value in the units of the denomination asset. Must divide by the units on a frontend to get the nominal value
Returns
getImpliedFullyDilutedValuation
Returns the implied pre-money fully diluted valuation of the company in the denomination asset
Returns the value in the units of the denomination asset. Must divide by the units on a frontend to get the nominal value
Returns
coreId
Returns the coreId of the implementation as a bytes32
The core ID is the keccak256 hash of the contract name followed by a version under the following syntax: "mezzanine.coreId.ContractName.vX" For example, the core ID of the 2nd version of the Treasury would be the following: keccak256(abi.encodePacked("mezzanine.coreId.Treasury.v2"))
version
Returns the version of the implementation as a uint256
supportsInterface
See {IERC165-supportsInterface}.
_reverseInvestment
Sends the investor's investment back to them. Updates state accordingly
Returns
_calculateInvestmentAmount
Update state
The 'pricePerShare' is in the denomination asset's units. We make the necessary adjustments here
_calculateAdjustedPricePerShare
'discountOrPremium' implictly converted from a int128 to a int256
_deleteAllocations
Deletes all the allocations
_validateRoundStateOpen
Validates that the round state is 'Open'
_validateRoundStateOpenOrFilled
Validates that the round state is 'Open' or 'Filled'
_validateInitArgs
_validateRaiseAmounts
Validates that the '_minimumRaise' is less than or equal to the '_targetRaise'
_validateDiscountOrPremium
Validates a 'discountOrPremium' value. A negative value is a discount, and a positive value is a premium A discount should never be below 100% (i.e. Constants.PRECISION_FACTOR), while a premium should never be above 500% (i.e. 5 * Constants.PRECISION_FACTOR)
_checkInvariants
Asserts that the cumulative shares and denomination asset deposited is greater than or equal to the cumulative shares and denomination asset released, respectively
Structs
PricedRoundStorage
Last updated