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
19 changes: 14 additions & 5 deletions contracts/Reliquary.sol
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import "./interfaces/IReliquary.sol";
import "openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol";
import "openzeppelin-contracts/contracts/token/ERC721/extensions/ERC721Burnable.sol";
import "openzeppelin-contracts/contracts/token/ERC721/extensions/ERC721Enumerable.sol";
import "openzeppelin-contracts/contracts/utils/math/Math.sol";
import "openzeppelin-contracts/contracts/utils/Multicall.sol";
import "openzeppelin-contracts/contracts/access/AccessControlEnumerable.sol";
import "openzeppelin-contracts/contracts/security/ReentrancyGuard.sol";
Expand Down Expand Up @@ -89,6 +90,7 @@ contract Reliquary is IReliquary, ERC721Burnable, ERC721Enumerable, AccessContro
event LogPoolAddition(
uint indexed pid,
uint allocPoint,
uint startTime,
IERC20 indexed poolToken,
IRewarder indexed rewarder,
INFTDescriptor nftDescriptor
Expand Down Expand Up @@ -185,6 +187,7 @@ contract Reliquary is IReliquary, ERC721Burnable, ERC721Enumerable, AccessContro
IRewarder _rewarder,
uint[] calldata requiredMaturity,
uint[] calldata allocPoints,
uint startTime,
string memory name,
INFTDescriptor _nftDescriptor
) external override onlyRole(OPERATOR) {
Expand Down Expand Up @@ -214,6 +217,7 @@ contract Reliquary is IReliquary, ERC721Burnable, ERC721Enumerable, AccessContro

poolInfo.push(
PoolInfo({
startTime: startTime,
allocPoint: allocPoint,
lastRewardTime: block.timestamp,
accOathPerShare: 0,
Expand All @@ -228,7 +232,7 @@ contract Reliquary is IReliquary, ERC721Burnable, ERC721Enumerable, AccessContro
})
);

emit LogPoolAddition((poolToken.length - 1), allocPoint, _poolToken, _rewarder, _nftDescriptor);
emit LogPoolAddition((poolToken.length - 1), allocPoint, startTime, _poolToken, _rewarder, _nftDescriptor);
}

/*
Expand Down Expand Up @@ -715,9 +719,14 @@ contract Reliquary is IReliquary, ERC721Burnable, ERC721Enumerable, AccessContro
*/
function _updateEntry(uint amount, uint relicId) internal {
PositionInfo storage position = positionForId[relicId];
uint weight = _findWeight(amount, position.amount);
uint maturity = block.timestamp - position.entry;
position.entry += maturity * weight / 1e18;
PoolInfo storage pool = poolInfo[position.poolId];
if(block.timestamp < pool.startTime) {
position.entry = pool.startTime;
} else {
uint weight = _findWeight(amount, position.amount);
uint maturity = block.timestamp - position.entry;
position.entry += maturity * weight / 1e18;
}
}

/*
Expand All @@ -732,7 +741,7 @@ contract Reliquary is IReliquary, ERC721Burnable, ERC721Enumerable, AccessContro
return 0;
}

uint maturity = block.timestamp - position.entry;
uint maturity = block.timestamp - Math.min(position.entry, block.timestamp);
for (newLevel = length - 1; true; newLevel = _uncheckedDec(newLevel)) {
if (maturity >= levelInfo.requiredMaturity[newLevel]) {
if (position.level != newLevel) {
Expand Down
2 changes: 2 additions & 0 deletions contracts/interfaces/IReliquary.sol
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ struct PositionInfo {
+ `name` Name of pool to be displayed in NFT image
*/
struct PoolInfo {
uint startTime;
uint accOathPerShare;
uint lastRewardTime;
uint allocPoint;
Expand Down Expand Up @@ -63,6 +64,7 @@ interface IReliquary is IERC721Enumerable {
IRewarder _rewarder,
uint[] calldata requiredMaturity,
uint[] calldata allocPoints,
uint startTime,
string memory name,
INFTDescriptor _nftDescriptor
) external;
Expand Down
1 change: 1 addition & 0 deletions scripts/Deploy.s.sol
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ contract Deploy is Script {
IRewarder(address(0)),
wethCurve,
wethLevels,
block.timestamp,
"ETH Pool",
nftDescriptor
);
Expand Down
2 changes: 1 addition & 1 deletion test/foundry/DepositHelper.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ contract DepositHelperTest is Test {
vault = IERC4626(0x58C60B6dF933Ff5615890dDdDCdD280bad53f1C1);
INFTDescriptor nftDescriptor = INFTDescriptor(new NFTDescriptorSingle4626(IReliquary(reliquary)));
reliquary.grantRole(keccak256(bytes("OPERATOR")), address(this));
reliquary.addPool(1000, vault, IRewarder(address(0)), wethCurve, wethLevels, "ETH Crypt", nftDescriptor);
reliquary.addPool(1000, vault, IRewarder(address(0)), wethCurve, wethLevels, block.timestamp, "ETH Crypt", nftDescriptor);

helper = new DepositHelper(address(reliquary));
weth = IERC20(vault.asset());
Expand Down
2 changes: 1 addition & 1 deletion test/foundry/Invariants.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ contract Invariants is Test {
TestToken testToken = new TestToken("Test Token", "TT", 6);
INFTDescriptor nftDescriptor = INFTDescriptor(new NFTDescriptor(IReliquary(reliquary)));
reliquary.grantRole(keccak256(bytes("OPERATOR")), address(this));
reliquary.addPool(1000, testToken, IRewarder(address(0)), curve, levels, "Test Token", nftDescriptor);
reliquary.addPool(1000, testToken, IRewarder(address(0)), curve, levels, block.timestamp, "Test Token", nftDescriptor);

ReliquaryUser user = new ReliquaryUser(address(reliquary), address(testToken));
Skipper skipper = new Skipper();
Expand Down
25 changes: 25 additions & 0 deletions test/foundry/Reliquary.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ contract ReliquaryTest is ERC721Holder, Test {

uint[] requiredMaturity = [0, 1 days, 7 days, 14 days, 30 days, 90 days, 180 days, 365 days];
uint[] allocPoints = [100, 120, 150, 200, 300, 400, 500, 750];
uint startTime;

event Deposit(
uint indexed pid,
Expand Down Expand Up @@ -57,13 +58,16 @@ contract ReliquaryTest is ERC721Holder, Test {
testToken = new TestToken("Test Token", "TT", 6);
nftDescriptor = INFTDescriptor(address(new NFTDescriptor(IReliquary(address(reliquary)))));

startTime = block.timestamp + 2 days;

reliquary.grantRole(keccak256(bytes("OPERATOR")), address(this));
reliquary.addPool(
100,
testToken,
IRewarder(address(0)),
requiredMaturity,
allocPoints,
startTime,
"ETH Pool",
nftDescriptor
);
Expand All @@ -75,13 +79,34 @@ contract ReliquaryTest is ERC721Holder, Test {
function testPoolLength() public {
assertTrue(reliquary.poolLength() == 1);
}
function testMaturingOnlyOnceStartTimeReachedForPool() public {
uint relicId = reliquary.createRelicAndDeposit(address(this), 0, 10 ether);
PositionInfo memory positionAfterDeposit = reliquary.getPositionForId(relicId);
assertEq(positionAfterDeposit.entry, startTime);
assertEq(positionAfterDeposit.level, 0);

skip(1 days);
// according to the level definition, we would be level 1 after 1 day
// but since we've set the start time to the future, it should still be level 0
reliquary.updatePosition(relicId);
PositionInfo memory positionAfter1Day = reliquary.getPositionForId(relicId);
assertEq(positionAfter1Day.level, 0);

skip(2 days);
// now we have passed the start time by 1 day and should therefore be level 1
reliquary.updatePosition(relicId);
PositionInfo memory positionAfter3Days= reliquary.getPositionForId(relicId);
assertEq(positionAfter3Days.level, 1);

}

function testModifyPool() public {
vm.expectEmit(true, true, false, true);
emit LogPoolModified(0, 100, IRewarder(address(0)), nftDescriptor);
reliquary.modifyPool(0, 100, IRewarder(address(0)), "USDC Pool", nftDescriptor, true);
}


function testRevertOnModifyInvalidPool() public {
vm.expectRevert(bytes("set: pool does not exist"));
reliquary.modifyPool(1, 100, IRewarder(address(0)), "USDC Pool", nftDescriptor, true);
Expand Down