Skip to content

Commit

Permalink
adding upgrade with fallback
Browse files Browse the repository at this point in the history
  • Loading branch information
julien51 committed Oct 24, 2024
1 parent 0de46a4 commit 2c1f544
Show file tree
Hide file tree
Showing 9 changed files with 27,496 additions and 37 deletions.
165 changes: 165 additions & 0 deletions contracts/UnlockPrimeHookWithRecipientAndFallback.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,165 @@
import "@unlock-protocol/contracts/dist/PublicLock/IPublicLockV13.sol";

// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.27;

// Uncomment this line to use console.log
// import "hardhat/console.sol";

interface IUniswapOracleV3 {
function PERIOD() external returns (uint256);

function factory() external returns (address);

function update(address _tokenIn, address _tokenOut) external;

function consult(
address _tokenIn,
uint256 _amountIn,
address _tokenOut
) external view returns (uint256 _amountOut);

function updateAndConsult(
address _tokenIn,
uint256 _amountIn,
address _tokenOut
) external returns (uint256 _amountOut);
}

contract UnlockPrimeHookWithRecipientAndFallback {
address public unlockPrime;
address public oracle;
address public weth;
mapping(address => uint[2]) public refunds; // [amount, time]

event UnlockPrimeSet(address);
event OracleSet(address);
event WethSet(address);
event RefundSet(address, uint256, uint256);
event RefundPaid(address, uint256);

constructor(address _unlockPrime, address _oracle, address _weth) {
initialize(_unlockPrime, _oracle, _weth);
}

function initialize(
address _unlockPrime,
address _oracle,
address _weth
) public {
if (unlockPrime != address(0)) {
revert("Already initialized");
}
unlockPrime = _unlockPrime;
emit UnlockPrimeSet(_unlockPrime);
oracle = _oracle;
emit OracleSet(_oracle);
weth = _weth;
emit WethSet(_weth);
}

// Set the unlock prime address, only callable by lock manager
function setUnlockPrime(address _unlockPrime) public {
if (!IPublicLockV13(unlockPrime).isLockManager(msg.sender)) {
revert("Caller is not a lock manager");
}
unlockPrime = _unlockPrime;
emit UnlockPrimeSet(_unlockPrime);
}

// Set the oracle address, only callable by lock manager
function setOracle(address _oracle) public {
if (!IPublicLockV13(unlockPrime).isLockManager(msg.sender)) {
revert("Caller is not a lock manager");
}
oracle = _oracle;
emit OracleSet(_oracle);
}

// Set the WETH address, only callable by lock manager
function setWeth(address _weth) public {
if (!IPublicLockV13(unlockPrime).isLockManager(msg.sender)) {
revert("Caller is not a lock manager");
}
weth = _weth;
emit WethSet(_weth);
}

// Return the price of a key
function keyPurchasePrice(
address /* from */,
address /* recipient */,
address /* referrer */,
bytes calldata /* data */
) external view returns (uint256 minKeyPrice) {
return IPublicLockV13(msg.sender).keyPrice();
}

function recordRefund(address beneficiary, uint amount) private {
address UPAddress = IPublicLockV13(unlockPrime).tokenAddress();
// At this point, check the pricePaid and its value against Uniswap oracles
uint valueInETH = IUniswapOracleV3(oracle).updateAndConsult(
UPAddress,
amount,
weth
);
// Store the refund and the delay
uint existingRefund = refunds[beneficiary][0];
uint existingDelay = refunds[beneficiary][1];
uint newRefund = (valueInETH * 11) / 10; // 10% bonus
uint newDelay = block.timestamp + 60 * 60 * 24 * 14; // 2 weeks delay!

if (existingDelay < block.timestamp) {
refunds[beneficiary] = [existingRefund + newRefund, newDelay];
} else {
// One needs to wait for the delay to be able to increase their refund.
refunds[beneficiary] = [newRefund, newDelay];
}

emit RefundSet(
beneficiary,
refunds[beneficiary][0],
refunds[beneficiary][1]
);
}

// This function is called by Unlock when a key is purchased
function onKeyPurchase(
uint256 /* tokenId */,
address /* from */,
address recipient,
address /* referrer */,
bytes calldata /* data */,
uint256 /* minKeyPrice */,
uint256 /* pricePaid */
) external {
if (msg.sender == unlockPrime) {
recordRefund(recipient, IPublicLockV13(msg.sender).keyPrice());
}
}

// This function is called by Unlock when a key is extended
function onKeyExtend(
uint tokenId,
address /* sender */,
uint /* newTimestamp */,
uint /* expirationTimestamp */
) external {
IPublicLockV13 lock = IPublicLockV13(msg.sender);
if (msg.sender == unlockPrime) {
recordRefund(lock.ownerOf(tokenId), lock.keyPrice());
}
}

// Claim the refund!
function claimRefund() external {
uint[2] memory refund = refunds[msg.sender];
require(refund[0] > 0, "No refund available");
require(refund[1] < block.timestamp, "Refund not available yet");
refunds[msg.sender] = [0, 0];
payable(msg.sender).transfer(refund[0]);
emit RefundPaid(msg.sender, refund[0]);
}

receive() external payable {}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"_format": "hh-sol-dbg-1",
"buildInfo": "../build-info/1bad1a246ced45928824d35deeda720c.json"
}
Loading

0 comments on commit 2c1f544

Please sign in to comment.