Skip to content

Instantly share code, notes, and snippets.

@transmissions11
Last active December 1, 2022 20:58
Show Gist options
  • Save transmissions11/485a6e2deb89236202bd2f59796262fd to your computer and use it in GitHub Desktop.
Save transmissions11/485a6e2deb89236202bd2f59796262fd to your computer and use it in GitHub Desktop.
import "./VRGDAC.sol";
import "./GameToken.sol";
import "solmate/tokens/ERC20.sol";
import "solmate/auth/Owned.sol";
contract ExchangePort is VRGDAC, Owned(msg.sender) {
// THIS SHIT IS GETTING CHEAPER OVER TIME!!!
GameToken public X;
GameToken public Y;
constructor(int256 _targetPrice, int256 _perTimeUnit, int256 _priceDecayPercent, GameToken _X, GameToken _Y)
VRGDAC(_targetPrice, _perTimeUnit, _priceDecayPercent)
{
X = _X;
Y = _Y;
}
uint256 startTime;
function setStartTime(uint256 _startTime) public onlyOwner {
startTime = _startTime;
}
int256 emittedXWad;
function buyX(address guy, uint256 amount) public onlyOwner {
int256 spentY = buyXQuote(amount);
Y.burn(guy, uint256(spentY));
X.mint(guy, amount);
emittedXWad += int256(amount);
}
function sellX(address guy, uint256 amount) public onlyOwner {
int256 gainedY = sellXQuote(amount);
X.burn(guy, amount);
Y.mint(guy, uint256(gainedY));
emittedXWad -= int256(amount);
}
function buyY(address guy, uint256 amount) public onlyOwner {
int256 spentX = buyYQuote(amount);
X.burn(guy, uint256(spentX));
Y.mint(msg.sender, amount);
emittedXWad -= int256(spentX);
}
function sellY(address guy, uint256 amount) public onlyOwner {
int256 gainedX = sellYQuote(amount);
Y.burn(guy, amount);
X.mint(guy, uint256(gainedX));
emittedXWad += int256(gainedX);
}
function buyXQuote(uint256 amount) public view returns (int256 spentY) {
return xToY({
timeSinceStart: int256(block.timestamp - startTime) * 1e18,
sold: emittedXWad,
amount: int256(amount)
});
}
function sellXQuote(uint256 amount) public view returns (int256 gainedY) {
return -xToY({timeSinceStart: int256(block.timestamp - startTime) * 1e18, sold: emittedXWad, amount: -int256(amount)});
}
function buyYQuote(uint256 amount) public view returns (int256 spentX) {
return -yToX({timeSinceStart: int256(block.timestamp - startTime) * 1e18, sold: emittedXWad, amount: -int256(amount)});
}
function sellYQuote(uint256 amount) public view returns (int256 gainedX) {
return yToX({
timeSinceStart: int256(block.timestamp - startTime) * 1e18,
sold: emittedXWad,
amount: int256(amount)
});
}
}
// SPDX-License-Identifier: MIT
pragma solidity >=0.8.0;
import {
wadExp,
wadLn,
wadMul,
wadDiv,
unsafeWadMul,
unsafeWadDiv,
toWadUnsafe,
wadPow
} from "solmate/utils/SignedWadMath.sol";
/// @title Continuous Variable Rate Gradual Dutch Auction
/// @author transmissions11 <t11s@paradigm.xyz>
/// @author FrankieIsLost <frankie@paradigm.xyz>
/// @author Dan Robinson <dan@paradigm.xyz>
/// @notice Sell tokens roughly according to an issuance schedule.
contract VRGDAC {
/*//////////////////////////////////////////////////////////////
VRGDA PARAMETERS
//////////////////////////////////////////////////////////////*/
int256 public immutable targetPrice;
int256 public immutable perTimeUnit;
int256 public immutable decayConstant;
int256 public immutable priceDecayPercent;
/// @notice Sets target price and per time unit price decay for the VRGDA.
/// @param _targetPrice The target price for a token if sold on pace, scaled by 1e18.
/// @param _perTimeUnit The number of tokens to target selling in 1 full unit of time, scaled by 1e18.
/// @param _priceDecayPercent The percent price decays per unit of time with no sales, scaled by 1e18.
constructor(int256 _targetPrice, int256 _perTimeUnit, int256 _priceDecayPercent) {
targetPrice = _targetPrice;
perTimeUnit = _perTimeUnit;
priceDecayPercent = _priceDecayPercent;
decayConstant = wadLn(1e18 - _priceDecayPercent);
// The decay constant must be negative for VRGDAs to work.
require(decayConstant < 0, "NON_NEGATIVE_DECAY_CONSTANT");
}
/*//////////////////////////////////////////////////////////////
PRICING LOGIC
//////////////////////////////////////////////////////////////*/
function xToY(int256 timeSinceStart, int256 sold, int256 amount) public view virtual returns (int256) {
unchecked {
return pIntegral(timeSinceStart, sold + amount) - pIntegral(timeSinceStart, sold);
}
}
function yToX(int256 timeSinceStart, int256 sold, int256 amount) public view virtual returns (int256) {
unchecked {
return wadMul(
-wadDiv(
wadLn(1e18 - wadMul(amount, wadDiv(decayConstant, wadMul(perTimeUnit, p(timeSinceStart, sold))))),
decayConstant
),
perTimeUnit
);
}
}
function pIntegral(int256 timeSinceStart, int256 sold) internal view returns (int256) {
return wadDiv(
-wadMul(
wadMul(targetPrice, perTimeUnit),
wadPow(1e18 - priceDecayPercent, timeSinceStart - unsafeWadDiv(sold, perTimeUnit))
),
decayConstant
);
}
function p(int256 timeSinceStart, int256 sold) internal view returns (int256) {
return wadMul(targetPrice, wadPow(1e18 - priceDecayPercent, timeSinceStart - unsafeWadDiv(sold, perTimeUnit)));
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment