Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 16 additions & 1 deletion contracts/Aelin.sol
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,9 @@ error UnauthorizedMinter();
error InvalidAddress();

contract Aelin is ERC20, Ownable {
// Initial supply set to 10M tokens as stated in AELIP-50
/**
* NOTE Set to 10M tokens as stated in AELIP-50.
*/
uint256 public constant INITIAL_SUPPLY = 10 * 1e6 * 1e18;

address public authorizedMinter;
Expand All @@ -17,15 +19,28 @@ contract Aelin is ERC20, Ownable {
_mint(_initialHolder, INITIAL_SUPPLY);
}

/**
* @notice The mint function for the Aelin token. Only the authorized minted can mint new tokens.
* @param _receiver The recipient of the new tokens.
* @param _amount The amount of tokens that will be recieved.
*/
function mint(address _receiver, uint256 _amount) external {
if (msg.sender != authorizedMinter) revert UnauthorizedMinter();
_mint(_receiver, _amount);
}

/**
* @notice The burn function for the Aelin token.
* @param _amount The amount to be burned.
*/
function burn(uint256 _amount) external {
_burn(msg.sender, _amount);
}

/**
* @notice This functions sets the authorized minter for the Aelin token.
* @param _minter The new authorized minter.
*/
function setAuthorizedMinter(address _minter) external onlyOwner {
if (_minter == address(0)) revert InvalidAddress();
authorizedMinter = _minter;
Expand Down
106 changes: 67 additions & 39 deletions contracts/AelinDeal.sol
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,7 @@ contract AelinDeal is AelinVestingToken, MinimalProxyFactory, IAelinDeal {
Timeline public proRataRedemption;

/**
* @dev the initialize method replaces the constructor setup and can only be called once
* NOTE the deal tokens wrapping the underlying are always 18 decimals
* NOTE The deal tokens wrapping the underlying are always 18 decimals.
*/
function initialize(
string calldata _poolName,
Expand All @@ -66,22 +65,23 @@ contract AelinDeal is AelinVestingToken, MinimalProxyFactory, IAelinDeal {

depositComplete = false;

/**
* calculates the amount of underlying deal tokens you get per wrapped deal token accepted
*/
// Calculates the amount of underlying deal tokens you get per wrapped deal token accepted
underlyingPerDealExchangeRate = (_dealData.underlyingDealTokenTotal * 1e18) / maxTotalSupply;
emit HolderAccepted(_dealData.holder);
}

/**
* @dev the holder finalizes the deal for the pool created by the
* sponsor by depositing funds using this method.
*
* NOTE if the deposit was completed with a transfer instead of this method
* the deposit still needs to be finalized by calling this method with
* _underlyingDealTokenAmount set to 0
* @notice This function allows the holder to deposit any amount of underlying deal tokens to a pool.
* If the cumulative deposited amount is greater than the underlyingDealTokenTotal the deal is finalized.
* @param _underlyingDealTokenAmount The amount of underlying deal tokens deposited.
* @return bool Returns true if the cumulative deposited amount is greater than the underlyingDealTokenTotal,
* meaning that the deal is full funded and finalized. Returns false otherwise.
* NOTE If the deposit was completed with a transfer instead of this method the deposit still needs to
* be finalized by calling this method with _underlyingDealTokenAmount set to 0.
*/
function depositUnderlying(uint256 _underlyingDealTokenAmount) external finalizeDeposit nonReentrant returns (bool) {
function depositUnderlying(
uint256 _underlyingDealTokenAmount
) external finalizeDeposit onlyHolder nonReentrant returns (bool) {
if (_underlyingDealTokenAmount > 0) {
uint256 currentBalance = IERC20(underlyingDealToken).balanceOf(address(this));
IERC20(underlyingDealToken).safeTransferFrom(msg.sender, address(this), _underlyingDealTokenAmount);
Expand Down Expand Up @@ -120,8 +120,9 @@ contract AelinDeal is AelinVestingToken, MinimalProxyFactory, IAelinDeal {
}

/**
* @dev the holder can withdraw any amount accidentally deposited over
* the amount needed to fulfill the deal or all amount if deposit was not completed
* @notice This function allows the holder to withdraw any amount of underlying tokens accidently
* deposited over the amount needed to fulfill the deal, or all of the amount deposited if the deal
* was not completed.
*/
function withdraw() external onlyHolder {
uint256 withdrawAmount;
Expand All @@ -137,11 +138,9 @@ contract AelinDeal is AelinVestingToken, MinimalProxyFactory, IAelinDeal {
}

/**
* @dev after the redemption period has ended the holder can withdraw
* the excess funds remaining from purchasers who did not accept the deal
*
* Requirements:
* - both the pro rata and open redemption windows are no longer active
* @notice This function allows the holder to withdraw any excess underlying deal tokens after
* the the redemption period has ended.
* NOTE Both the pro rata and open redemption windows must no longer be active.
*/
function withdrawExpiry() external onlyHolder {
require(proRataRedemption.expiry > 0, "redemption period not started");
Expand All @@ -158,9 +157,11 @@ contract AelinDeal is AelinVestingToken, MinimalProxyFactory, IAelinDeal {
}

/**
* @dev a view showing the number of claimable underlying deal
* @notice This view function returns the number of claimable underlying deal tokens given the token id
* of a user's vesting token.
* @param _tokenId The token id of a user's vesting token.
* @return uint256 The number of underlying deal tokens a user can claim.
*/

function claimableUnderlyingTokens(uint256 _tokenId) public view returns (uint256) {
VestingDetails memory schedule = vestingDetails[_tokenId];
uint256 precisionAdjustedUnderlyingClaimable;
Expand All @@ -178,8 +179,11 @@ contract AelinDeal is AelinVestingToken, MinimalProxyFactory, IAelinDeal {
: (schedule.share * (maxTime - minTime)) / vestingPeriod;
uint256 underlyingClaimable = (underlyingPerDealExchangeRate * claimableAmount) / 1e18;

// This could potentially be the case where the last user claims a slightly smaller amount if there is some precision loss
// although it will generally never happen as solidity rounds down so there should always be a little bit left
/**
* @dev There could potentially be the case where the last user claims a slightly smaller amount
* if there is some precision loss, although it will generally never happen as solidity rounds
* down so there should always be a little bit left.
*/
precisionAdjustedUnderlyingClaimable = underlyingClaimable >
IERC20(underlyingDealToken).balanceOf(address(this))
? IERC20(underlyingDealToken).balanceOf(address(this))
Expand All @@ -189,6 +193,14 @@ contract AelinDeal is AelinVestingToken, MinimalProxyFactory, IAelinDeal {
return precisionAdjustedUnderlyingClaimable;
}

/**
* @notice This function allows a user to claim their underlying deal tokens, or a partial amount of their
* underlying tokens, from multiple vesting tokens once they have vested according to the schedule created
* by the sponsor.
* @param _indices The token ids of a user's vesting tokens.
* @return uint256 The number of underlying deal tokens a user claimed.
* NOTE If the vesting of any token ids has been completed the corresponding vesting token will be burned.
*/
function claimUnderlyingMultipleEntries(uint256[] memory _indices) external returns (uint256) {
uint256 totalClaimed;
for (uint256 i = 0; i < _indices.length; i++) {
Expand All @@ -198,9 +210,11 @@ contract AelinDeal is AelinVestingToken, MinimalProxyFactory, IAelinDeal {
}

/**
* @dev allows a user to claim their underlying deal tokens or a partial amount
* of their underlying tokens once they have vested according to the schedule
* created by the sponsor
* @notice This function allows a user to claim their underlying deal tokens, or a partial amount of their
* underlying tokens, once they have vested according to the schedule created by the sponsor.
* @param _tokenId The token id of a user's vesting token.
* @return uint256 The number of underlying deal tokens a user claimed.
* NOTE If the vesting has been completed the vesting token will be burned.
*/
function claimUnderlyingTokens(uint256 _tokenId) external returns (uint256) {
return _claimUnderlyingTokens(msg.sender, _tokenId);
Expand All @@ -224,33 +238,47 @@ contract AelinDeal is AelinVestingToken, MinimalProxyFactory, IAelinDeal {
}

/**
* @dev allows the purchaser to mint deal tokens. this method is also used
* to send deal tokens to the sponsor. It may only be called from the pool
* contract that created this deal
* @notice This function allows the purchaser to mint deal tokens. It is also used to send deal tokens to
* the sponsor.
* @param _to The recipient of the vesting token.
* @param _amount The number of vesting tokens to be minted.
* NOTE It may only be called from the pool contract that created this deal, and only after the deposit has
* been completed.
*/
function mintVestingToken(address _to, uint256 _amount) external depositCompleted onlyPool {
totalUnderlyingAccepted += _amount;
_mintVestingToken(_to, _amount, vestingCliffExpiry);
/**
* @dev Vesting index hard-coded to zero here. Multiple vesting schedules currently not supported
* for these deals.
*/
_mintVestingToken(_to, _amount, vestingCliffExpiry, 0);
}

/**
* @dev allows the protocol to handle protocol fees coming in deal tokens.
* It may only be called from the pool contract that created this deal
* @notice This function allows the protocol to handle protocol fees, with deal tokens.
* @param _dealTokenAmount The number of deal tokens reserved for protocol fees.
* NOTE It may only be called from the pool contract that created this deal, and only after the deposit has
* been completed.
*/
function transferProtocolFee(uint256 dealTokenAmount) external depositCompleted onlyPool {
uint256 underlyingProtocolFees = (underlyingPerDealExchangeRate * dealTokenAmount) / 1e18;
function transferProtocolFee(uint256 _dealTokenAmount) external depositCompleted onlyPool {
uint256 underlyingProtocolFees = (underlyingPerDealExchangeRate * _dealTokenAmount) / 1e18;
IERC20(underlyingDealToken).safeTransfer(address(aelinFeeEscrow), underlyingProtocolFees);
}

/**
* @dev the holder may change their address
* @notice This function allows the holder to set a future holder address without changing the
* holder address currently.
* @param _futureHolder The future holder address.
*/
function setHolder(address _holder) external onlyHolder {
require(_holder != address(0), "holder cant be null");
futureHolder = _holder;
emit HolderSet(_holder);
function setHolder(address _futureHolder) external onlyHolder {
require(_futureHolder != address(0), "holder cant be null");
futureHolder = _futureHolder;
emit HolderSet(_futureHolder);
}

/**
* @notice This function allows the future holder address to replace the current holder address.
*/
function acceptHolder() external {
require(msg.sender == futureHolder, "only future holder can access");
holder = futureHolder;
Expand Down
25 changes: 16 additions & 9 deletions contracts/AelinERC20.sol
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,15 @@ pragma solidity 0.8.19;
import {ERC20} from "@openzeppelin/contracts/token/ERC20/ERC20.sol";

/**
* @dev a standard ERC20 contract that is extended with a few methods
* described in detail below
* @dev A standard ERC20 contract that is extended with a few additional functions and variables.
* Due to the constructor being empty for the MinimalProxy architecture the customName, customSymbol,
* and customDecimals variables are set in the initializer. The MinimalProxy architecture also
* requires custom logic for the name(), symbol(), decimals(), and _setNameSymbolAndDecimals()
* functions.
*/
contract AelinERC20 is ERC20 {
bool private setInfo;
/**
* @dev Due to the constructor being empty for the MinimalProxy architecture we need
* to set the name and symbol in the initializer which requires these custom variables
*/

string private customName;
string private customSymbol;
uint8 private customDecimals;
Expand All @@ -27,18 +27,25 @@ contract AelinERC20 is ERC20 {
}

/**
* @dev Due to the constructor being empty for the MinimalProxy architecture we need
* to set the name, symbol, and decimals in the initializer which requires this
* custom logic for name(), symbol(), decimals(), and _setNameSymbolAndDecimals()
* @notice This view function returns the name of the token.
* @return string The name of the token.
*/
function name() public view virtual override returns (string memory) {
return customName;
}

/**
* @notice This view function returns the symbol of the token.
* @return string The symbol of the token.
*/
function symbol() public view virtual override returns (string memory) {
return customSymbol;
}

/**
* @notice This view function returns the number of decimals the token has.
* @return uint8 The number of decimals the token has.
*/
function decimals() public view virtual override returns (uint8) {
return customDecimals;
}
Expand Down
19 changes: 12 additions & 7 deletions contracts/AelinERC721.sol
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,13 @@ pragma solidity 0.8.19;
import {ERC721} from "@openzeppelin/contracts/token/ERC721/ERC721.sol";
import {ReentrancyGuard} from "@openzeppelin/contracts/security/ReentrancyGuard.sol";

/**
* @dev A standard ERC721 contract that is extended with a few additional functions and variables.
* Due to the constructor being empty for the MinimalProxy architecture the customName and customSymbol
* variables are set in the initializer. The MinimalProxy architecture also requires custom logic for
* the name(), symbol(), and _setNameAndSymbol() functions.
*/
contract AelinERC721 is ERC721, ReentrancyGuard {
/**
* @dev Due to the constructor being empty for the MinimalProxy architecture we need
* to set the name and symbol in the initializer which requires these custom variables
*/
string private customName;
string private customSymbol;

Expand All @@ -24,14 +26,17 @@ contract AelinERC721 is ERC721, ReentrancyGuard {
}

/**
* @dev Due to the constructor being empty for the MinimalProxy architecture we need
* to set the name and symbol, and decimals in the initializer which requires this
* custom logic for name(), symbol(), and _setNameAndSymbol()
* @notice This view function returns the name of the token.
* @return string The name of the token.
*/
function name() public view virtual override returns (string memory) {
return customName;
}

/**
* @notice This view function returns the symbol of the token.
* @return string The symbol of the token.
*/
function symbol() public view virtual override returns (string memory) {
return customSymbol;
}
Expand Down
13 changes: 11 additions & 2 deletions contracts/AelinFeeEscrow.sol
Original file line number Diff line number Diff line change
Expand Up @@ -24,26 +24,35 @@ contract AelinFeeEscrow {
}

/**
* @dev the treasury may change their address
* @notice This function allows the treasury to set a future treasury address without changing the
* treasury address currently.
* @param _futureTreasury The future treasury address.
*/
function setTreasury(address _futureTreasury) external onlyTreasury {
require(_futureTreasury != address(0), "cant pass null treasury address");
futureTreasury = _futureTreasury;
}

/**
* @notice This function allows the future treasury address to replace the current treasury address.
*/
function acceptTreasury() external {
require(msg.sender == futureTreasury, "must be future treasury");
treasury = futureTreasury;
emit SetTreasury(futureTreasury);
}

/**
* @notice This function allows the treasury to further delay the vesting expiry of escrowed assets
* by the DELAY_PERIOD.
*/
function delayEscrow() external onlyTreasury {
vestingExpiry = block.timestamp + DELAY_PERIOD;
emit DelayEscrow(vestingExpiry);
}

/**
* @dev transfer all the escrow tokens to the treasury
* @notice This function allows the treasury to transfer all of the escrow tokens to the treasury.
*/
function withdrawToken() external onlyTreasury {
require(block.timestamp > vestingExpiry, "cannot access funds yet");
Expand Down
Loading