function fnftIdToLock(uint fnftId) public view override returns (IRevest.Lock memory) {
return locks[fnftIdToLockId[fnftId]];
}
Returns the Lock object associated with the passed in fnftId.
function getLock(uint lockId) external view override returns (IRevest.Lock memory) {
return locks[lockId];
}
Returns the lock object associated with the passed in lockId.
function getSupply(uint fnftId) public view override returns (uint) {
return supply[fnftId];
}
Gets the total supply of FNFTs within the given ID.
function getLockMaturity(uint fnftId) public view override returns (bool) {
IRevest.Lock memory lock = locks[fnftIdToLockId[fnftId]];
if (lock.lockType == IRevest.LockType.TimeLock) {
return lock.unlocked || lock.timeLockExpiry < block.timestamp;
}
else if (lock.lockType == IRevest.LockType.ValueLock) {
return lock.unlocked || getValueLockMaturity(fnftId);
}
else if (lock.lockType == IRevest.LockType.AddressLock) {
return lock.unlocked || (lock.addressLock.supportsInterface(ADDRESS_LOCK_INTERFACE_ID) &&
IAddressLock(lock.addressLock).isUnlockable(fnftId, fnftIdToLockId[fnftId]));
}
else {
revert("E050");
}
}
Helper function for getLockMaturity. Checks if a value lock is mature.
function lockTypes(uint tokenId) external view override returns (IRevest.LockType) {
return fnftIdToLock(tokenId).lockType;
}
function pointFNFTToLock(uint fnftId, uint lockId) external override onlyRevest {
fnftIdToLockId[fnftId] = lockId;
}
Maps an FNFT id to a lock ID.
function createLock(uint fnftId, IRevest.LockParam memory lock) external override onlyRevest returns (uint) {
// Extensive validation on creation
require(lock.lockType != IRevest.LockType.DoesNotExist, "E058");
IRevest.Lock storage newLock = locks[numLocks];
newLock.lockType = lock.lockType;
newLock.creationTime = block.timestamp;
if(lock.lockType == IRevest.LockType.TimeLock) {
require(lock.timeLockExpiry > block.timestamp, "E002");
newLock.timeLockExpiry = lock.timeLockExpiry;
}
else if (lock.lockType == IRevest.LockType.ValueLock) {
require(lock.valueLock.unlockValue > 0, "E003");
require(lock.valueLock.compareTo != address(0) && lock.valueLock.asset != address(0), "E004");
//Begin validation code to ensure this is actually keyed to a proper oracle
IOracleDispatch oracle = IOracleDispatch(lock.valueLock.oracle);
bool oraclePresent = oracle.getPairHasOracle(lock.valueLock.asset, lock.valueLock.compareTo);
//If the oracle is not present, attempt to initialize it
if(!oraclePresent && oracle.oracleNeedsInitialization(lock.valueLock.asset, lock.valueLock.compareTo)) {
oraclePresent = oracle.initializeOracle(lock.valueLock.asset, lock.valueLock.compareTo);
}
require(oraclePresent, "E049");
newLock.valueLock = lock.valueLock;
}
else if (lock.lockType == IRevest.LockType.AddressLock) {
require(lock.addressLock != address(0), "E004");
newLock.addressLock = lock.addressLock;
}
else {
require(false, "Invalid type");
}
fnftIdToLockId[fnftId] = numLocks;
numLocks += 1;
return numLocks - 1;
}
function unlockFNFT(uint fnftId, address sender) external override onlyRevestController returns (bool) {
uint lockId = fnftIdToLockId[fnftId];
IRevest.Lock storage lock = locks[lockId];
IRevest.LockType typeLock = lock.lockType;
if (typeLock == IRevest.LockType.TimeLock) {
if(!lock.unlocked && lock.timeLockExpiry <= block.timestamp) {
lock.unlocked = true;
//Should refund some gas
lock.timeLockExpiry = 0;
}
}
else if (typeLock == IRevest.LockType.ValueLock) {
bool unlockState;
address oracleAdd =lock.valueLock.oracle;
if(getLockMaturity(fnftId)) {
unlockState = true;
} else {
IOracleDispatch oracle = IOracleDispatch(oracleAdd);
unlockState = oracle.updateOracle(lock.valueLock.asset, lock.valueLock.compareTo) &&
getLockMaturity(fnftId);
}
if(unlockState && oracleAdd != address(0)) {
//We only want to write this once
lock.unlocked = true;
//Refund some gas
lock.valueLock.oracle = address(0);
lock.valueLock.asset = address(0);
lock.valueLock.compareTo = address(0);
lock.valueLock.unlockValue = 0;
lock.valueLock.unlockRisingEdge = false;
}
}
else if (typeLock == IRevest.LockType.AddressLock) {
address addLock = lock.addressLock;
if (!lock.unlocked && (sender == addLock ||
(addLock.supportsInterface(ADDRESS_LOCK_INTERFACE_ID) && IAddressLock(addLock).isUnlockable(fnftId, lockId)))
) {
lock.unlocked = true;
//Refund some gas
lock.addressLock = address(0);
}
}
return lock.unlocked;
}
// SPDX-License-Identifier: GNU-GPL v3.0 or later
pragma solidity >=0.8.0;
import "./IRevest.sol";
/**
* @title Mintable interface for Revest FNFTs
* @dev ...
*/
interface ILockManager {
function createLock(uint fnftId, IRevest.LockParam memory lock) external returns (uint);
function getLock(uint lockId) external view returns (IRevest.Lock memory);
function fnftIdToLockId(uint fnftId) external view returns (uint);
function fnftIdToLock(uint fnftId) external view returns (IRevest.Lock memory);
function pointFNFTToLock(uint fnftId, uint lockId) external;
function lockTypes(uint tokenId) external view returns (IRevest.LockType);
function unlockFNFT(uint fnftId, address sender) external returns (bool);
function getLockMaturity(uint fnftId) external view returns (bool);
}