// SPDX-License-Identifier: Apache-2.0
pragma solidity ^0.8.0;
interface IERC20 {
function symbol() external view returns (string memory);
function balanceOf(address account) external view returns (uint256);
// Note this is non standard but nearly all ERC20 have exposed decimal functions
function decimals() external view returns (uint8);
function transfer(address recipient, uint256 amount)
external
returns (bool);
function allowance(address owner, address spender)
external
view
returns (uint256);
function approve(address spender, uint256 amount) external returns (bool);
function transferFrom(
address sender,
address recipient,
uint256 amount
) external returns (bool);
event Transfer(address indexed from, address indexed to, uint256 value);
event Approval(
address indexed owner,
address indexed spender,
uint256 value
);
}
// Forked from openzepplin
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "./IERC20.sol";
/**
* @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in
* https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].
*
* Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by
* presenting a message signed by the account. By not relying on `{IERC20-approve}`, the token holder account doesn't
* need to send a transaction, and thus is not required to hold Ether at all.
*/
interface IERC20Permit is IERC20 {
/**
* @dev Sets `value` as the allowance of `spender` over `owner`'s tokens,
* given `owner`'s signed approval.
*
* IMPORTANT: The same issues {IERC20-approve} has related to transaction
* ordering also apply here.
*
* Emits an {Approval} event.
*
* Requirements:
*
* - `spender` cannot be the zero address.
* - `deadline` must be a timestamp in the future.
* - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`
* over the EIP712-formatted function arguments.
* - the signature must use ``owner``'s current nonce (see {nonces}).
*
* For more information on the signature format, see the
* https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP
* section].
*/
function permit(
address owner,
address spender,
uint256 value,
uint256 deadline,
uint8 v,
bytes32 r,
bytes32 s
) external;
/**
* @dev Returns the current nonce for `owner`. This value must be
* included whenever a signature is generated for {permit}.
*
* Every successful call to {permit} increases ``owner``'s nonce by one. This
* prevents a signature from being used multiple times.
*/
function nonces(address owner) external view returns (uint256);
/**
* @dev Returns the domain separator used in the encoding of the signature for `permit`, as defined by {EIP712}.
*/
// solhint-disable-next-line func-name-mixedcase
function DOMAIN_SEPARATOR() external view returns (bytes32);
}
// SPDX-License-Identifier: Apache-2.0
pragma solidity ^0.8.0;
import "./IERC20Permit.sol";
interface IInterestToken is IERC20Permit {
function mint(address _account, uint256 _amount) external;
function burn(address _account, uint256 _amount) external;
}
// SPDX-License-Identifier: Apache-2.0
pragma solidity ^0.8.0;
import "./IERC20Permit.sol";
import "./IInterestToken.sol";
interface ITranche is IERC20Permit {
function deposit(uint256 _shares, address destination)
external
returns (uint256, uint256);
function prefundedDeposit(address _destination)
external
returns (uint256, uint256);
function withdrawPrincipal(uint256 _amount, address _destination)
external
returns (uint256);
function withdrawInterest(uint256 _amount, address _destination)
external
returns (uint256);
function interestToken() external view returns (IInterestToken);
function interestSupply() external view returns (uint128);
}
// SPDX-License-Identifier: Apache-2.0
pragma solidity ^0.8.0;
import "./libraries/ERC20Permit.sol";
import "./libraries/DateString.sol";
import "./interfaces/IInterestToken.sol";
import "./interfaces/ITranche.sol";
contract InterestToken is ERC20Permit, IInterestToken {
// The tranche address which controls the minting
ITranche public immutable tranche;
/// @dev Initializes the ERC20 and writes the correct names
/// @param _tranche The tranche contract address
/// @param _strategySymbol The symbol of the associated WrappedPosition contract
/// @param _timestamp The unlock time on the tranche
/// @param _decimals The decimal encoding for this token
constructor(
address _tranche,
string memory _strategySymbol,
uint256 _timestamp,
uint8 _decimals
)
ERC20Permit(
_processName("Element Yield Token ", _strategySymbol, _timestamp),
_processSymbol("eY", _strategySymbol, _timestamp)
)
{
tranche = ITranche(_tranche);
_setupDecimals(_decimals);
}
/// @notice We use this function to add the date to the name string
/// @param _name start of the name
/// @param _strategySymbol the strategy symbol
/// @param _timestamp the unix second timestamp to be encoded and added to the end of the string
function _processName(
string memory _name,
string memory _strategySymbol,
uint256 _timestamp
) internal returns (string memory) {
// Set the name in the super
name = _name;
// Use the library to write the rest
DateString._encodeAndWriteTimestamp(_strategySymbol, _timestamp, name);
// load and return the name
return name;
}
/// @notice We use this function to add the date to the name string
/// @param _symbol start of the symbol
/// @param _strategySymbol the strategy symbol
/// @param _timestamp the unix second timestamp to be encoded and added to the end of the string
function _processSymbol(
string memory _symbol,
string memory _strategySymbol,
uint256 _timestamp
) internal returns (string memory) {
// Set the symbol in the super
symbol = _symbol;
// Use the library to write the rest
DateString._encodeAndWriteTimestamp(
_strategySymbol,
_timestamp,
symbol
);
// load and return the name
return symbol;
}
/// @dev Aliasing of the lookup method for the supply of yield tokens which
/// improves our ERC20 compatibility.
/// @return The total supply of yield tokens
function totalSupply() external view returns (uint256) {
return uint256(tranche.interestSupply());
}
/// @dev Prevents execution if the caller isn't the tranche
modifier onlyMintAuthority() {
require(
msg.sender == address(tranche),
"caller is not an authorized minter"
);
_;
}
/// @dev Mints tokens to an address
/// @param _account The account to mint to
/// @param _amount The amount to mint
function mint(address _account, uint256 _amount)
external
override
onlyMintAuthority
{
_mint(_account, _amount);
}
/// @dev Burns tokens from an address
/// @param _account The account to burn from
/// @param _amount The amount of token to burn
function burn(address _account, uint256 _amount)
external
override
onlyMintAuthority
{
_burn(_account, _amount);
}
}