bump RDA version
This commit is contained in:
parent
6beafd9b35
commit
5b13dfe581
1
.gitattributes
vendored
Normal file
1
.gitattributes
vendored
Normal file
@ -0,0 +1 @@
|
||||
*.sol linguist-language=Solidity
|
279
src/RDA.sol
279
src/RDA.sol
@ -1,12 +1,10 @@
|
||||
pragma solidity 0.8.13;
|
||||
|
||||
import { UD60x18 } from "@prb/math/UD60x18.sol";
|
||||
import { IRDA } from "@root/interfaces/IRDA.sol";
|
||||
|
||||
import { IRDA } from "@interfaces/IRDA.sol";
|
||||
import { IERC20 } from "@openzeppelin/token/ERC20/IERC20.sol";
|
||||
import { IDelegatedVesting } from "@interfaces/IDelegatedVesting.sol";
|
||||
|
||||
import { add, sub, mul, wrap, unwrap, gt, mod, div } from "@prb/math/UD60x18.sol";
|
||||
import { ERC20 } from "@openzeppelin/token/ERC20/ERC20.sol";
|
||||
import { SafeERC20 } from "@openzeppelin/token/ERC20/utils/SafeERC20.sol";
|
||||
import { ReentrancyGuard } from "@openzeppelin/security/ReentrancyGuard.sol";
|
||||
|
||||
/*
|
||||
* @title Rolling Dutch Auction (RDA)
|
||||
@ -14,7 +12,9 @@ import { add, sub, mul, wrap, unwrap, gt, mod, div } from "@prb/math/UD60x18.sol
|
||||
* @description A dutch auction derivative with composite decay
|
||||
*/
|
||||
|
||||
contract RDA is IRDA {
|
||||
contract RDA is IRDA, ReentrancyGuard {
|
||||
|
||||
using SafeERC20 for ERC20;
|
||||
|
||||
/* @dev Address mapping for an auction's redeemable balances */
|
||||
mapping(address => mapping(bytes => bytes)) public _claims;
|
||||
@ -28,13 +28,11 @@ contract RDA is IRDA {
|
||||
/* @dev Auction mapping for the window index */
|
||||
mapping(bytes => uint256) public _windows;
|
||||
|
||||
mapping(bytes => Vesting) public _vesting;
|
||||
|
||||
struct Auction {
|
||||
uint256 windowDuration; /* @dev Unix time window duration */
|
||||
uint256 windowTimestamp; /* @dev Unix timestamp for window start */
|
||||
uint256 startTimestamp; /* @dev Unix auction start timestamp */
|
||||
uint256 endTimestamp; /* @dev Unix auction end timestamp */
|
||||
uint256 endTimestamp; /* @dev Unix auction end timestamp */
|
||||
uint256 duration; /* @dev Unix time auction duration */
|
||||
uint256 proceeds; /* @dev Auction proceeds balance */
|
||||
uint256 reserves; /* @dev Auction reserves balance */
|
||||
@ -49,17 +47,14 @@ contract RDA is IRDA {
|
||||
bool processed; /* @dev Window fuflfillment state */
|
||||
}
|
||||
|
||||
struct Vesting {
|
||||
address instance;
|
||||
uint256 period;
|
||||
}
|
||||
|
||||
/*
|
||||
* @dev Conditioner to ensure an auction is active
|
||||
* @param a͟u͟c͟t͟i͟o͟n͟I͟d͟ Encoded auction parameter identifier
|
||||
*/
|
||||
modifier activeAuction(bytes memory auctionId) {
|
||||
require(remainingWindowTime(auctionId) > 0 || remainingTime(auctionId) > 0);
|
||||
modifier activeAuction(bytes calldata auctionId) {
|
||||
if (remainingWindowTime(auctionId) == 0 && remainingTime(auctionId) == 0) {
|
||||
revert AuctionInactive();
|
||||
}
|
||||
_;
|
||||
}
|
||||
|
||||
@ -67,8 +62,10 @@ contract RDA is IRDA {
|
||||
* @dev Conditioner to ensure an auction is inactive
|
||||
* @param a͟u͟c͟t͟i͟o͟n͟I͟d͟ Encoded auction parameter identifier
|
||||
*/
|
||||
modifier inactiveAuction(bytes memory auctionId) {
|
||||
require(remainingWindowTime(auctionId) == 0 && remainingTime(auctionId) == 0);
|
||||
modifier inactiveAuction(bytes calldata auctionId) {
|
||||
if (remainingWindowTime(auctionId) > 0 || remainingTime(auctionId) > 0) {
|
||||
revert AuctionActive();
|
||||
}
|
||||
_;
|
||||
}
|
||||
|
||||
@ -76,7 +73,7 @@ contract RDA is IRDA {
|
||||
* @dev Helper to view an auction's operator address
|
||||
* @param a͟u͟c͟t͟i͟o͟n͟I͟d͟ Encoded auction parameter identifier
|
||||
*/
|
||||
function operatorAddress(bytes memory auctionId) public pure returns (address opAddress) {
|
||||
function operatorAddress(bytes calldata auctionId) public pure returns (address opAddress) {
|
||||
(opAddress,,,,) = abi.decode(auctionId, (address, address, address, uint256, bytes));
|
||||
}
|
||||
|
||||
@ -84,15 +81,31 @@ contract RDA is IRDA {
|
||||
* @dev Helper to view an auction's purchase token address
|
||||
* @param a͟u͟c͟t͟i͟o͟n͟I͟d͟ Ancoded auction parameter identifier
|
||||
*/
|
||||
function purchaseToken(bytes memory auctionId) public pure returns (address tokenAddress) {
|
||||
function purchaseToken(bytes calldata auctionId) public pure returns (address tokenAddress) {
|
||||
(,, tokenAddress,,) = abi.decode(auctionId, (address, address, address, uint256, bytes));
|
||||
}
|
||||
|
||||
function isWindowInit(bytes calldata auctionId) public view returns (bool) {
|
||||
return _window[auctionId][_windows[auctionId]].expiry != 0;
|
||||
}
|
||||
|
||||
function isWindowActive(bytes calldata auctionId) public view returns (bool) {
|
||||
Window storage window = _window[auctionId][_windows[auctionId]];
|
||||
|
||||
return isWindowInit(auctionId) && window.expiry > block.timestamp;
|
||||
}
|
||||
|
||||
function isWindowExpired(bytes calldata auctionId) public view returns (bool) {
|
||||
Window storage window = _window[auctionId][_windows[auctionId]];
|
||||
|
||||
return isWindowInit(auctionId) && window.expiry < block.timestamp;
|
||||
}
|
||||
|
||||
/*
|
||||
* @dev Helper to view an auction's reserve token address
|
||||
* @param a͟u͟c͟t͟i͟o͟n͟I͟d͟ Encoded auction parameter identifier
|
||||
*/
|
||||
function reserveToken(bytes memory auctionId) public pure returns (address tokenAddress) {
|
||||
function reserveToken(bytes calldata auctionId) public pure returns (address tokenAddress) {
|
||||
(, tokenAddress,,,) = abi.decode(auctionId, (address, address, address, uint256, bytes));
|
||||
}
|
||||
|
||||
@ -124,7 +137,6 @@ contract RDA is IRDA {
|
||||
* @param w͟i͟n͟d͟o͟w͟D͟u͟r͟a͟t͟i͟o͟n͟ Uinx time window duration
|
||||
*/
|
||||
function createAuction(
|
||||
address vestingAddress,
|
||||
address operatorAddress,
|
||||
address reserveToken,
|
||||
address purchaseToken,
|
||||
@ -133,9 +145,8 @@ contract RDA is IRDA {
|
||||
uint256 startingOriginPrice,
|
||||
uint256 startTimestamp,
|
||||
uint256 endTimestamp,
|
||||
uint256 windowDuration,
|
||||
uint256 vestingDuration
|
||||
) external returns (bytes memory) {
|
||||
uint256 windowDuration
|
||||
) override external returns (bytes memory) {
|
||||
bytes memory auctionId = abi.encode(
|
||||
operatorAddress,
|
||||
reserveToken,
|
||||
@ -144,24 +155,38 @@ contract RDA is IRDA {
|
||||
abi.encodePacked(reserveAmount, startingOriginPrice, startTimestamp, endTimestamp, windowDuration)
|
||||
);
|
||||
|
||||
ERC20 tokenReserve = ERC20(reserveToken);
|
||||
ERC20 tokenPurchase = ERC20(purchaseToken);
|
||||
|
||||
Auction storage state = _auctions[auctionId];
|
||||
|
||||
uint256 auctionDuration = endTimestamp - startTimestamp;
|
||||
|
||||
if (state.price != 0) {
|
||||
revert AuctionExists();
|
||||
}
|
||||
if (startingOriginPrice == 0) {
|
||||
revert InvalidAuctionPrice();
|
||||
}
|
||||
if (startTimestamp < block.timestamp) {
|
||||
revert InvalidAuctionTimestamp();
|
||||
}
|
||||
if (tokenReserve.decimals() != tokenPurchase.decimals()){
|
||||
revert InvalidTokenDecimals();
|
||||
}
|
||||
if (auctionDuration < 1 days || windowDuration < 2 hours) {
|
||||
revert InvalidAuctionDurations();
|
||||
}
|
||||
|
||||
_vesting[auctionId].instance = vestingAddress;
|
||||
_vesting[auctionId].period = vestingDuration;
|
||||
tokenReserve.safeTransferFrom(msg.sender, address(this), reserveAmount);
|
||||
|
||||
IERC20(reserveToken).transferFrom(msg.sender, address(this), reserveAmount);
|
||||
|
||||
state.duration = endTimestamp - startTimestamp;
|
||||
state.windowDuration = windowDuration;
|
||||
state.windowTimestamp = startTimestamp;
|
||||
state.startTimestamp = startTimestamp;
|
||||
state.endTimestamp = endTimestamp;
|
||||
state.reserves = reserveAmount;
|
||||
state.price = startingOriginPrice;
|
||||
state.duration = auctionDuration;
|
||||
state.reserves = reserveAmount;
|
||||
|
||||
emit NewAuction(auctionId, reserveToken, reserveAmount, startingOriginPrice, endTimestamp);
|
||||
|
||||
@ -172,18 +197,10 @@ contract RDA is IRDA {
|
||||
* @dev Helper to view an auction's minimum purchase amount
|
||||
* @param a͟u͟c͟t͟i͟o͟n͟I͟d͟ Encoded auction parameter identifier
|
||||
*/
|
||||
function minimumPurchase(bytes memory auctionId) public pure returns (uint256 minimumAmount) {
|
||||
function minimumPurchase(bytes calldata auctionId) public pure returns (uint256 minimumAmount) {
|
||||
(,,, minimumAmount,) = abi.decode(auctionId, (address, address, address, uint256, bytes));
|
||||
}
|
||||
|
||||
/*
|
||||
* @dev Helper to view an auction's active scalar price formatted to uint256
|
||||
* @param a͟u͟c͟t͟i͟o͟n͟I͟d͟ Encoded auction parameter identifier
|
||||
*/
|
||||
function scalarPriceUint(bytes calldata auctionId) external returns (uint256) {
|
||||
return unwrap(scalarPrice(auctionId));
|
||||
}
|
||||
|
||||
/*
|
||||
* @dev Active price decay proportional to time delta (t) between the current
|
||||
* timestamp and the window's start timestamp or if the window is expired;
|
||||
@ -194,22 +211,23 @@ contract RDA is IRDA {
|
||||
* the origin price (y) and subtracted by y to result the decayed price
|
||||
* @param a͟u͟c͟t͟i͟o͟n͟I͟d͟ Encoded auction parameter identifier
|
||||
*/
|
||||
function scalarPrice(bytes memory auctionId) public view returns (UD60x18) {
|
||||
function scalarPrice(bytes calldata auctionId)
|
||||
activeAuction(auctionId)
|
||||
public view returns (uint256) {
|
||||
Auction storage state = _auctions[auctionId];
|
||||
Window storage window = _window[auctionId][_windows[auctionId]];
|
||||
|
||||
bool isInitialised = window.expiry != 0;
|
||||
bool isExpired = window.expiry < block.timestamp && isInitialised;
|
||||
uint256 ts = isWindowExpired(auctionId) ? window.expiry : state.windowTimestamp;
|
||||
uint256 y = !isWindowInit(auctionId) ? state.price : window.price;
|
||||
|
||||
uint256 timestamp = isExpired ? window.expiry : state.windowTimestamp;
|
||||
uint256 t = block.timestamp - ts;
|
||||
uint256 t_r = state.duration - elapsedTimeFromWindow(auctionId);
|
||||
|
||||
UD60x18 t = wrap(block.timestamp - timestamp);
|
||||
UD60x18 t_r = wrap(state.duration - elapsedTime(auctionId, timestamp));
|
||||
uint256 t_mod = t % (t_r - t);
|
||||
uint256 x = (t + t_mod) * 1e18;
|
||||
uint256 y_x = y * x / t_r;
|
||||
|
||||
UD60x18 x = div(add(t, mod(t, sub(t_r, t))), t_r);
|
||||
UD60x18 y = !isInitialised ? wrap(state.price) : wrap(window.price);
|
||||
|
||||
return sub(y, mul(y, x));
|
||||
return y - y_x / 1e18;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -218,9 +236,11 @@ contract RDA is IRDA {
|
||||
* @param p͟r͟i͟c͟e͟ Bid order price
|
||||
* @param v͟o͟l͟u͟m͟e͟ Bid order volume
|
||||
*/
|
||||
function commitBid(bytes memory auctionId, uint256 price, uint256 volume)
|
||||
function commitBid(bytes calldata auctionId, uint256 price, uint256 volume)
|
||||
activeAuction(auctionId)
|
||||
external returns (bytes memory) {
|
||||
nonReentrant
|
||||
override external returns (bytes memory bidId) {
|
||||
Auction storage state = _auctions[auctionId];
|
||||
Window storage window = _window[auctionId][_windows[auctionId]];
|
||||
|
||||
if (volume < minimumPurchase(auctionId)) {
|
||||
@ -229,8 +249,8 @@ contract RDA is IRDA {
|
||||
|
||||
bool hasExpired;
|
||||
|
||||
if (window.expiry != 0) {
|
||||
if (remainingWindowTime(auctionId) > 0) {
|
||||
if (isWindowInit(auctionId)) {
|
||||
if (isWindowActive(auctionId)) {
|
||||
if (window.price < price) {
|
||||
if (volume < window.volume) {
|
||||
revert InvalidWindowVolume();
|
||||
@ -244,68 +264,85 @@ contract RDA is IRDA {
|
||||
}
|
||||
|
||||
if (window.price == 0 || hasExpired) {
|
||||
if (gt(scalarPrice(auctionId), wrap(price))) {
|
||||
if (price < scalarPrice(auctionId)) {
|
||||
revert InvalidScalarPrice();
|
||||
}
|
||||
}
|
||||
|
||||
IERC20(purchaseToken(auctionId)).transferFrom(msg.sender, address(this), volume);
|
||||
uint256 orderVolume = volume - (volume % price);
|
||||
|
||||
if (_auctions[auctionId].reserves < (volume / price)) {
|
||||
if (state.reserves < orderVolume * 1e18 / price) {
|
||||
revert InsufficientReserves();
|
||||
}
|
||||
if (volume < price) {
|
||||
revert InvalidReserveVolume();
|
||||
}
|
||||
|
||||
bytes memory bidId = abi.encode(auctionId, msg.sender, price, volume);
|
||||
bidId = abi.encode(auctionId, msg.sender, price, orderVolume);
|
||||
|
||||
(uint256 refund, uint256 claim) = balancesOf(_claims[msg.sender][auctionId]);
|
||||
|
||||
_claims[msg.sender][auctionId] = abi.encode(refund + volume, claim);
|
||||
_claims[msg.sender][auctionId] = abi.encode(refund + orderVolume, claim);
|
||||
|
||||
if (hasExpired) {
|
||||
window = _window[auctionId][windowExpiration(auctionId)];
|
||||
}
|
||||
|
||||
_auctions[auctionId].windowTimestamp = block.timestamp;
|
||||
|
||||
window.expiry = block.timestamp + _auctions[auctionId].windowDuration;
|
||||
window.volume = volume;
|
||||
window.expiry = block.timestamp + state.windowDuration;
|
||||
window.volume = orderVolume;
|
||||
window.price = price;
|
||||
window.bidId = bidId;
|
||||
|
||||
emit Offer(auctionId, msg.sender, window.bidId, window.expiry);
|
||||
state.windowTimestamp = block.timestamp;
|
||||
|
||||
return bidId;
|
||||
emit Offer(auctionId, msg.sender, bidId, window.expiry);
|
||||
|
||||
ERC20 tokenPurchase = ERC20(purchaseToken(auctionId));
|
||||
|
||||
tokenPurchase.safeTransferFrom(msg.sender, address(this), orderVolume);
|
||||
}
|
||||
|
||||
/*
|
||||
* @dev Expire and fulfill an auction's active window
|
||||
* @param a͟u͟c͟t͟i͟o͟n͟I͟d͟ Encoded auction parameter identifier
|
||||
*/
|
||||
function windowExpiration(bytes memory auctionId) internal returns (uint256) {
|
||||
function windowExpiration(bytes calldata auctionId) internal returns (uint256) {
|
||||
uint256 windowIndex = _windows[auctionId];
|
||||
uint256 auctionElapsedTime = elapsedTime(auctionId, block.timestamp);
|
||||
uint256 auctionRemainingTime = _auctions[auctionId].duration - auctionElapsedTime;
|
||||
|
||||
_auctions[auctionId].endTimestamp = block.timestamp + auctionRemainingTime;
|
||||
_auctions[auctionId].price = _window[auctionId][windowIndex].price;
|
||||
Auction storage state = _auctions[auctionId];
|
||||
Window storage window = _window[auctionId][windowIndex];
|
||||
|
||||
state.endTimestamp = block.timestamp + remainingTime(auctionId);
|
||||
state.price = window.price;
|
||||
|
||||
_windows[auctionId] = windowIndex + 1;
|
||||
|
||||
fulfillWindow(auctionId, windowIndex);
|
||||
_fulfillWindow(auctionId, windowIndex);
|
||||
|
||||
emit Expiration(auctionId, _window[auctionId][windowIndex].bidId, windowIndex);
|
||||
emit Expiration(auctionId, window.bidId, windowIndex);
|
||||
|
||||
return windowIndex + 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* @dev Fulfill a window index even if the auction is inactive
|
||||
* @dev Fulfill a window index for an inactive auction
|
||||
* @param a͟u͟c͟t͟i͟o͟n͟I͟d͟ Encoded auction parameter identifier
|
||||
*/
|
||||
function fulfillWindow(bytes memory auctionId, uint256 windowId) public {
|
||||
function fulfillWindow(bytes calldata auctionId, uint256 windowId)
|
||||
inactiveAuction(auctionId)
|
||||
override public {
|
||||
_fulfillWindow(auctionId, windowId);
|
||||
}
|
||||
|
||||
/*
|
||||
* @dev Fulfill a window index
|
||||
* @param a͟u͟c͟t͟i͟o͟n͟I͟d͟ Encoded auction parameter identifier
|
||||
*/
|
||||
function _fulfillWindow(bytes calldata auctionId, uint256 windowId) internal {
|
||||
Auction storage state = _auctions[auctionId];
|
||||
Window storage window = _window[auctionId][windowId];
|
||||
|
||||
if (window.expiry > block.timestamp) {
|
||||
if (isWindowActive(auctionId)) {
|
||||
revert WindowUnexpired();
|
||||
}
|
||||
if (window.processed) {
|
||||
@ -319,10 +356,12 @@ contract RDA is IRDA {
|
||||
|
||||
window.processed = true;
|
||||
|
||||
_auctions[auctionId].reserves -= volume / price;
|
||||
_auctions[auctionId].proceeds += volume;
|
||||
uint256 orderAmount = volume * 1e18 / price;
|
||||
|
||||
_claims[bidder][auctionId] = abi.encode(refund - volume, claim + (volume / price));
|
||||
state.reserves -= orderAmount;
|
||||
state.proceeds += volume;
|
||||
|
||||
_claims[bidder][auctionId] = abi.encode(refund - volume, claim + orderAmount);
|
||||
|
||||
emit Fulfillment(auctionId, window.bidId, windowId);
|
||||
}
|
||||
@ -331,53 +370,64 @@ contract RDA is IRDA {
|
||||
* @dev Helper to view an auction's remaining duration
|
||||
* @param a͟u͟c͟t͟i͟o͟n͟I͟d͟ Encoded auction parameter identifier
|
||||
*/
|
||||
function remainingTime(bytes memory auctionId) public view returns (uint256) {
|
||||
uint256 endTimestamp = _auctions[auctionId].endTimestamp;
|
||||
|
||||
if (endTimestamp > block.timestamp) {
|
||||
return endTimestamp - block.timestamp;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
function remainingTime(bytes calldata auctionId) public view returns (uint256) {
|
||||
return _auctions[auctionId].duration - elapsedTime(auctionId);
|
||||
}
|
||||
|
||||
/*
|
||||
* @dev Helper to view an auction's active remaining window duration
|
||||
* @param a͟u͟c͟t͟i͟o͟n͟I͟d͟ Encoded auction parameter identifier
|
||||
*/
|
||||
function remainingWindowTime(bytes memory auctionId) public view returns (uint256) {
|
||||
uint256 expiryTimestamp = _window[auctionId][_windows[auctionId]].expiry;
|
||||
|
||||
if (expiryTimestamp > 0 && block.timestamp < expiryTimestamp) {
|
||||
return expiryTimestamp - block.timestamp;
|
||||
} else {
|
||||
function remainingWindowTime(bytes calldata auctionId) public view returns (uint256) {
|
||||
if (!isWindowActive(auctionId)) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return _window[auctionId][_windows[auctionId]].expiry - block.timestamp;
|
||||
}
|
||||
|
||||
/*
|
||||
* @dev Helper to view an auction's progress in unix time
|
||||
* @param a͟u͟c͟t͟i͟o͟n͟I͟d͟ Encoded auction parameter identifier
|
||||
*/
|
||||
function elapsedTime(bytes memory auctionId, uint256 timestamp) public view returns (uint256) {
|
||||
uint256 windowIndex = _windows[auctionId] + 1;
|
||||
uint256 auctionElapsedTime = timestamp - _auctions[auctionId].startTimestamp;
|
||||
uint256 windowElapsedTime = _auctions[auctionId].windowDuration * windowIndex;
|
||||
function elapsedTime(bytes calldata auctionId) public view returns (uint256) {
|
||||
return block.timestamp - windowElapsedTime(auctionId) - _auctions[auctionId].startTimestamp;
|
||||
}
|
||||
|
||||
if (auctionElapsedTime > windowElapsedTime) {
|
||||
return auctionElapsedTime - windowElapsedTime;
|
||||
} else {
|
||||
return auctionElapsedTime;
|
||||
function windowElapsedTime(bytes calldata auctionId) public view returns (uint256) {
|
||||
if (!isWindowInit(auctionId)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint256 windowIndex = _windows[auctionId];
|
||||
uint256 elapsedWindowsTime = _auctions[auctionId].windowDuration * (windowIndex + 1);
|
||||
|
||||
return elapsedWindowsTime - remainingWindowTime(auctionId);
|
||||
}
|
||||
|
||||
function elapsedTimeFromWindow(bytes calldata auctionId) public view returns (uint256) {
|
||||
Auction storage state = _auctions[auctionId];
|
||||
|
||||
uint256 endTimestamp = state.windowTimestamp;
|
||||
|
||||
if (isWindowExpired(auctionId)) {
|
||||
endTimestamp = _window[auctionId][_windows[auctionId]].expiry;
|
||||
}
|
||||
|
||||
|
||||
return endTimestamp - windowElapsedTime(auctionId) - state.startTimestamp;
|
||||
}
|
||||
|
||||
/*
|
||||
* @dev Auction management redemption
|
||||
* @param a͟u͟c͟t͟i͟o͟n͟I͟d͟ Encoded auction parameter identifier
|
||||
*/
|
||||
function withdraw(bytes memory auctionId)
|
||||
function withdraw(bytes calldata auctionId)
|
||||
inactiveAuction(auctionId)
|
||||
external {
|
||||
override external {
|
||||
ERC20 tokenReserve = ERC20(reserveToken(auctionId));
|
||||
ERC20 tokenPurchase = ERC20(purchaseToken(auctionId));
|
||||
|
||||
uint256 proceeds = _auctions[auctionId].proceeds;
|
||||
uint256 reserves = _auctions[auctionId].reserves;
|
||||
|
||||
@ -385,10 +435,10 @@ contract RDA is IRDA {
|
||||
delete _auctions[auctionId].reserves;
|
||||
|
||||
if (proceeds > 0) {
|
||||
IERC20(purchaseToken(auctionId)).transfer(operatorAddress(auctionId), proceeds);
|
||||
tokenPurchase.safeTransfer(operatorAddress(auctionId), proceeds);
|
||||
}
|
||||
if (reserves > 0) {
|
||||
IERC20(reserveToken(auctionId)).transfer(operatorAddress(auctionId), reserves);
|
||||
tokenReserve.safeTransfer(operatorAddress(auctionId), reserves);
|
||||
}
|
||||
|
||||
emit Withdraw(auctionId);
|
||||
@ -398,24 +448,23 @@ contract RDA is IRDA {
|
||||
* @dev Auction order and refund redemption
|
||||
* @param a͟u͟c͟t͟i͟o͟n͟I͟d͟ Encoded auction parameter identifier
|
||||
*/
|
||||
function redeem(address bidder, bytes memory auctionId)
|
||||
function redeem(address bidder, bytes calldata auctionId)
|
||||
inactiveAuction(auctionId)
|
||||
external {
|
||||
bytes memory claimHash = _claims[bidder][auctionId];
|
||||
override external {
|
||||
ERC20 tokenReserve = ERC20(reserveToken(auctionId));
|
||||
ERC20 tokenPurchase = ERC20(purchaseToken(auctionId));
|
||||
|
||||
delete _claims[bidder][auctionId];
|
||||
bytes memory claimHash = _claims[bidder][auctionId];
|
||||
|
||||
(uint256 refund, uint256 claim) = balancesOf(claimHash);
|
||||
|
||||
uint256 vestingTimestamp = block.timestamp + _vesting[auctionId].period;
|
||||
address vestingAddress = _vesting[auctionId].instance;
|
||||
delete _claims[bidder][auctionId];
|
||||
|
||||
if (refund > 0) {
|
||||
IERC20(purchaseToken(auctionId)).transfer(bidder, refund);
|
||||
tokenPurchase.safeTransfer(bidder, refund);
|
||||
}
|
||||
if (claim > 0) {
|
||||
IERC20(reserveToken(auctionId)).approve(vestingAddress, claim);
|
||||
IDelegatedVesting(vestingAddress).makeCommitment(bidder, claim, vestingTimestamp);
|
||||
tokenReserve.safeTransfer(bidder, claim);
|
||||
}
|
||||
|
||||
emit Claim(auctionId, claimHash);
|
||||
|
Loading…
Reference in New Issue
Block a user