文件 1 的 40:AbstractOwned.sol
pragma solidity ^0.8.9;
abstract contract AbstractOwned {
address public owner;
address public nominatedOwner;
function nominateNewOwner(address _owner) external onlyOwner {
nominatedOwner = _owner;
emit OwnerNominated(_owner);
}
function acceptOwnership() external {
if (msg.sender != nominatedOwner) {
revert OnlyNominatedOwner(address(this), msg.sender, nominatedOwner);
}
emit OwnerChanged(owner, nominatedOwner);
owner = nominatedOwner;
nominatedOwner = address(0);
}
modifier onlyOwner() {
_onlyOwner();
_;
}
function _onlyOwner() private view {
if (msg.sender != owner) {
revert OnlyOwner(address(this), msg.sender, owner);
}
}
event OwnerNominated(address newOwner);
event OwnerChanged(address oldOwner, address newOwner);
error OnlyOwner(address thrower, address caller, address owner);
error OnlyNominatedOwner(address thrower, address caller, address nominatedOwner);
}
文件 2 的 40:BasePositionHandler.sol
pragma solidity ^0.8.0;
abstract contract BasePositionHandler {
event Deposit(uint256 indexed amount);
event Withdraw(uint256 indexed amount);
event Claim(uint256 indexed amount);
struct Position {
uint256 posValue;
uint256 lastUpdatedBlock;
}
function positionInWantToken()
external
view
virtual
returns (uint256, uint256);
function _openPosition(bytes calldata _data) internal virtual;
function _closePosition(bytes calldata _data) internal virtual;
function _deposit(bytes calldata _data) internal virtual;
function _withdraw(bytes calldata _data) internal virtual;
function _claimRewards(bytes calldata _data) internal virtual;
}
文件 3 的 40:BaseTradeExecutor.sol
pragma solidity ^0.8.4;
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "../interfaces/ITradeExecutor.sol";
import "../interfaces/IVault.sol";
abstract contract BaseTradeExecutor is ITradeExecutor {
uint256 internal constant MAX_INT = type(uint256).max;
ActionStatus public override depositStatus;
ActionStatus public override withdrawalStatus;
address public override vault;
constructor(address _vault) {
vault = _vault;
IERC20(vaultWantToken()).approve(vault, MAX_INT);
}
function vaultWantToken() public view returns (address) {
return IVault(vault).wantToken();
}
function governance() public view returns (address) {
return IVault(vault).governance();
}
function keeper() public view returns (address) {
return IVault(vault).keeper();
}
modifier onlyGovernance() {
require(msg.sender == governance(), "ONLY_GOV");
_;
}
modifier onlyKeeper() {
require(msg.sender == keeper(), "ONLY_KEEPER");
_;
}
modifier keeperOrGovernance() {
require(
msg.sender == keeper() || msg.sender == governance(),
"ONLY_KEEPER_OR_GOVERNANCE"
);
_;
}
function sweep(address _token) public onlyGovernance {
IERC20(_token).transfer(
governance(),
IERC20(_token).balanceOf(address(this))
);
}
function initiateDeposit(bytes calldata _data) public override onlyKeeper {
require(!depositStatus.inProcess, "DEPOSIT_IN_PROGRESS");
depositStatus.inProcess = true;
_initateDeposit(_data);
}
function confirmDeposit() public override onlyKeeper {
require(depositStatus.inProcess, "DEPOSIT_COMPLETED");
depositStatus.inProcess = false;
_confirmDeposit();
}
function initiateWithdraw(bytes calldata _data) public override onlyKeeper {
require(!withdrawalStatus.inProcess, "WITHDRAW_IN_PROGRESS");
withdrawalStatus.inProcess = true;
_initiateWithdraw(_data);
}
function confirmWithdraw() public override onlyKeeper {
require(withdrawalStatus.inProcess, "WITHDRAW_COMPLETED");
withdrawalStatus.inProcess = false;
_confirmWithdraw();
}
function _initateDeposit(bytes calldata _data) internal virtual;
function _confirmDeposit() internal virtual;
function _initiateWithdraw(bytes calldata _data) internal virtual;
function _confirmWithdraw() internal virtual;
}
文件 4 的 40:BasicFeeCounter.sol
pragma solidity 0.8.9;
import "../synthetix/Owned.sol";
import "../interfaces/IFeeCounter.sol";
contract BasicFeeCounter is IFeeCounter, Owned {
mapping(address => bool) public trustedCounter;
mapping(address => mapping(address => uint)) public totalFeesPerMarket;
constructor() Owned() {}
function setTrustedCounter(address counter, bool isTrusted) external onlyOwner {
trustedCounter[counter] = isTrusted;
}
function trackFee(
address market,
address trader,
uint,
uint,
uint totalFee
) external onlyTrustedCounter {
totalFeesPerMarket[market][trader] += totalFee;
}
modifier onlyTrustedCounter() {
require(trustedCounter[msg.sender], "not trusted counter");
_;
}
}
文件 5 的 40:BlackScholes.sol
pragma solidity 0.8.9;
import "../synthetix/SignedDecimalMath.sol";
import "../synthetix/DecimalMath.sol";
import "./FixedPointMathLib.sol";
library BlackScholes {
using DecimalMath for uint;
using SignedDecimalMath for int;
struct PricesDeltaStdVega {
uint callPrice;
uint putPrice;
int callDelta;
int putDelta;
uint vega;
uint stdVega;
}
struct BlackScholesInputs {
uint timeToExpirySec;
uint volatilityDecimal;
uint spotDecimal;
uint strikePriceDecimal;
int rateDecimal;
}
uint private constant SECONDS_PER_YEAR = 31536000;
uint private constant PRECISE_UNIT = 1e27;
uint private constant SQRT_TWOPI = 2506628274631000502415765285;
int private constant MIN_CDF_STD_DIST_INPUT = (int(PRECISE_UNIT) * -45) / 10;
int private constant MAX_CDF_STD_DIST_INPUT = int(PRECISE_UNIT) * 10;
uint private constant MIN_T_ANNUALISED = PRECISE_UNIT / SECONDS_PER_YEAR;
uint private constant MIN_VOLATILITY = PRECISE_UNIT / 10000;
uint private constant VEGA_STANDARDISATION_MIN_DAYS = 7 days;
uint private constant SPLIT = 7071067811865470000000000000;
uint private constant N0 = 220206867912376000000000000000;
uint private constant N1 = 221213596169931000000000000000;
uint private constant N2 = 112079291497871000000000000000;
uint private constant N3 = 33912866078383000000000000000;
uint private constant N4 = 6373962203531650000000000000;
uint private constant N5 = 700383064443688000000000000;
uint private constant N6 = 35262496599891100000000000;
uint private constant M0 = 440413735824752000000000000000;
uint private constant M1 = 793826512519948000000000000000;
uint private constant M2 = 637333633378831000000000000000;
uint private constant M3 = 296564248779674000000000000000;
uint private constant M4 = 86780732202946100000000000000;
uint private constant M5 = 16064177579207000000000000000;
uint private constant M6 = 1755667163182640000000000000;
uint private constant M7 = 88388347648318400000000000;
function optionPrices(BlackScholesInputs memory bsInput) public pure returns (uint call, uint put) {
uint tAnnualised = _annualise(bsInput.timeToExpirySec);
uint spotPrecise = bsInput.spotDecimal.decimalToPreciseDecimal();
uint strikePricePrecise = bsInput.strikePriceDecimal.decimalToPreciseDecimal();
int ratePrecise = bsInput.rateDecimal.decimalToPreciseDecimal();
(int d1, int d2) = _d1d2(
tAnnualised,
bsInput.volatilityDecimal.decimalToPreciseDecimal(),
spotPrecise,
strikePricePrecise,
ratePrecise
);
(call, put) = _optionPrices(tAnnualised, spotPrecise, strikePricePrecise, ratePrecise, d1, d2);
return (call.preciseDecimalToDecimal(), put.preciseDecimalToDecimal());
}
function pricesDeltaStdVega(BlackScholesInputs memory bsInput) public pure returns (PricesDeltaStdVega memory) {
uint tAnnualised = _annualise(bsInput.timeToExpirySec);
uint spotPrecise = bsInput.spotDecimal.decimalToPreciseDecimal();
(int d1, int d2) = _d1d2(
tAnnualised,
bsInput.volatilityDecimal.decimalToPreciseDecimal(),
spotPrecise,
bsInput.strikePriceDecimal.decimalToPreciseDecimal(),
bsInput.rateDecimal.decimalToPreciseDecimal()
);
(uint callPrice, uint putPrice) = _optionPrices(
tAnnualised,
spotPrecise,
bsInput.strikePriceDecimal.decimalToPreciseDecimal(),
bsInput.rateDecimal.decimalToPreciseDecimal(),
d1,
d2
);
(uint vegaPrecise, uint stdVegaPrecise) = _standardVega(d1, spotPrecise, bsInput.timeToExpirySec);
(int callDelta, int putDelta) = _delta(d1);
return
PricesDeltaStdVega(
callPrice.preciseDecimalToDecimal(),
putPrice.preciseDecimalToDecimal(),
callDelta.preciseDecimalToDecimal(),
putDelta.preciseDecimalToDecimal(),
vegaPrecise.preciseDecimalToDecimal(),
stdVegaPrecise.preciseDecimalToDecimal()
);
}
function delta(BlackScholesInputs memory bsInput) public pure returns (int callDeltaDecimal, int putDeltaDecimal) {
uint tAnnualised = _annualise(bsInput.timeToExpirySec);
uint spotPrecise = bsInput.spotDecimal.decimalToPreciseDecimal();
(int d1, ) = _d1d2(
tAnnualised,
bsInput.volatilityDecimal.decimalToPreciseDecimal(),
spotPrecise,
bsInput.strikePriceDecimal.decimalToPreciseDecimal(),
bsInput.rateDecimal.decimalToPreciseDecimal()
);
(int callDelta, int putDelta) = _delta(d1);
return (callDelta.preciseDecimalToDecimal(), putDelta.preciseDecimalToDecimal());
}
function vega(BlackScholesInputs memory bsInput) public pure returns (uint vegaDecimal) {
uint tAnnualised = _annualise(bsInput.timeToExpirySec);
uint spotPrecise = bsInput.spotDecimal.decimalToPreciseDecimal();
(int d1, ) = _d1d2(
tAnnualised,
bsInput.volatilityDecimal.decimalToPreciseDecimal(),
spotPrecise,
bsInput.strikePriceDecimal.decimalToPreciseDecimal(),
bsInput.rateDecimal.decimalToPreciseDecimal()
);
return _vega(tAnnualised, spotPrecise, d1).preciseDecimalToDecimal();
}
function _d1d2(
uint tAnnualised,
uint volatility,
uint spot,
uint strikePrice,
int rate
) internal pure returns (int d1, int d2) {
tAnnualised = tAnnualised < MIN_T_ANNUALISED ? MIN_T_ANNUALISED : tAnnualised;
volatility = volatility < MIN_VOLATILITY ? MIN_VOLATILITY : volatility;
int vtSqrt = int(volatility.multiplyDecimalRoundPrecise(_sqrtPrecise(tAnnualised)));
int log = FixedPointMathLib.lnPrecise(int(spot.divideDecimalRoundPrecise(strikePrice)));
int v2t = (int(volatility.multiplyDecimalRoundPrecise(volatility) / 2) + rate).multiplyDecimalRoundPrecise(
int(tAnnualised)
);
d1 = (log + v2t).divideDecimalRoundPrecise(vtSqrt);
d2 = d1 - vtSqrt;
}
function _optionPrices(
uint tAnnualised,
uint spot,
uint strikePrice,
int rate,
int d1,
int d2
) internal pure returns (uint call, uint put) {
uint strikePricePV = strikePrice.multiplyDecimalRoundPrecise(
FixedPointMathLib.expPrecise(int(-rate.multiplyDecimalRoundPrecise(int(tAnnualised))))
);
uint spotNd1 = spot.multiplyDecimalRoundPrecise(_stdNormalCDF(d1));
uint strikePriceNd2 = strikePricePV.multiplyDecimalRoundPrecise(_stdNormalCDF(d2));
call = strikePriceNd2 <= spotNd1 ? spotNd1 - strikePriceNd2 : 0;
put = call + strikePricePV;
put = spot <= put ? put - spot : 0;
}
function _delta(int d1) internal pure returns (int callDelta, int putDelta) {
callDelta = int(_stdNormalCDF(d1));
putDelta = callDelta - int(PRECISE_UNIT);
}
function _vega(
uint tAnnualised,
uint spot,
int d1
) internal pure returns (uint) {
return _sqrtPrecise(tAnnualised).multiplyDecimalRoundPrecise(_stdNormal(d1).multiplyDecimalRoundPrecise(spot));
}
function _standardVega(
int d1,
uint spot,
uint timeToExpirySec
) internal pure returns (uint, uint) {
uint tAnnualised = _annualise(timeToExpirySec);
uint normalisationFactor = _getVegaNormalisationFactorPrecise(timeToExpirySec);
uint vegaPrecise = _vega(tAnnualised, spot, d1);
return (vegaPrecise, vegaPrecise.multiplyDecimalRoundPrecise(normalisationFactor));
}
function _getVegaNormalisationFactorPrecise(uint timeToExpirySec) internal pure returns (uint) {
timeToExpirySec = timeToExpirySec < VEGA_STANDARDISATION_MIN_DAYS ? VEGA_STANDARDISATION_MIN_DAYS : timeToExpirySec;
uint daysToExpiry = timeToExpirySec / 1 days;
uint thirty = 30 * PRECISE_UNIT;
return _sqrtPrecise(thirty / daysToExpiry) / 100;
}
function _abs(int val) internal pure returns (uint) {
return uint(val < 0 ? -val : val);
}
function _sqrt(uint x) internal pure returns (uint result) {
if (x == 0) {
return 0;
}
uint xAux = uint(x);
result = 1;
if (xAux >= 0x100000000000000000000000000000000) {
xAux >>= 128;
result <<= 64;
}
if (xAux >= 0x10000000000000000) {
xAux >>= 64;
result <<= 32;
}
if (xAux >= 0x100000000) {
xAux >>= 32;
result <<= 16;
}
if (xAux >= 0x10000) {
xAux >>= 16;
result <<= 8;
}
if (xAux >= 0x100) {
xAux >>= 8;
result <<= 4;
}
if (xAux >= 0x10) {
xAux >>= 4;
result <<= 2;
}
if (xAux >= 0x8) {
result <<= 1;
}
unchecked {
result = (result + x / result) >> 1;
result = (result + x / result) >> 1;
result = (result + x / result) >> 1;
result = (result + x / result) >> 1;
result = (result + x / result) >> 1;
result = (result + x / result) >> 1;
result = (result + x / result) >> 1;
uint roundedDownResult = x / result;
return result >= roundedDownResult ? roundedDownResult : result;
}
}
function _sqrtPrecise(uint x) internal pure returns (uint) {
return _sqrt(x * PRECISE_UNIT);
}
function _stdNormal(int x) internal pure returns (uint) {
return
FixedPointMathLib.expPrecise(int(-x.multiplyDecimalRoundPrecise(x / 2))).divideDecimalRoundPrecise(SQRT_TWOPI);
}
function _stdNormalCDF(int x) public pure returns (uint) {
uint z = _abs(x);
int c;
if (z <= 37 * PRECISE_UNIT) {
uint e = FixedPointMathLib.expPrecise(-int(z.multiplyDecimalRoundPrecise(z / 2)));
if (z < SPLIT) {
c = int(
(_stdNormalCDFNumerator(z).divideDecimalRoundPrecise(_stdNormalCDFDenom(z)).multiplyDecimalRoundPrecise(e))
);
} else {
uint f = (z +
PRECISE_UNIT.divideDecimalRoundPrecise(
z +
(2 * PRECISE_UNIT).divideDecimalRoundPrecise(
z +
(3 * PRECISE_UNIT).divideDecimalRoundPrecise(
z + (4 * PRECISE_UNIT).divideDecimalRoundPrecise(z + ((PRECISE_UNIT * 13) / 20))
)
)
));
c = int(e.divideDecimalRoundPrecise(f.multiplyDecimalRoundPrecise(SQRT_TWOPI)));
}
}
return uint((x <= 0 ? c : (int(PRECISE_UNIT) - c)));
}
function _stdNormalCDFNumerator(uint z) internal pure returns (uint) {
uint numeratorInner = ((((((N6 * z) / PRECISE_UNIT + N5) * z) / PRECISE_UNIT + N4) * z) / PRECISE_UNIT + N3);
return (((((numeratorInner * z) / PRECISE_UNIT + N2) * z) / PRECISE_UNIT + N1) * z) / PRECISE_UNIT + N0;
}
function _stdNormalCDFDenom(uint z) internal pure returns (uint) {
uint denominatorInner = ((((((M7 * z) / PRECISE_UNIT + M6) * z) / PRECISE_UNIT + M5) * z) / PRECISE_UNIT + M4);
return
(((((((denominatorInner * z) / PRECISE_UNIT + M3) * z) / PRECISE_UNIT + M2) * z) / PRECISE_UNIT + M1) * z) /
PRECISE_UNIT +
M0;
}
function _annualise(uint secs) internal pure returns (uint yearFraction) {
return secs.divideDecimalRoundPrecise(SECONDS_PER_YEAR);
}
}
文件 6 的 40:Context.sol
pragma solidity ^0.8.0;
abstract contract Context {
function _msgSender() internal view virtual returns (address) {
return msg.sender;
}
function _msgData() internal view virtual returns (bytes calldata) {
return msg.data;
}
}
文件 7 的 40:DecimalMath.sol
pragma solidity ^0.8.9;
library DecimalMath {
uint8 public constant decimals = 18;
uint8 public constant highPrecisionDecimals = 27;
uint public constant UNIT = 10**uint(decimals);
uint public constant PRECISE_UNIT = 10**uint(highPrecisionDecimals);
uint private constant UNIT_TO_HIGH_PRECISION_CONVERSION_FACTOR = 10**uint(highPrecisionDecimals - decimals);
function unit() external pure returns (uint) {
return UNIT;
}
function preciseUnit() external pure returns (uint) {
return PRECISE_UNIT;
}
function multiplyDecimal(uint x, uint y) internal pure returns (uint) {
return (x * y) / UNIT;
}
function _multiplyDecimalRound(
uint x,
uint y,
uint precisionUnit
) private pure returns (uint) {
uint quotientTimesTen = (x * y) / (precisionUnit / 10);
if (quotientTimesTen % 10 >= 5) {
quotientTimesTen += 10;
}
return quotientTimesTen / 10;
}
function multiplyDecimalRoundPrecise(uint x, uint y) internal pure returns (uint) {
return _multiplyDecimalRound(x, y, PRECISE_UNIT);
}
function multiplyDecimalRound(uint x, uint y) internal pure returns (uint) {
return _multiplyDecimalRound(x, y, UNIT);
}
function divideDecimal(uint x, uint y) internal pure returns (uint) {
return (x * UNIT) / y;
}
function _divideDecimalRound(
uint x,
uint y,
uint precisionUnit
) private pure returns (uint) {
uint resultTimesTen = (x * (precisionUnit * 10)) / y;
if (resultTimesTen % 10 >= 5) {
resultTimesTen += 10;
}
return resultTimesTen / 10;
}
function divideDecimalRound(uint x, uint y) internal pure returns (uint) {
return _divideDecimalRound(x, y, UNIT);
}
function divideDecimalRoundPrecise(uint x, uint y) internal pure returns (uint) {
return _divideDecimalRound(x, y, PRECISE_UNIT);
}
function decimalToPreciseDecimal(uint i) internal pure returns (uint) {
return i * UNIT_TO_HIGH_PRECISION_CONVERSION_FACTOR;
}
function preciseDecimalToDecimal(uint i) internal pure returns (uint) {
uint quotientTimesTen = i / (UNIT_TO_HIGH_PRECISION_CONVERSION_FACTOR / 10);
if (quotientTimesTen % 10 >= 5) {
quotientTimesTen += 10;
}
return quotientTimesTen / 10;
}
}
文件 8 的 40:FixedPointMathLib.sol
pragma solidity 0.8.9;
library FixedPointMathLib {
function lnPrecise(int x) internal pure returns (int r) {
return ln(x / 1e9) * 1e9;
}
function expPrecise(int x) internal pure returns (uint r) {
return exp(x / 1e9) * 1e9;
}
function ln(int x) internal pure returns (int r) {
unchecked {
if (x < 1) {
if (x < 0) revert LnNegativeUndefined();
revert Overflow();
}
int k = int(ilog2(uint(x))) - 96;
x <<= uint(159 - k);
x = int(uint(x) >> 159);
int p = x + 3273285459638523848632254066296;
p = ((p * x) >> 96) + 24828157081833163892658089445524;
p = ((p * x) >> 96) + 43456485725739037958740375743393;
p = ((p * x) >> 96) - 11111509109440967052023855526967;
p = ((p * x) >> 96) - 45023709667254063763336534515857;
p = ((p * x) >> 96) - 14706773417378608786704636184526;
p = p * x - (795164235651350426258249787498 << 96);
int q = x + 5573035233440673466300451813936;
q = ((q * x) >> 96) + 71694874799317883764090561454958;
q = ((q * x) >> 96) + 283447036172924575727196451306956;
q = ((q * x) >> 96) + 401686690394027663651624208769553;
q = ((q * x) >> 96) + 204048457590392012362485061816622;
q = ((q * x) >> 96) + 31853899698501571402653359427138;
q = ((q * x) >> 96) + 909429971244387300277376558375;
assembly {
r := sdiv(p, q)
}
r *= 1677202110996718588342820967067443963516166;
r += 16597577552685614221487285958193947469193820559219878177908093499208371 * k;
r += 600920179829731861736702779321621459595472258049074101567377883020018308;
r >>= 174;
}
}
function ilog2(uint x) internal pure returns (uint r) {
assembly {
r := shl(7, lt(0xffffffffffffffffffffffffffffffff, x))
r := or(r, shl(6, lt(0xffffffffffffffff, shr(r, x))))
r := or(r, shl(5, lt(0xffffffff, shr(r, x))))
r := or(r, shl(4, lt(0xffff, shr(r, x))))
r := or(r, shl(3, lt(0xff, shr(r, x))))
r := or(r, shl(2, lt(0xf, shr(r, x))))
r := or(r, shl(1, lt(0x3, shr(r, x))))
r := or(r, lt(0x1, shr(r, x)))
}
}
function exp(int x) internal pure returns (uint r) {
unchecked {
if (x <= -42139678854452767551) {
return 0;
}
if (x >= 135305999368893231589) revert ExpOverflow();
x = (x << 78) / 5**18;
int k = ((x << 96) / 54916777467707473351141471128 + 2**95) >> 96;
x = x - k * 54916777467707473351141471128;
int p = x + 2772001395605857295435445496992;
p = ((p * x) >> 96) + 44335888930127919016834873520032;
p = ((p * x) >> 96) + 398888492587501845352592340339721;
p = ((p * x) >> 96) + 1993839819670624470859228494792842;
p = p * x + (4385272521454847904632057985693276 << 96);
int z = x + 750530180792738023273180420736;
z = ((z * x) >> 96) + 32788456221302202726307501949080;
int w = x - 2218138959503481824038194425854;
w = ((w * z) >> 96) + 892943633302991980437332862907700;
int q = z + w - 78174809823045304726920794422040;
q = ((q * w) >> 96) + 4203224763890128580604056984195872;
assembly {
r := sdiv(p, q)
}
r = (uint(r) * 3822833074963236453042738258902158003155416615667) >> uint(195 - k);
}
}
error Overflow();
error ExpOverflow();
error LnNegativeUndefined();
}
文件 9 的 40:GWAV.sol
pragma solidity 0.8.9;
import "../synthetix/SignedDecimalMath.sol";
import "../synthetix/DecimalMath.sol";
import "./FixedPointMathLib.sol";
library GWAV {
using DecimalMath for uint;
using SignedDecimalMath for int;
struct Params {
Observation[] observations;
uint index;
}
struct Observation {
int q;
uint nextVal;
uint blockTimestamp;
}
function _initialize(
Params storage self,
uint newVal,
uint blockTimestamp
) internal {
_initializeWithManualQ(self, FixedPointMathLib.ln((int(newVal))) * int(blockTimestamp), newVal, blockTimestamp);
}
function _write(
Params storage self,
uint nextVal,
uint blockTimestamp
) internal {
Observation memory last = self.observations[self.index];
if (blockTimestamp < last.blockTimestamp) {
revert InvalidBlockTimestamp(address(this), blockTimestamp, last.blockTimestamp);
}
if (last.blockTimestamp == blockTimestamp) {
self.observations[self.index].nextVal = nextVal;
return;
}
if (last.nextVal == nextVal) return;
uint timestampDelta = blockTimestamp - last.blockTimestamp;
int newQ = last.q + FixedPointMathLib.ln((int(last.nextVal))) * int(timestampDelta);
uint indexUpdated = (self.index + 1);
self.observations.push(_transform(newQ, nextVal, blockTimestamp));
self.index = indexUpdated;
}
function getGWAVForPeriod(
Params storage self,
uint secondsAgoA,
uint secondsAgoB
) public view returns (uint) {
(int q0, uint t0) = queryFirstBeforeAndScale(self, block.timestamp, secondsAgoA);
(int q1, uint t1) = queryFirstBeforeAndScale(self, block.timestamp, secondsAgoB);
if (t0 == t1) {
return uint(FixedPointMathLib.exp(q1 / int(t1)));
}
return uint(FixedPointMathLib.exp((q1 - q0) / int(t1 - t0)));
}
function observe(
Params storage self,
uint currentBlockTimestamp,
uint[] memory secondsAgos
) public view returns (int[] memory qCumulatives, uint[] memory timestamps) {
uint secondsAgosLength = secondsAgos.length;
qCumulatives = new int[](secondsAgosLength);
timestamps = new uint[](secondsAgosLength);
for (uint i = 0; i < secondsAgosLength; ++i) {
(qCumulatives[i], timestamps[i]) = queryFirstBefore(self, currentBlockTimestamp, secondsAgos[i]);
}
}
function queryFirstBefore(
Params storage self,
uint currentBlockTimestamp,
uint secondsAgo
) internal view returns (int qCumulative, uint timestamp) {
uint target = currentBlockTimestamp - secondsAgo;
Observation memory beforeOrAt = _queryFirstBefore(self, target);
return (beforeOrAt.q, beforeOrAt.blockTimestamp);
}
function queryFirstBeforeAndScale(
Params storage self,
uint currentBlockTimestamp,
uint secondsAgo
) internal view returns (int qCumulative, uint timestamp) {
uint target = currentBlockTimestamp - secondsAgo;
Observation memory beforeOrAt = _queryFirstBefore(self, target);
int timestampDelta = int(target - beforeOrAt.blockTimestamp);
return (beforeOrAt.q + (FixedPointMathLib.ln(int(beforeOrAt.nextVal)) * timestampDelta), target);
}
function _queryFirstBefore(Params storage self, uint target) private view returns (Observation memory beforeOrAt) {
beforeOrAt = self.observations[self.index];
if (beforeOrAt.blockTimestamp <= target) {
return (beforeOrAt);
}
beforeOrAt = self.observations[0];
if (beforeOrAt.blockTimestamp > target) {
return _transform((beforeOrAt.q * int(target)) / int(beforeOrAt.blockTimestamp), beforeOrAt.nextVal, target);
}
return self.observations[_binarySearch(self, target)];
}
function _binarySearch(Params storage self, uint target) internal view returns (uint) {
uint oldest = 0;
uint newest = self.index;
uint i;
while (true) {
i = (oldest + newest) / 2;
uint beforeOrAtTimestamp = self.observations[i].blockTimestamp;
uint atOrAfterTimestamp = self.observations[i + 1].blockTimestamp;
bool targetAtOrAfter = beforeOrAtTimestamp <= target;
if (targetAtOrAfter && target <= atOrAfterTimestamp) break;
if (!targetAtOrAfter) {
newest = i - 1;
} else {
oldest = i + 1;
}
}
return i;
}
function _initializeWithManualQ(
Params storage self,
int qVal,
uint nextVal,
uint blockTimestamp
) internal {
self.observations.push(Observation({q: qVal, nextVal: nextVal, blockTimestamp: blockTimestamp}));
}
function _transform(
int newQ,
uint nextVal,
uint blockTimestamp
) private pure returns (Observation memory) {
return Observation({q: newQ, nextVal: nextVal, blockTimestamp: blockTimestamp});
}
error InvalidBlockTimestamp(address thrower, uint timestamp, uint lastObservedTimestamp);
}
文件 10 的 40:IAddressResolver.sol
pragma solidity ^0.8.9;
interface IAddressResolver {
function getAddress(bytes32 name) external view returns (address);
}
文件 11 的 40:ICrossDomainMessenger.sol
pragma solidity ^0.8.0;
pragma experimental ABIEncoderV2;
interface ICrossDomainMessenger {
event SentMessage(bytes message);
event RelayedMessage(bytes32 msgHash);
event FailedRelayedMessage(bytes32 msgHash);
event TransactionEnqueued(
address indexed _l1TxOrigin,
address indexed _target,
uint256 _gasLimit,
bytes _data,
uint256 indexed _queueIndex,
uint256 _timestamp
);
event QueueBatchAppended(
uint256 _startingQueueIndex,
uint256 _numQueueElements,
uint256 _totalElements
);
event SequencerBatchAppended(
uint256 _startingQueueIndex,
uint256 _numQueueElements,
uint256 _totalElements
);
event TransactionBatchAppended(
uint256 indexed _batchIndex,
bytes32 _batchRoot,
uint256 _batchSize,
uint256 _prevTotalElements,
bytes _extraData
);
function receivedMessages(bytes32 messageHash) external view returns (bool);
function sentMessages(bytes32 messageHash) external view returns (bool);
function targetMessengerAddress() external view returns (address);
function messageNonce() external view returns (uint256);
function xDomainMessageSender() external view returns (address);
function setTargetMessengerAddress(address _targetMessengerAddress)
external;
function sendMessage(
address _target,
bytes memory _message,
uint32 _gasLimit
) external;
}
文件 12 的 40:ICurve.sol
pragma solidity ^0.8.9;
interface ICurve {
function exchange_with_best_rate(
address _from,
address _to,
uint _amount,
uint _expected,
address _receiver
) external payable returns (uint amountOut);
function exchange_underlying(
int128 _from,
int128 _to,
uint _amount,
uint _expected
) external payable returns (uint amountOut);
function get_best_rate(
address _from,
address _to,
uint _amount
) external view returns (address pool, uint amountOut);
}
文件 13 的 40:IDelegateApprovals.sol
pragma solidity ^0.8.9;
interface IDelegateApprovals {
function approveExchangeOnBehalf(address delegate) external;
function canExchangeOnBehalf(address exchanger, address beneficiary) external view returns (bool);
}
文件 14 的 40:IERC165.sol
pragma solidity ^0.8.0;
interface IERC165 {
function supportsInterface(bytes4 interfaceId) external view returns (bool);
}
文件 15 的 40:IERC20.sol
pragma solidity ^0.8.0;
interface IERC20 {
event Transfer(address indexed from, address indexed to, uint256 value);
event Approval(address indexed owner, address indexed spender, uint256 value);
function totalSupply() external view returns (uint256);
function balanceOf(address account) external view returns (uint256);
function transfer(address to, uint256 amount) external returns (bool);
function allowance(address owner, address spender) external view returns (uint256);
function approve(address spender, uint256 amount) external returns (bool);
function transferFrom(
address from,
address to,
uint256 amount
) external returns (bool);
}
文件 16 的 40:IERC721.sol
pragma solidity ^0.8.0;
import "../../utils/introspection/IERC165.sol";
interface IERC721 is IERC165 {
event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);
event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);
event ApprovalForAll(address indexed owner, address indexed operator, bool approved);
function balanceOf(address owner) external view returns (uint256 balance);
function ownerOf(uint256 tokenId) external view returns (address owner);
function safeTransferFrom(
address from,
address to,
uint256 tokenId
) external;
function transferFrom(
address from,
address to,
uint256 tokenId
) external;
function approve(address to, uint256 tokenId) external;
function getApproved(uint256 tokenId) external view returns (address operator);
function setApprovalForAll(address operator, bool _approved) external;
function isApprovedForAll(address owner, address operator) external view returns (bool);
function safeTransferFrom(
address from,
address to,
uint256 tokenId,
bytes calldata data
) external;
}
文件 17 的 40:IExchangeRates.sol
pragma solidity ^0.8.9;
interface IExchangeRates {
function rateAndInvalid(bytes32 currencyKey) external view returns (uint rate, bool isInvalid);
}
文件 18 的 40:IExchanger.sol
pragma solidity ^0.8.9;
interface IExchanger {
function feeRateForExchange(bytes32 sourceCurrencyKey, bytes32 destinationCurrencyKey)
external
view
returns (uint exchangeFeeRate);
}
文件 19 的 40:IFeeCounter.sol
pragma solidity ^0.8.9;
interface IFeeCounter {
function trackFee(
address market,
address trader,
uint amount,
uint totalCost,
uint totalFee
) external;
}
文件 20 的 40:IGWAVOracle.sol
pragma solidity 0.8.9;
interface IGWAVOracle {
function ivGWAV(uint boardId, uint secondsAgo) external view returns (uint);
function skewGWAV(uint strikeId, uint secondsAgo) external view returns (uint);
function volGWAV(uint strikeId, uint secondsAgo) external view returns (uint);
function deltaGWAV(uint strikeId, uint secondsAgo) external view returns (int callDelta);
function vegaGWAV(uint strikeId, uint secondsAgo) external view returns (uint vega);
function optionPriceGWAV(uint strikeId, uint secondsAgo) external view returns (uint callPrice, uint putPrice);
}
文件 21 的 40:ILiquidityPool.sol
pragma solidity 0.8.9;
interface ILiquidityPool {
struct Collateral {
uint quote;
uint base;
}
struct Liquidity {
uint freeLiquidity;
uint burnableLiquidity;
uint usedCollatLiquidity;
uint pendingDeltaLiquidity;
uint usedDeltaLiquidity;
uint NAV;
}
struct QueuedDeposit {
uint id;
address beneficiary;
uint amountLiquidity;
uint mintedTokens;
uint depositInitiatedTime;
}
struct QueuedWithdrawal {
uint id;
address beneficiary;
uint amountTokens;
uint quoteSent;
uint withdrawInitiatedTime;
}
struct LiquidityPoolParameters {
uint minDepositWithdraw;
uint depositDelay;
uint withdrawalDelay;
uint withdrawalFee;
uint liquidityCBThreshold;
uint liquidityCBTimeout;
uint ivVarianceCBThreshold;
uint skewVarianceCBThreshold;
uint ivVarianceCBTimeout;
uint skewVarianceCBTimeout;
address guardianMultisig;
uint guardianDelay;
uint boardSettlementCBTimeout;
uint maxFeePaid;
}
function poolHedger() external view returns (address);
function queuedDeposits(uint id) external view returns (QueuedDeposit memory);
function totalQueuedDeposits() external view returns (uint);
function queuedDepositHead() external view returns (uint);
function nextQueuedDepositId() external view returns (uint);
function queuedWithdrawals(uint id) external view returns (QueuedWithdrawal memory);
function totalQueuedWithdrawals() external view returns (uint);
function queuedWithdrawalHead() external view returns (uint);
function nextQueuedWithdrawalId() external view returns (uint);
function CBTimestamp() external view returns (uint);
function lockedCollateral() external view returns (Collateral memory);
function totalOutstandingSettlements() external view returns (uint);
function insolventSettlementAmount() external view returns (uint);
function liquidationInsolventAmount() external view returns (uint);
function initiateDeposit(address beneficiary, uint amountQuote) external;
function initiateWithdraw(address beneficiary, uint amountLiquidityToken) external;
function processDepositQueue(uint limit) external;
function processWithdrawalQueue(uint limit) external;
function updateCBs() external;
function getTotalTokenSupply() external view returns (uint);
function getTokenPriceWithCheck()
external
view
returns (
uint tokenPrice,
bool isStale,
uint circuitBreakerExpiry
);
function getTokenPrice() external view returns (uint);
function getCurrentLiquidity() external view returns (Liquidity memory);
function getLiquidity(uint spotPrice) external view returns (Liquidity memory);
function getTotalPoolValueQuote() external view returns (uint);
function exchangeBase() external;
function getLpParams() external view returns (LiquidityPoolParameters memory);
event LiquidityPoolParametersUpdated(LiquidityPoolParameters lpParams);
event PoolHedgerUpdated(address poolHedger);
event QuoteLocked(uint quoteLocked, uint lockedCollateralQuote);
event QuoteFreed(uint quoteFreed, uint lockedCollateralQuote);
event BaseLocked(uint baseLocked, uint lockedCollateralBase);
event BaseFreed(uint baseFreed, uint lockedCollateralBase);
event BoardSettlement(uint insolventSettlementAmount, uint amountQuoteReserved, uint totalOutstandingSettlements);
event OutstandingSettlementSent(address indexed user, uint amount, uint totalOutstandingSettlements);
event BasePurchased(uint quoteSpent, uint baseReceived);
event BaseSold(uint amountBase, uint quoteReceived);
event PremiumTransferred(address indexed recipient, uint recipientPortion, uint optionMarketPortion);
event QuoteTransferredToPoolHedger(uint amountQuote);
event InsolventSettlementAmountUpdated(uint amountQuoteAdded, uint totalInsolventSettlementAmount);
event DepositQueued(
address indexed depositor,
address indexed beneficiary,
uint indexed depositQueueId,
uint amountDeposited,
uint totalQueuedDeposits,
uint timestamp
);
event DepositProcessed(
address indexed caller,
address indexed beneficiary,
uint indexed depositQueueId,
uint amountDeposited,
uint tokenPrice,
uint tokensReceived,
uint timestamp
);
event WithdrawProcessed(
address indexed caller,
address indexed beneficiary,
uint indexed withdrawalQueueId,
uint amountWithdrawn,
uint tokenPrice,
uint quoteReceived,
uint totalQueuedWithdrawals,
uint timestamp
);
event WithdrawPartiallyProcessed(
address indexed caller,
address indexed beneficiary,
uint indexed withdrawalQueueId,
uint amountWithdrawn,
uint tokenPrice,
uint quoteReceived,
uint totalQueuedWithdrawals,
uint timestamp
);
event WithdrawQueued(
address indexed withdrawer,
address indexed beneficiary,
uint indexed withdrawalQueueId,
uint amountWithdrawn,
uint totalQueuedWithdrawals,
uint timestamp
);
event CircuitBreakerUpdated(
uint newTimestamp,
bool ivVarianceThresholdCrossed,
bool skewVarianceThresholdCrossed,
bool liquidityThresholdCrossed
);
event BoardSettlementCircuitBreakerUpdated(uint newTimestamp);
event CheckingCanProcess(uint entryId, bool boardNotStale, bool validEntry, bool guardianBypass, bool delaysExpired);
error InvalidLiquidityPoolParameters(address thrower, LiquidityPoolParameters lpParams);
error InvalidBeneficiaryAddress(address thrower, address beneficiary);
error MinimumDepositNotMet(address thrower, uint amountQuote, uint minDeposit);
error MinimumWithdrawNotMet(address thrower, uint amountLiquidityToken, uint minWithdraw);
error LockingMoreQuoteThanIsFree(address thrower, uint quoteToLock, uint freeLiquidity, Collateral lockedCollateral);
error SendPremiumNotEnoughCollateral(address thrower, uint premium, uint reservedFee, uint freeLiquidity);
error NotEnoughFreeToReclaimInsolvency(address thrower, uint amountQuote, Liquidity liquidity);
error OptionValueDebtExceedsTotalAssets(address thrower, int totalAssetValue, int optionValueDebt);
error InsufficientFreeLiquidityForBaseExchange(
address thrower,
uint pendingBase,
uint estimatedExchangeCost,
uint freeLiquidity
);
error OnlyPoolHedger(address thrower, address caller, address poolHedger);
error OnlyOptionMarket(address thrower, address caller, address optionMarket);
error OnlyShortCollateral(address thrower, address caller, address poolHedger);
error QuoteTransferFailed(address thrower, address from, address to, uint amount);
error BaseTransferFailed(address thrower, address from, address to, uint amount);
}
文件 22 的 40:ILyraRegistry.sol
pragma solidity 0.8.9;
import "openzeppelin-contracts-4.4.1/token/ERC20/IERC20.sol";
interface ILyraRegistry {
struct OptionMarketAddresses {
address liquidityPool;
address liquidityToken;
address greekCache;
address optionMarket;
address optionMarketPricer;
address optionToken;
address poolHedger;
address shortCollateral;
address gwavOracle;
IERC20 quoteAsset;
IERC20 baseAsset;
}
function optionMarkets() external view returns (address[] memory);
function marketAddress(address market) external view returns (OptionMarketAddresses memory);
function globalAddresses(bytes32 name) external view returns (address);
function getMarketAddresses(address optionMarket) external view returns (OptionMarketAddresses memory);
function getGlobalAddress(bytes32 contractName) external view returns (address globalContract);
event GlobalAddressUpdated(bytes32 indexed name, address addr);
event MarketUpdated(address indexed optionMarket, OptionMarketAddresses market);
event MarketRemoved(address indexed market);
error RemovingInvalidMarket(address thrower, address market);
error NonExistentMarket(address optionMarket);
error NonExistentGlobalContract(bytes32 contractName);
}
文件 23 的 40:IOptionGreekCache.sol
pragma solidity 0.8.9;
import "./IOptionMarket.sol";
interface IOptionGreekCache {
struct GreekCacheParameters {
uint maxStrikesPerBoard;
uint acceptableSpotPricePercentMove;
uint staleUpdateDuration;
uint varianceIvGWAVPeriod;
uint varianceSkewGWAVPeriod;
uint optionValueIvGWAVPeriod;
uint optionValueSkewGWAVPeriod;
uint gwavSkewFloor;
uint gwavSkewCap;
int rateAndCarry;
}
struct ForceCloseParameters {
uint ivGWAVPeriod;
uint skewGWAVPeriod;
uint shortVolShock;
uint shortPostCutoffVolShock;
uint longVolShock;
uint longPostCutoffVolShock;
uint liquidateVolShock;
uint liquidatePostCutoffVolShock;
uint shortSpotMin;
uint liquidateSpotMin;
}
struct MinCollateralParameters {
uint minStaticQuoteCollateral;
uint minStaticBaseCollateral;
uint shockVolA;
uint shockVolPointA;
uint shockVolB;
uint shockVolPointB;
uint callSpotPriceShock;
uint putSpotPriceShock;
}
struct GlobalCache {
uint minUpdatedAt;
uint minUpdatedAtPrice;
uint maxUpdatedAtPrice;
uint maxSkewVariance;
uint maxIvVariance;
NetGreeks netGreeks;
}
struct OptionBoardCache {
uint id;
uint[] strikes;
uint expiry;
uint iv;
NetGreeks netGreeks;
uint updatedAt;
uint updatedAtPrice;
uint maxSkewVariance;
uint ivVariance;
}
struct StrikeCache {
uint id;
uint boardId;
uint strikePrice;
uint skew;
StrikeGreeks greeks;
int callExposure;
int putExposure;
uint skewVariance;
}
struct StrikeGreeks {
int callDelta;
int putDelta;
uint stdVega;
uint callPrice;
uint putPrice;
}
struct NetGreeks {
int netDelta;
int netStdVega;
int netOptionValue;
}
struct TradePricing {
uint optionPrice;
int preTradeAmmNetStdVega;
int postTradeAmmNetStdVega;
int callDelta;
uint volTraded;
uint ivVariance;
uint vega;
}
struct BoardGreeksView {
NetGreeks boardGreeks;
uint ivGWAV;
StrikeGreeks[] strikeGreeks;
uint[] skewGWAVs;
}
function getPriceForForceClose(
IOptionMarket.TradeParameters memory trade,
IOptionMarket.Strike memory strike,
uint expiry,
uint newVol,
bool isPostCutoff
) external view returns (uint optionPrice, uint forceCloseVol);
function getMinCollateral(
IOptionMarket.OptionType optionType,
uint strikePrice,
uint expiry,
uint spotPrice,
uint amount
) external view returns (uint minCollateral);
function getShockVol(uint timeToMaturity) external view returns (uint);
function updateBoardCachedGreeks(uint boardId) external;
function isGlobalCacheStale(uint spotPrice) external view returns (bool);
function isBoardCacheStale(uint boardId) external view returns (bool);
function getGlobalNetDelta() external view returns (int);
function getGlobalOptionValue() external view returns (int);
function getBoardGreeksView(uint boardId) external view returns (BoardGreeksView memory);
function getStrikeCache(uint strikeId) external view returns (StrikeCache memory);
function getOptionBoardCache(uint boardId) external view returns (OptionBoardCache memory);
function getGlobalCache() external view returns (GlobalCache memory);
function getIvGWAV(uint boardId, uint secondsAgo) external view returns (uint ivGWAV);
function getSkewGWAV(uint strikeId, uint secondsAgo) external view returns (uint skewGWAV);
function getGreekCacheParams() external view returns (GreekCacheParameters memory);
function getForceCloseParams() external view returns (ForceCloseParameters memory);
function getMinCollatParams() external view returns (MinCollateralParameters memory);
event GreekCacheParametersSet(GreekCacheParameters params);
event ForceCloseParametersSet(ForceCloseParameters params);
event MinCollateralParametersSet(MinCollateralParameters params);
event StrikeCacheUpdated(StrikeCache strikeCache);
event BoardCacheUpdated(OptionBoardCache boardCache);
event GlobalCacheUpdated(GlobalCache globalCache);
event BoardCacheRemoved(uint boardId);
event StrikeCacheRemoved(uint strikeId);
event BoardIvUpdated(uint boardId, uint newIv, uint globalMaxIvVariance);
event StrikeSkewUpdated(uint strikeId, uint newSkew, uint globalMaxSkewVariance);
error InvalidGreekCacheParameters(address thrower, GreekCacheParameters greekCacheParams);
error InvalidForceCloseParameters(address thrower, ForceCloseParameters forceCloseParams);
error InvalidMinCollatParams(address thrower, MinCollateralParameters minCollatParams);
error BoardStrikeLimitExceeded(address thrower, uint boardId, uint newStrikesLength, uint maxStrikesPerBoard);
error InvalidBoardId(address thrower, uint boardId);
error CannotUpdateExpiredBoard(address thrower, uint boardId, uint expiry, uint currentTimestamp);
error OnlyIOptionMarket(address thrower, address caller, address optionMarket);
error OnlyIOptionMarketPricer(address thrower, address caller, address optionMarketPricer);
}
文件 24 的 40:IOptionMarket.sol
pragma solidity 0.8.9;
import "./ILiquidityPool.sol";
import "./ISynthetixAdapter.sol";
import "./IOptionMarketPricer.sol";
interface IOptionMarket {
enum TradeDirection {
OPEN,
CLOSE,
LIQUIDATE
}
enum OptionType {
LONG_CALL,
LONG_PUT,
SHORT_CALL_BASE,
SHORT_CALL_QUOTE,
SHORT_PUT_QUOTE
}
enum NonZeroValues {
BASE_IV,
SKEW,
STRIKE_PRICE,
ITERATIONS,
STRIKE_ID
}
struct Strike {
uint id;
uint strikePrice;
uint skew;
uint longCall;
uint shortCallBase;
uint shortCallQuote;
uint longPut;
uint shortPut;
uint boardId;
}
struct OptionBoard {
uint id;
uint expiry;
uint iv;
bool frozen;
uint[] strikeIds;
}
struct OptionMarketParameters {
uint maxBoardExpiry;
address securityModule;
uint feePortionReserved;
uint staticBaseSettlementFee;
}
struct TradeInputParameters {
uint strikeId;
uint positionId;
uint iterations;
OptionType optionType;
uint amount;
uint setCollateralTo;
uint minTotalCost;
uint maxTotalCost;
}
struct TradeParameters {
bool isBuy;
bool isForceClose;
TradeDirection tradeDirection;
OptionType optionType;
uint amount;
uint expiry;
uint strikePrice;
ILiquidityPool.Liquidity liquidity;
ISynthetixAdapter.ExchangeParams exchangeParams;
}
struct TradeEventData {
uint expiry;
uint strikePrice;
OptionType optionType;
TradeDirection tradeDirection;
uint amount;
uint setCollateralTo;
bool isForceClose;
uint spotPrice;
uint reservedFee;
uint totalCost;
}
struct LiquidationEventData {
address rewardBeneficiary;
address caller;
uint returnCollateral;
uint lpPremiums;
uint lpFee;
uint liquidatorFee;
uint smFee;
uint insolventAmount;
}
struct Result {
uint positionId;
uint totalCost;
uint totalFee;
}
function smClaim() external;
function getOptionMarketParams() external view returns (OptionMarketParameters memory);
function getLiveBoards() external view returns (uint[] memory _liveBoards);
function getNumLiveBoards() external view returns (uint numLiveBoards);
function getStrikeAndExpiry(uint strikeId) external view returns (uint strikePrice, uint expiry);
function getBoardStrikes(uint boardId) external view returns (uint[] memory strikeIds);
function getStrike(uint strikeId) external view returns (Strike memory);
function getOptionBoard(uint boardId) external view returns (OptionBoard memory);
function getStrikeAndBoard(uint strikeId) external view returns (Strike memory, OptionBoard memory);
function getBoardAndStrikeDetails(uint boardId)
external
view
returns (
OptionBoard memory,
Strike[] memory,
uint[] memory,
uint
);
function openPosition(TradeInputParameters memory params) external returns (Result memory result);
function closePosition(TradeInputParameters memory params) external returns (Result memory result);
function forceClosePosition(TradeInputParameters memory params) external returns (Result memory result);
function addCollateral(uint positionId, uint amountCollateral) external;
function liquidatePosition(uint positionId, address rewardBeneficiary) external;
function settleExpiredBoard(uint boardId) external;
function getSettlementParameters(uint strikeId)
external
view
returns (
uint strikePrice,
uint priceAtExpiry,
uint strikeToBaseReturned
);
event BoardCreated(uint indexed boardId, uint expiry, uint baseIv, bool frozen);
event BoardFrozen(uint indexed boardId, bool frozen);
event BoardBaseIvSet(uint indexed boardId, uint baseIv);
event StrikeSkewSet(uint indexed strikeId, uint skew);
event StrikeAdded(uint indexed boardId, uint indexed strikeId, uint strikePrice, uint skew);
event OptionMarketParamsSet(OptionMarketParameters optionMarketParams);
event SMClaimed(address securityModule, uint quoteAmount, uint baseAmount);
event Trade(
address indexed trader,
uint indexed strikeId,
uint indexed positionId,
TradeEventData trade,
IOptionMarketPricer.TradeResult[] tradeResults,
LiquidationEventData liquidation,
uint timestamp
);
event BoardSettled(
uint indexed boardId,
uint spotPriceAtExpiry,
uint totalUserLongProfitQuote,
uint totalBoardLongCallCollateral,
uint totalBoardLongPutCollateral,
uint totalAMMShortCallProfitBase,
uint totalAMMShortCallProfitQuote,
uint totalAMMShortPutProfitQuote
);
error ExpectedNonZeroValue(address thrower, NonZeroValues valueType);
error InvalidOptionMarketParams(address thrower, OptionMarketParameters optionMarketParams);
error InvalidBoardId(address thrower, uint boardId);
error InvalidExpiryTimestamp(address thrower, uint currentTime, uint expiry, uint maxBoardExpiry);
error BoardNotFrozen(address thrower, uint boardId);
error BoardAlreadySettled(address thrower, uint boardId);
error BoardNotExpired(address thrower, uint boardId);
error InvalidStrikeId(address thrower, uint strikeId);
error StrikeSkewLengthMismatch(address thrower, uint strikesLength, uint skewsLength);
error TotalCostOutsideOfSpecifiedBounds(address thrower, uint totalCost, uint minCost, uint maxCost);
error BoardIsFrozen(address thrower, uint boardId);
error BoardExpired(address thrower, uint boardId, uint boardExpiry, uint currentTime);
error TradeIterationsHasRemainder(
address thrower,
uint iterations,
uint expectedAmount,
uint tradeAmount,
uint totalAmount
);
error OnlySecurityModule(address thrower, address caller, address securityModule);
error BaseTransferFailed(address thrower, address from, address to, uint amount);
error QuoteTransferFailed(address thrower, address from, address to, uint amount);
}
文件 25 的 40:IOptionMarketPricer.sol
pragma solidity 0.8.9;
import "./IOptionMarket.sol";
import "./IOptionGreekCache.sol";
interface IOptionMarketPricer {
struct PricingParameters {
uint optionPriceFeeCoefficient;
uint optionPriceFee1xPoint;
uint optionPriceFee2xPoint;
uint spotPriceFeeCoefficient;
uint spotPriceFee1xPoint;
uint spotPriceFee2xPoint;
uint vegaFeeCoefficient;
uint standardSize;
uint skewAdjustmentFactor;
}
struct TradeLimitParameters {
int minDelta;
int minForceCloseDelta;
uint tradingCutoff;
uint minBaseIV;
uint maxBaseIV;
uint minSkew;
uint maxSkew;
uint minVol;
uint maxVol;
uint absMinSkew;
uint absMaxSkew;
bool capSkewsToAbs;
}
struct VarianceFeeParameters {
uint defaultVarianceFeeCoefficient;
uint forceCloseVarianceFeeCoefficient;
uint skewAdjustmentCoefficient;
uint referenceSkew;
uint minimumStaticSkewAdjustment;
uint vegaCoefficient;
uint minimumStaticVega;
uint ivVarianceCoefficient;
uint minimumStaticIvVariance;
}
struct TradeResult {
uint amount;
uint premium;
uint optionPriceFee;
uint spotPriceFee;
VegaUtilFeeComponents vegaUtilFee;
VarianceFeeComponents varianceFee;
uint totalFee;
uint totalCost;
uint volTraded;
uint newBaseIv;
uint newSkew;
}
struct VegaUtilFeeComponents {
int preTradeAmmNetStdVega;
int postTradeAmmNetStdVega;
uint vegaUtil;
uint volTraded;
uint NAV;
uint vegaUtilFee;
}
struct VarianceFeeComponents {
uint varianceFeeCoefficient;
uint vega;
uint vegaCoefficient;
uint skew;
uint skewCoefficient;
uint ivVariance;
uint ivVarianceCoefficient;
uint varianceFee;
}
struct VolComponents {
uint vol;
uint baseIv;
uint skew;
}
function pricingParams() external view returns (PricingParameters memory);
function tradeLimitParams() external view returns (TradeLimitParameters memory);
function varianceFeeParams() external view returns (VarianceFeeParameters memory);
function ivImpactForTrade(
IOptionMarket.TradeParameters memory trade,
uint boardBaseIv,
uint strikeSkew
) external view returns (uint newBaseIv, uint newSkew);
function getTradeResult(
IOptionMarket.TradeParameters memory trade,
IOptionGreekCache.TradePricing memory pricing,
uint newBaseIv,
uint newSkew
) external view returns (TradeResult memory tradeResult);
function getTimeWeightedFee(
uint expiry,
uint pointA,
uint pointB,
uint coefficient
) external view returns (uint timeWeightedFee);
function getVegaUtilFee(IOptionMarket.TradeParameters memory trade, IOptionGreekCache.TradePricing memory pricing)
external
view
returns (VegaUtilFeeComponents memory vegaUtilFeeComponents);
function getVarianceFee(
IOptionMarket.TradeParameters memory trade,
IOptionGreekCache.TradePricing memory pricing,
uint skew
) external view returns (VarianceFeeComponents memory varianceFeeComponents);
function getPricingParams() external view returns (PricingParameters memory pricingParameters);
function getTradeLimitParams() external view returns (TradeLimitParameters memory tradeLimitParameters);
function getVarianceFeeParams() external view returns (VarianceFeeParameters memory varianceFeeParameters);
event PricingParametersSet(PricingParameters pricingParams);
event TradeLimitParametersSet(TradeLimitParameters tradeLimitParams);
event VarianceFeeParametersSet(VarianceFeeParameters varianceFeeParams);
error InvalidTradeLimitParameters(address thrower, TradeLimitParameters tradeLimitParams);
error InvalidPricingParameters(address thrower, PricingParameters pricingParams);
error TradingCutoffReached(address thrower, uint tradingCutoff, uint boardExpiry, uint currentTime);
error ForceCloseSkewOutOfRange(address thrower, bool isBuy, uint newSkew, uint minSkew, uint maxSkew);
error VolSkewOrBaseIvOutsideOfTradingBounds(
address thrower,
bool isBuy,
VolComponents currentVol,
VolComponents newVol,
VolComponents tradeBounds
);
error TradeDeltaOutOfRange(address thrower, int strikeCallDelta, int minDelta, int maxDelta);
error ForceCloseDeltaOutOfRange(address thrower, int strikeCallDelta, int minDelta, int maxDelta);
error OnlyOptionMarket(address thrower, address caller, address optionMarket);
}
文件 26 的 40:IOptionToken.sol
pragma solidity 0.8.9;
import "./IOptionMarket.sol";
import "./ISynthetixAdapter.sol";
import "./IOptionGreekCache.sol";
import "openzeppelin-contracts-4.4.1/token/ERC721/IERC721.sol";
interface IOptionToken is IERC721 {
enum PositionState {
EMPTY,
ACTIVE,
CLOSED,
LIQUIDATED,
SETTLED,
MERGED
}
enum PositionUpdatedType {
OPENED,
ADJUSTED,
CLOSED,
SPLIT_FROM,
SPLIT_INTO,
MERGED,
MERGED_INTO,
SETTLED,
LIQUIDATED,
TRANSFER
}
struct OptionPosition {
uint positionId;
uint strikeId;
IOptionMarket.OptionType optionType;
uint amount;
uint collateral;
PositionState state;
}
struct PartialCollateralParameters {
uint penaltyRatio;
uint liquidatorFeeRatio;
uint smFeeRatio;
uint minLiquidationFee;
}
struct PositionWithOwner {
uint positionId;
uint strikeId;
IOptionMarket.OptionType optionType;
uint amount;
uint collateral;
PositionState state;
address owner;
}
struct LiquidationFees {
uint returnCollateral;
uint lpPremiums;
uint lpFee;
uint liquidatorFee;
uint smFee;
uint insolventAmount;
}
function positions(uint positionId) external view returns (OptionPosition memory);
function nextId() external view returns (uint);
function partialCollatParams() external view returns (PartialCollateralParameters memory);
function baseURI() external view returns (string memory);
function canLiquidate(
OptionPosition memory position,
uint expiry,
uint strikePrice,
uint spotPrice
) external view returns (bool);
function getLiquidationFees(
uint gwavPremium,
uint userPositionCollateral,
uint convertedMinLiquidationFee,
uint insolvencyMultiplier
) external view returns (LiquidationFees memory liquidationFees);
function split(
uint positionId,
uint newAmount,
uint newCollateral,
address recipient
) external returns (uint newPositionId);
function merge(uint[] memory positionIds) external;
function getPositionState(uint positionId) external view returns (PositionState);
function getOptionPosition(uint positionId) external view returns (OptionPosition memory);
function getOptionPositions(uint[] memory positionIds) external view returns (OptionPosition[] memory);
function getPositionWithOwner(uint positionId) external view returns (PositionWithOwner memory);
function getPositionsWithOwner(uint[] memory positionIds) external view returns (PositionWithOwner[] memory);
function getOwnerPositions(address target) external view returns (OptionPosition[] memory);
function getPartialCollatParams() external view returns (PartialCollateralParameters memory);
event URISet(string URI);
event PartialCollateralParamsSet(PartialCollateralParameters partialCollateralParams);
event PositionUpdated(
uint indexed positionId,
address indexed owner,
PositionUpdatedType indexed updatedType,
OptionPosition position,
uint timestamp
);
error InvalidPartialCollateralParameters(address thrower, PartialCollateralParameters partialCollatParams);
error AdjustmentResultsInMinimumCollateralNotBeingMet(address thrower, OptionPosition position, uint spotPrice);
error CannotClosePositionZero(address thrower);
error CannotOpenZeroAmount(address thrower);
error CannotAdjustInvalidPosition(
address thrower,
uint positionId,
bool invalidPositionId,
bool positionInactive,
bool strikeMismatch,
bool optionTypeMismatch
);
error OnlyOwnerCanAdjustPosition(address thrower, uint positionId, address trader, address owner);
error FullyClosingWithNonZeroSetCollateral(address thrower, uint positionId, uint setCollateralTo);
error AddingCollateralToInvalidPosition(
address thrower,
uint positionId,
bool invalidPositionId,
bool positionInactive,
bool isShort
);
error PositionNotLiquidatable(address thrower, OptionPosition position, uint spotPrice);
error SplittingUnapprovedPosition(address thrower, address caller, uint positionId);
error InvalidSplitAmount(address thrower, uint originalPositionAmount, uint splitAmount);
error ResultingOriginalPositionLiquidatable(address thrower, OptionPosition position, uint spotPrice);
error ResultingNewPositionLiquidatable(address thrower, OptionPosition position, uint spotPrice);
error MustMergeTwoOrMorePositions(address thrower);
error MergingUnapprovedPosition(address thrower, address caller, uint positionId);
error PositionMismatchWhenMerging(
address thrower,
OptionPosition firstPosition,
OptionPosition nextPosition,
bool ownerMismatch,
bool strikeMismatch,
bool optionTypeMismatch,
bool duplicatePositionId
);
error StrikeIsSettled(address thrower, uint strikeId);
error OnlyOptionMarket(address thrower, address caller, address optionMarket);
error OnlyShortCollateral(address thrower, address caller, address shortCollateral);
}
文件 27 的 40:IPositionHandler.sol
pragma solidity ^0.8.4;
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import {LyraAdapter} from "@lyrafinance/protocol/contracts/periphery/LyraAdapter.sol";
interface IPositionHandler {
function wantTokenL2() external view returns (address);
function positionInWantToken() external view returns (uint256, uint256);
function openPosition(
uint256 listingId,
bool isCall,
uint256 amount,
bool updateExistingPosition
) external returns (LyraAdapter.TradeResult memory);
function closePosition(bool toSettle) external;
function deposit() external;
function withdraw(
uint256 amountOut,
address allowanceTarget,
address socketRegistry,
bytes calldata socketData
) external;
function sweep(address _token) external;
function isCurrentPositionActive() external view returns (bool);
}
文件 28 的 40:IShortCollateral.sol
pragma solidity 0.8.9;
import "./IOptionMarket.sol";
import "./IOptionToken.sol";
interface IShortCollateral {
function LPBaseExcess() external view returns (uint);
function LPQuoteExcess() external view returns (uint);
function settleOptions(uint[] memory positionIds) external;
event BoardSettlementCollateralSent(
uint amountBaseSent,
uint amountQuoteSent,
uint lpBaseInsolvency,
uint lpQuoteInsolvency,
uint LPBaseExcess,
uint LPQuoteExcess
);
event PositionSettled(
uint indexed positionId,
address indexed settler,
address indexed optionOwner,
uint strikePrice,
uint priceAtExpiry,
IOptionMarket.OptionType optionType,
uint amount,
uint settlementAmount,
uint insolventAmount
);
event QuoteSent(address indexed receiver, uint amount);
event BaseSent(address indexed receiver, uint amount);
event BaseExchangedAndQuoteSent(address indexed recipient, uint amountBase, uint quoteReceived);
error OutOfQuoteCollateralForTransfer(address thrower, uint balance, uint amount);
error OutOfBaseCollateralForTransfer(address thrower, uint balance, uint amount);
error OutOfBaseCollateralForExchangeAndTransfer(address thrower, uint balance, uint amount);
error BaseTransferFailed(address thrower, address from, address to, uint amount);
error QuoteTransferFailed(address thrower, address from, address to, uint amount);
error BoardMustBeSettled(address thrower, IOptionToken.PositionWithOwner position);
error OnlyOptionMarket(address thrower, address caller, address optionMarket);
}
文件 29 的 40:ISynthetix.sol
pragma solidity ^0.8.9;
interface ISynthetix {
function exchange(
bytes32 sourceCurrencyKey,
uint sourceAmount,
bytes32 destinationCurrencyKey
) external returns (uint amountReceived);
function exchangeOnBehalfWithTracking(
address exchangeForAddress,
bytes32 sourceCurrencyKey,
uint sourceAmount,
bytes32 destinationCurrencyKey,
address rewardAddress,
bytes32 trackingCode
) external returns (uint amountReceived);
}
文件 30 的 40:ISynthetixAdapter.sol
pragma solidity 0.8.9;
import "./IAddressResolver.sol";
import "./ISynthetix.sol";
import "./IExchanger.sol";
import "./IExchangeRates.sol";
import "./IDelegateApprovals.sol";
interface ISynthetixAdapter {
struct ExchangeParams {
uint spotPrice;
bytes32 quoteKey;
bytes32 baseKey;
uint quoteBaseFeeRate;
uint baseQuoteFeeRate;
}
function isMarketPaused(address market) external view returns (bool);
function isGlobalPaused() external view returns (bool);
function addressResolver() external view returns (address);
function synthetix() external view returns (address);
function exchanger() external view returns (address);
function exchangeRates() external view returns (address);
function delegateApprovals() external view returns (address);
function quoteKey(address market) external view returns (bytes32);
function baseKey(address market) external view returns (bytes32);
function rewardAddress(address market) external view returns (bytes32);
function trackingCode(address market) external view returns (bytes32);
function updateSynthetixAddresses() external;
function getSpotPriceForMarket(address _contractAddress)
external
view
returns (uint spotPrice);
function getSpotPrice(bytes32 to) external view returns (uint);
function getExchangeParams(address optionMarket)
external
view
returns (ExchangeParams memory exchangeParams);
function requireNotGlobalPaused(address optionMarket) external view;
function exchangeFromExactQuote(address optionMarket, uint amountQuote) external returns (uint baseReceived);
function exchangeToExactBase(
ExchangeParams memory exchangeParams,
address optionMarket,
uint amountBase
) external returns (uint quoteSpent, uint baseReceived);
function exchangeToExactBaseWithLimit(
ExchangeParams memory exchangeParams,
address optionMarket,
uint amountBase,
uint quoteLimit
) external returns (uint quoteSpent, uint baseReceived);
function estimateExchangeToExactBase(ExchangeParams memory exchangeParams, uint amountBase)
external
pure
returns (uint quoteNeeded);
function exchangeFromExactBase(address optionMarket, uint amountBase) external returns (uint quoteReceived);
function exchangeToExactQuote(
ExchangeParams memory exchangeParams,
address optionMarket,
uint amountQuote
) external returns (uint baseSpent, uint quoteReceived);
function exchangeToExactQuoteWithLimit(
ExchangeParams memory exchangeParams,
address optionMarket,
uint amountQuote,
uint baseLimit
) external returns (uint baseSpent, uint quoteReceived);
function estimateExchangeToExactQuote(ExchangeParams memory exchangeParams, uint amountQuote)
external
pure
returns (uint baseNeeded);
event AddressResolverSet(IAddressResolver addressResolver);
event SynthetixAddressesUpdated(
ISynthetix synthetix,
IExchanger exchanger,
IExchangeRates exchangeRates,
IDelegateApprovals delegateApprovals
);
event GlobalsSetForContract(
address indexed market,
bytes32 quoteKey,
bytes32 baseKey,
address rewardAddress,
bytes32 trackingCode
);
event GlobalPausedSet(bool isPaused);
event MarketPausedSet(address contractAddress, bool isPaused);
event BaseSwappedForQuote(
address indexed marketAddress,
address indexed exchanger,
uint baseSwapped,
uint quoteReceived
);
event QuoteSwappedForBase(
address indexed marketAddress,
address indexed exchanger,
uint quoteSwapped,
uint baseReceived
);
error InvalidRewardAddress(address thrower, address rewardAddress);
error AllMarketsPaused(address thrower, address marketAddress);
error MarketIsPaused(address thrower, address marketAddress);
error ReceivedZeroFromExchange(
address thrower,
bytes32 fromKey,
bytes32 toKey,
uint amountSwapped,
uint amountReceived
);
error QuoteBaseExchangeExceedsLimit(
address thrower,
uint amountBaseRequested,
uint quoteToSpend,
uint quoteLimit,
uint spotPrice,
bytes32 quoteKey,
bytes32 baseKey
);
error BaseQuoteExchangeExceedsLimit(
address thrower,
uint amountQuoteRequested,
uint baseToSpend,
uint baseLimit,
uint spotPrice,
bytes32 baseKey,
bytes32 quoteKey
);
error RateIsInvalid(address thrower, uint spotPrice, bool invalid);
}
文件 31 的 40:ITradeExecutor.sol
pragma solidity ^0.8.4;
interface ITradeExecutor {
struct ActionStatus {
bool inProcess;
address from;
}
function vault() external view returns (address);
function depositStatus() external returns (bool, address);
function withdrawalStatus() external returns (bool, address);
function initiateDeposit(bytes calldata _data) external;
function confirmDeposit() external;
function initiateWithdraw(bytes calldata _data) external;
function confirmWithdraw() external;
function totalFunds()
external
view
returns (uint256 posValue, uint256 lastUpdatedBlock);
}
文件 32 的 40:IVault.sol
pragma solidity ^0.8.0;
interface IVault {
function keeper() external view returns (address);
function governance() external view returns (address);
function wantToken() external view returns (address);
function deposit(uint256 amountIn, address receiver)
external
returns (uint256 shares);
function withdraw(uint256 sharesIn, address receiver)
external
returns (uint256 amountOut);
}
文件 33 的 40:LyraAdapter.sol
pragma solidity 0.8.9;
import "../libraries/GWAV.sol";
import "../libraries/BlackScholes.sol";
import "../synthetix/DecimalMath.sol";
import "openzeppelin-contracts-4.4.1/access/Ownable.sol";
import "openzeppelin-contracts-4.4.1/token/ERC20/IERC20.sol";
import "../interfaces/IOptionToken.sol";
import "../interfaces/IOptionMarket.sol";
import "../interfaces/ILiquidityPool.sol";
import "../interfaces/IShortCollateral.sol";
import "../interfaces/IOptionGreekCache.sol";
import "../interfaces/ISynthetixAdapter.sol";
import "../interfaces/IDelegateApprovals.sol";
import "../interfaces/ICurve.sol";
import "../interfaces/IGWAVOracle.sol";
import "../interfaces/ILyraRegistry.sol";
import "./BasicFeeCounter.sol";
contract LyraAdapter is Ownable {
using DecimalMath for uint;
struct Strike {
uint id;
uint expiry;
uint strikePrice;
uint skew;
uint boardIv;
}
struct Board {
uint id;
uint expiry;
uint boardIv;
uint[] strikeIds;
}
struct OptionPosition {
uint positionId;
uint strikeId;
OptionType optionType;
uint amount;
uint collateral;
PositionState state;
}
enum OptionType {
LONG_CALL,
LONG_PUT,
SHORT_CALL_BASE,
SHORT_CALL_QUOTE,
SHORT_PUT_QUOTE
}
enum PositionState {
EMPTY,
ACTIVE,
CLOSED,
LIQUIDATED,
SETTLED,
MERGED
}
struct TradeInputParameters {
uint strikeId;
uint positionId;
uint iterations;
OptionType optionType;
uint amount;
uint setCollateralTo;
uint minTotalCost;
uint maxTotalCost;
address rewardRecipient;
}
struct TradeResult {
uint positionId;
uint totalCost;
uint totalFee;
}
struct Liquidity {
uint freeLiquidity;
uint burnableLiquidity;
uint usedCollatLiquidity;
uint pendingDeltaLiquidity;
uint usedDeltaLiquidity;
uint NAV;
}
struct MarketParams {
uint standardSize;
uint skewAdjustmentParam;
int rateAndCarry;
int deltaCutOff;
uint tradingCutoff;
int minForceCloseDelta;
}
struct ExchangeRateParams {
uint spotPrice;
uint quoteBaseFeeRate;
uint baseQuoteFeeRate;
}
ILyraRegistry public lyraRegistry;
ISynthetixAdapter internal synthetixAdapter;
IOptionMarket public optionMarket;
IOptionToken public optionToken;
ILiquidityPool public liquidityPool;
IShortCollateral public shortCollateral;
IGWAVOracle public gwavOracle;
IOptionMarketPricer public optionPricer;
IOptionGreekCache public greekCache;
IERC20 public quoteAsset;
IERC20 public baseAsset;
ICurve public curveSwap;
BasicFeeCounter public feeCounter;
bytes32 private constant SNX_ADAPTER = "SYNTHETIX_ADAPTER";
constructor() Ownable() {}
function setLyraAddresses(
address _lyraRegistry,
address _optionMarket,
address _curveSwap,
address _feeCounter
) public onlyOwner {
if (address(quoteAsset) != address(0)) {
quoteAsset.approve(address(optionMarket), 0);
}
if (address(baseAsset) != address(0)) {
baseAsset.approve(address(optionMarket), 0);
}
optionMarket = IOptionMarket(_optionMarket);
lyraRegistry = ILyraRegistry(_lyraRegistry);
synthetixAdapter = ISynthetixAdapter(lyraRegistry.getGlobalAddress(SNX_ADAPTER));
_assignLyraRegistryMarketAddresses();
curveSwap = ICurve(_curveSwap);
feeCounter = BasicFeeCounter(_feeCounter);
IDelegateApprovals(synthetixAdapter.delegateApprovals()).approveExchangeOnBehalf(address(synthetixAdapter));
quoteAsset.approve(address(optionMarket), type(uint).max);
baseAsset.approve(address(optionMarket), type(uint).max);
}
function updateDelegateApproval() external onlyOwner {
IDelegateApprovals(synthetixAdapter.delegateApprovals()).approveExchangeOnBehalf(address(synthetixAdapter));
}
function _openPosition(TradeInputParameters memory params) internal returns (TradeResult memory tradeResult) {
IOptionMarket.Result memory result = optionMarket.openPosition(_convertParams(params));
if (params.rewardRecipient != address(0)) {
feeCounter.trackFee(
address(optionMarket),
params.rewardRecipient,
_convertParams(params).amount,
result.totalCost,
result.totalFee
);
}
return TradeResult({positionId: result.positionId, totalCost: result.totalCost, totalFee: result.totalFee});
}
function _closeOrForceClosePosition(TradeInputParameters memory params)
internal
returns (TradeResult memory tradeResult)
{
if (!_isOutsideDeltaCutoff(params.strikeId) && !_isWithinTradingCutoff(params.strikeId)) {
return _closePosition(params);
} else {
return _forceClosePosition(params);
}
}
function _closePosition(TradeInputParameters memory params) internal returns (TradeResult memory tradeResult) {
IOptionMarket.Result memory result = optionMarket.closePosition(_convertParams(params));
if (params.rewardRecipient != address(0)) {
feeCounter.trackFee(
address(optionMarket),
params.rewardRecipient,
_convertParams(params).amount,
result.totalCost,
result.totalFee
);
}
return TradeResult({positionId: result.positionId, totalCost: result.totalCost, totalFee: result.totalFee});
}
function _forceClosePosition(TradeInputParameters memory params) internal returns (TradeResult memory tradeResult) {
IOptionMarket.Result memory result = optionMarket.forceClosePosition(_convertParams(params));
if (params.rewardRecipient != address(0)) {
feeCounter.trackFee(
address(optionMarket),
params.rewardRecipient,
_convertParams(params).amount,
result.totalCost,
result.totalFee
);
}
return TradeResult({positionId: result.positionId, totalCost: result.totalCost, totalFee: result.totalFee});
}
function _exchangeFromExactQuote(uint amountQuote, uint minBaseReceived) internal returns (uint baseReceived) {
baseReceived = synthetixAdapter.exchangeFromExactQuote(address(optionMarket), amountQuote);
if (baseReceived < minBaseReceived) {
revert ExchangerBaseReceivedTooLow(address(this), minBaseReceived, baseReceived);
}
}
function _exchangeToExactQuote(uint amountQuote, uint maxBaseUsed) internal returns (uint quoteReceived) {
ISynthetixAdapter.ExchangeParams memory exchangeParams = synthetixAdapter.getExchangeParams(address(optionMarket));
(, quoteReceived) = synthetixAdapter.exchangeToExactQuoteWithLimit(
exchangeParams,
address(optionMarket),
amountQuote,
maxBaseUsed
);
}
function _exchangeFromExactBase(uint amountBase, uint minQuoteReceived) internal returns (uint quoteReceived) {
quoteReceived = synthetixAdapter.exchangeFromExactBase(address(optionMarket), amountBase);
if (quoteReceived < minQuoteReceived) {
revert ExchangerQuoteReceivedTooLow(address(this), minQuoteReceived, quoteReceived);
}
}
function _exchangeToExactBase(uint amountBase, uint maxQuoteUsed) internal returns (uint baseReceived) {
ISynthetixAdapter.ExchangeParams memory exchangeParams = synthetixAdapter.getExchangeParams(address(optionMarket));
(, baseReceived) = synthetixAdapter.exchangeToExactBaseWithLimit(
exchangeParams,
address(optionMarket),
amountBase,
maxQuoteUsed
);
}
function _getExchangeParams() internal view returns (ExchangeRateParams memory) {
ISynthetixAdapter.ExchangeParams memory params = synthetixAdapter.getExchangeParams(address(optionMarket));
return
ExchangeRateParams({
spotPrice: params.spotPrice,
quoteBaseFeeRate: params.quoteBaseFeeRate,
baseQuoteFeeRate: params.baseQuoteFeeRate
});
}
function _swapStables(
address from,
address to,
uint amount,
uint expected,
address receiver
) internal returns (uint amountOut) {
amountOut = curveSwap.exchange_with_best_rate(from, to, amount, expected, receiver);
}
function _getPositions(uint[] memory positionIds) internal view returns (OptionPosition[] memory) {
IOptionToken.OptionPosition[] memory positions = optionToken.getOptionPositions(positionIds);
uint positionsLen = positions.length;
OptionPosition[] memory convertedPositions = new OptionPosition[](positionsLen);
for (uint i = 0; i < positionsLen; ++i) {
convertedPositions[i] = OptionPosition({
positionId: positions[i].positionId,
strikeId: positions[i].strikeId,
optionType: OptionType(uint(positions[i].optionType)),
amount: positions[i].amount,
collateral: positions[i].collateral,
state: PositionState(uint(positions[i].state))
});
}
return convertedPositions;
}
function _splitPosition(
uint positionId,
uint newAmount,
uint newCollateral,
address recipient
) internal returns (uint newPositionId) {
newPositionId = optionToken.split(positionId, newAmount, newCollateral, recipient);
}
function _mergePositions(uint[] memory positionIds) internal {
optionToken.merge(positionIds);
}
function _getLiveBoards() internal view returns (uint[] memory liveBoards) {
liveBoards = optionMarket.getLiveBoards();
}
function _getBoard(uint boardId) internal view returns (Board memory) {
IOptionMarket.OptionBoard memory board = optionMarket.getOptionBoard(boardId);
return Board({id: board.id, expiry: board.expiry, boardIv: board.iv, strikeIds: board.strikeIds});
}
function _getStrikes(uint[] memory strikeIds) internal view returns (Strike[] memory allStrikes) {
uint strikesLen = strikeIds.length;
allStrikes = new Strike[](strikesLen);
for (uint i = 0; i < strikesLen; ++i) {
(IOptionMarket.Strike memory strike, IOptionMarket.OptionBoard memory board) = optionMarket.getStrikeAndBoard(
strikeIds[i]
);
allStrikes[i] = Strike({
id: strike.id,
expiry: board.expiry,
strikePrice: strike.strikePrice,
skew: strike.skew,
boardIv: board.iv
});
}
return allStrikes;
}
function _getVols(uint[] memory strikeIds) internal view returns (uint[] memory vols) {
uint strikesLen = strikeIds.length;
vols = new uint[](strikesLen);
for (uint i = 0; i < strikesLen; ++i) {
(IOptionMarket.Strike memory strike, IOptionMarket.OptionBoard memory board) = optionMarket.getStrikeAndBoard(
strikeIds[i]
);
vols[i] = board.iv.multiplyDecimal(strike.skew);
}
return vols;
}
function _getDeltas(uint[] memory strikeIds) internal view returns (int[] memory callDeltas) {
uint strikesLen = strikeIds.length;
callDeltas = new int[](strikesLen);
for (uint i = 0; i < strikesLen; ++i) {
BlackScholes.BlackScholesInputs memory bsInput = _getBsInput(strikeIds[i]);
(callDeltas[i], ) = BlackScholes.delta(bsInput);
}
}
function _getVegas(uint[] memory strikeIds) internal view returns (uint[] memory vegas) {
uint strikesLen = strikeIds.length;
vegas = new uint[](strikesLen);
for (uint i = 0; i < strikesLen; ++i) {
BlackScholes.BlackScholesInputs memory bsInput = _getBsInput(strikeIds[i]);
vegas[i] = BlackScholes.vega(bsInput);
}
}
function _getPurePremium(
uint secondsToExpiry,
uint vol,
uint spotPrice,
uint strikePrice
) internal view returns (uint call, uint put) {
BlackScholes.BlackScholesInputs memory bsInput = BlackScholes.BlackScholesInputs({
timeToExpirySec: secondsToExpiry,
volatilityDecimal: vol,
spotDecimal: spotPrice,
strikePriceDecimal: strikePrice,
rateDecimal: greekCache.getGreekCacheParams().rateAndCarry
});
(call, put) = BlackScholes.optionPrices(bsInput);
}
function _getPurePremiumForStrike(uint strikeId) internal view returns (uint call, uint put) {
BlackScholes.BlackScholesInputs memory bsInput = _getBsInput(strikeId);
(call, put) = BlackScholes.optionPrices(bsInput);
}
function _getLiquidity() internal view returns (Liquidity memory) {
ILiquidityPool.Liquidity memory liquidity = liquidityPool.getCurrentLiquidity();
return
Liquidity({
freeLiquidity: liquidity.freeLiquidity,
burnableLiquidity: liquidity.burnableLiquidity,
usedCollatLiquidity: liquidity.usedCollatLiquidity,
pendingDeltaLiquidity: liquidity.pendingDeltaLiquidity,
usedDeltaLiquidity: liquidity.usedDeltaLiquidity,
NAV: liquidity.NAV
});
}
function _getFreeLiquidity() internal view returns (uint freeLiquidity) {
freeLiquidity = liquidityPool.getCurrentLiquidity().freeLiquidity;
}
function _getMarketParams() internal view returns (MarketParams memory) {
IOptionMarketPricer.PricingParameters memory pricingParams = optionPricer.getPricingParams();
IOptionMarketPricer.TradeLimitParameters memory tradeLimitParams = optionPricer.getTradeLimitParams();
return
MarketParams({
standardSize: pricingParams.standardSize,
skewAdjustmentParam: pricingParams.skewAdjustmentFactor,
rateAndCarry: greekCache.getGreekCacheParams().rateAndCarry,
deltaCutOff: tradeLimitParams.minDelta,
tradingCutoff: tradeLimitParams.tradingCutoff,
minForceCloseDelta: tradeLimitParams.minForceCloseDelta
});
}
function _isOutsideDeltaCutoff(uint strikeId) internal view returns (bool) {
MarketParams memory marketParams = _getMarketParams();
uint[] memory dynamicArray = new uint[](1);
dynamicArray[0] = strikeId;
int callDelta = _getDeltas(dynamicArray)[0];
return callDelta > (int(DecimalMath.UNIT) - marketParams.deltaCutOff) || callDelta < marketParams.deltaCutOff;
}
function _isWithinTradingCutoff(uint strikeId) internal view returns (bool) {
MarketParams memory marketParams = _getMarketParams();
uint[] memory dynamicArray = new uint[](1);
dynamicArray[0] = strikeId;
Strike memory strike = _getStrikes(dynamicArray)[0];
return strike.expiry - block.timestamp <= marketParams.tradingCutoff;
}
function _getMinCollateral(
OptionType optionType,
uint strikePrice,
uint expiry,
uint spotPrice,
uint amount
) internal view returns (uint) {
return
greekCache.getMinCollateral(IOptionMarket.OptionType(uint(optionType)), strikePrice, expiry, spotPrice, amount);
}
function _getMinCollateralForPosition(uint positionId) internal view returns (uint) {
IOptionToken.PositionWithOwner memory position = optionToken.getPositionWithOwner(positionId);
if (_isLong(OptionType(uint(position.optionType)))) return 0;
uint strikePrice;
uint expiry;
(strikePrice, expiry) = optionMarket.getStrikeAndExpiry(position.strikeId);
return
_getMinCollateral(
OptionType(uint(position.optionType)),
strikePrice,
expiry,
synthetixAdapter.getSpotPriceForMarket(address(optionMarket)),
position.amount
);
}
function _getMinCollateralForStrike(
OptionType optionType,
uint strikeId,
uint amount
) internal view returns (uint) {
if (_isLong(optionType)) return 0;
uint strikePrice;
uint expiry;
(strikePrice, expiry) = optionMarket.getStrikeAndExpiry(strikeId);
return
_getMinCollateral(
optionType,
strikePrice,
expiry,
synthetixAdapter.getSpotPriceForMarket(address(optionMarket)),
amount
);
}
function _ivGWAV(uint boardId, uint secondsAgo) internal view returns (uint) {
return gwavOracle.ivGWAV(boardId, secondsAgo);
}
function _skewGWAV(uint strikeId, uint secondsAgo) internal view returns (uint) {
return gwavOracle.skewGWAV(strikeId, secondsAgo);
}
function _volGWAV(uint strikeId, uint secondsAgo) internal view returns (uint) {
return gwavOracle.volGWAV(strikeId, secondsAgo);
}
function _deltaGWAV(uint strikeId, uint secondsAgo) internal view returns (int callDelta) {
return gwavOracle.deltaGWAV(strikeId, secondsAgo);
}
function _vegaGWAV(uint strikeId, uint secondsAgo) internal view returns (uint) {
return gwavOracle.vegaGWAV(strikeId, secondsAgo);
}
function _optionPriceGWAV(uint strikeId, uint secondsAgo) internal view returns (uint callPrice, uint putPrice) {
return gwavOracle.optionPriceGWAV(strikeId, secondsAgo);
}
function _getBsInput(uint strikeId) internal view returns (BlackScholes.BlackScholesInputs memory bsInput) {
(IOptionMarket.Strike memory strike, IOptionMarket.OptionBoard memory board) = optionMarket.getStrikeAndBoard(
strikeId
);
bsInput = BlackScholes.BlackScholesInputs({
timeToExpirySec: board.expiry - block.timestamp,
volatilityDecimal: board.iv.multiplyDecimal(strike.skew),
spotDecimal: synthetixAdapter.getSpotPriceForMarket(address(optionMarket)),
strikePriceDecimal: strike.strikePrice,
rateDecimal: greekCache.getGreekCacheParams().rateAndCarry
});
}
function _isLong(OptionType optionType) internal pure returns (bool) {
return (optionType < OptionType.SHORT_CALL_BASE);
}
function _convertParams(TradeInputParameters memory _params)
internal
pure
returns (IOptionMarket.TradeInputParameters memory)
{
return
IOptionMarket.TradeInputParameters({
strikeId: _params.strikeId,
positionId: _params.positionId,
iterations: _params.iterations,
optionType: IOptionMarket.OptionType(uint(_params.optionType)),
amount: _params.amount,
setCollateralTo: _params.setCollateralTo,
minTotalCost: _params.minTotalCost,
maxTotalCost: _params.maxTotalCost
});
}
function _assignLyraRegistryMarketAddresses() internal {
ILyraRegistry.OptionMarketAddresses memory addresses = lyraRegistry.getMarketAddresses(address(optionMarket));
liquidityPool = ILiquidityPool(addresses.liquidityPool);
greekCache = IOptionGreekCache(addresses.greekCache);
optionPricer = IOptionMarketPricer(addresses.optionMarketPricer);
optionToken = IOptionToken(addresses.optionToken);
shortCollateral = IShortCollateral(addresses.shortCollateral);
gwavOracle = IGWAVOracle(addresses.gwavOracle);
quoteAsset = addresses.quoteAsset;
baseAsset = addresses.baseAsset;
}
error ExchangerBaseReceivedTooLow(address thrower, uint baseExpected, uint baseReceived);
error ExchangerQuoteReceivedTooLow(address thrower, uint quoteExpected, uint quoteReceived);
}
文件 34 的 40:LyraPositionHandler.sol
pragma solidity ^0.8.4;
import "./OptimismWrapper.sol";
import "./SocketV1Controller.sol";
import "../../interfaces/BasePositionHandler.sol";
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "../LyraL2/interfaces/IPositionHandler.sol";
contract LyraPositionHandler is
BasePositionHandler,
OptimismWrapper,
SocketV1Controller
{
struct OpenPositionParams {
uint256 _listingId;
bool _isCall;
uint256 _amount;
bool _updateExistingPosition;
uint32 _gasLimit;
}
struct ClosePositionParams {
bool _toSettle;
uint32 _gasLimit;
}
struct DepositParams {
uint256 _amount;
address _allowanceTarget;
address _socketRegistry;
bytes _socketData;
}
struct WithdrawParams {
uint256 _amount;
address _allowanceTarget;
address _socketRegistry;
bytes _socketData;
uint32 _gasLimit;
}
address public wantTokenL1;
address public wantTokenL2;
address public positionHandlerL2Address;
address public socketRegistry;
Position public override positionInWantToken;
function _initHandler(
address _wantTokenL1,
address _wantTokenL2,
address _positionHandlerL2Address,
address _L1CrossDomainMessenger,
address _socketRegistry
) internal {
wantTokenL1 = _wantTokenL1;
wantTokenL2 = _wantTokenL2;
positionHandlerL2Address = _positionHandlerL2Address;
L1CrossDomainMessenger = _L1CrossDomainMessenger;
socketRegistry = _socketRegistry;
}
function _deposit(bytes calldata data) internal override {
DepositParams memory depositParams = abi.decode(data, (DepositParams));
require(
depositParams._socketRegistry == socketRegistry,
"INVALID_SOCKET_REGISTRY"
);
sendTokens(
wantTokenL1,
depositParams._allowanceTarget,
depositParams._socketRegistry,
positionHandlerL2Address,
depositParams._amount,
10,
depositParams._socketData
);
emit Deposit(depositParams._amount);
}
function _withdraw(bytes calldata data) internal override {
WithdrawParams memory withdrawParams = abi.decode(
data,
(WithdrawParams)
);
bytes memory L2calldata = abi.encodeWithSelector(
IPositionHandler.withdraw.selector,
withdrawParams._amount,
withdrawParams._socketRegistry,
withdrawParams._socketData
);
sendMessageToL2(
positionHandlerL2Address,
L2calldata,
withdrawParams._gasLimit
);
emit Withdraw(withdrawParams._amount);
}
function _openPosition(bytes calldata data) internal override {
OpenPositionParams memory openPositionParams = abi.decode(
data,
(OpenPositionParams)
);
bytes memory L2calldata = abi.encodeWithSelector(
IPositionHandler.openPosition.selector,
openPositionParams._listingId,
openPositionParams._isCall,
openPositionParams._amount,
openPositionParams._updateExistingPosition
);
sendMessageToL2(
positionHandlerL2Address,
L2calldata,
openPositionParams._gasLimit
);
}
function _closePosition(bytes calldata data) internal override {
ClosePositionParams memory closePositionParams = abi.decode(
data,
(ClosePositionParams)
);
bytes memory L2calldata = abi.encodeWithSelector(
IPositionHandler.closePosition.selector,
closePositionParams._toSettle
);
sendMessageToL2(
positionHandlerL2Address,
L2calldata,
closePositionParams._gasLimit
);
}
function _claimRewards(bytes calldata _data) internal override {
}
function _setPosValue(uint256 _posValue) internal {
positionInWantToken.posValue = _posValue;
positionInWantToken.lastUpdatedBlock = block.number;
}
}
文件 35 的 40:LyraTradeExecutor.sol
pragma solidity ^0.8.4;
import "../BaseTradeExecutor.sol";
import "./LyraPositionHandler.sol";
import "../../interfaces/IVault.sol";
contract LyraTradeExecutor is BaseTradeExecutor, LyraPositionHandler {
constructor(
address vault,
address _wantTokenL2,
address _l2HandlerAddress,
address _L1CrossDomainMessenger,
address _socketRegistry
) BaseTradeExecutor(vault) {
_initHandler(
vaultWantToken(),
_wantTokenL2,
_l2HandlerAddress,
_L1CrossDomainMessenger,
_socketRegistry
);
}
event UpdatedSocketRegistry(
address indexed oldRegistry,
address indexed newRegistry
);
function totalFunds()
public
view
override
returns (uint256 posValue, uint256 lastUpdatedBlock)
{
return (
positionInWantToken.posValue +
IERC20(vaultWantToken()).balanceOf(address(this)),
positionInWantToken.lastUpdatedBlock
);
}
function setPosValue(uint256 _posValue) public keeperOrGovernance {
LyraPositionHandler._setPosValue(_posValue);
}
function setSocketRegistry(address _socketRegistry) public onlyGovernance {
emit UpdatedSocketRegistry(socketRegistry, _socketRegistry);
socketRegistry = _socketRegistry;
}
function setL2Handler(address _l2HandlerAddress) public onlyGovernance {
positionHandlerL2Address = _l2HandlerAddress;
}
function _initateDeposit(bytes calldata _data) internal override {
LyraPositionHandler._deposit(_data);
}
function _confirmDeposit() internal override {}
function _initiateWithdraw(bytes calldata _data) internal override {
LyraPositionHandler._withdraw(_data);
}
function _confirmWithdraw() internal override {}
function openPosition(bytes calldata _data) public onlyKeeper {
LyraPositionHandler._openPosition(_data);
}
function closePosition(bytes calldata _data) public onlyKeeper {
LyraPositionHandler._closePosition(_data);
}
}
文件 36 的 40:OptimismWrapper.sol
pragma solidity ^0.8.4;
import "../../interfaces/ICrossDomainMessenger.sol";
contract OptimismWrapper {
address public L1CrossDomainMessenger;
function messageSender() internal view returns (address) {
ICrossDomainMessenger optimismMessenger = ICrossDomainMessenger(
L1CrossDomainMessenger
);
return optimismMessenger.xDomainMessageSender();
}
function sendMessageToL2(
address _target,
bytes memory _message,
uint32 _gasLimit
) internal {
ICrossDomainMessenger optimismMessenger = ICrossDomainMessenger(
L1CrossDomainMessenger
);
optimismMessenger.sendMessage(_target, _message, _gasLimit);
}
}
文件 37 的 40:Ownable.sol
pragma solidity ^0.8.0;
import "../utils/Context.sol";
abstract contract Ownable is Context {
address private _owner;
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
constructor() {
_transferOwnership(_msgSender());
}
function owner() public view virtual returns (address) {
return _owner;
}
modifier onlyOwner() {
require(owner() == _msgSender(), "Ownable: caller is not the owner");
_;
}
function renounceOwnership() public virtual onlyOwner {
_transferOwnership(address(0));
}
function transferOwnership(address newOwner) public virtual onlyOwner {
require(newOwner != address(0), "Ownable: new owner is the zero address");
_transferOwnership(newOwner);
}
function _transferOwnership(address newOwner) internal virtual {
address oldOwner = _owner;
_owner = newOwner;
emit OwnershipTransferred(oldOwner, newOwner);
}
}
文件 38 的 40:Owned.sol
pragma solidity ^0.8.9;
import "./AbstractOwned.sol";
contract Owned is AbstractOwned {
constructor() {
owner = msg.sender;
emit OwnerChanged(address(0), msg.sender);
}
}
文件 39 的 40:SignedDecimalMath.sol
pragma solidity ^0.8.9;
library SignedDecimalMath {
uint8 public constant decimals = 18;
uint8 public constant highPrecisionDecimals = 27;
int public constant UNIT = int(10**uint(decimals));
int public constant PRECISE_UNIT = int(10**uint(highPrecisionDecimals));
int private constant UNIT_TO_HIGH_PRECISION_CONVERSION_FACTOR = int(10**uint(highPrecisionDecimals - decimals));
function unit() external pure returns (int) {
return UNIT;
}
function preciseUnit() external pure returns (int) {
return PRECISE_UNIT;
}
function _roundDividingByTen(int valueTimesTen) private pure returns (int) {
int increment;
if (valueTimesTen % 10 >= 5) {
increment = 10;
} else if (valueTimesTen % 10 <= -5) {
increment = -10;
}
return (valueTimesTen + increment) / 10;
}
function multiplyDecimal(int x, int y) internal pure returns (int) {
return (x * y) / UNIT;
}
function _multiplyDecimalRound(
int x,
int y,
int precisionUnit
) private pure returns (int) {
int quotientTimesTen = (x * y) / (precisionUnit / 10);
return _roundDividingByTen(quotientTimesTen);
}
function multiplyDecimalRoundPrecise(int x, int y) internal pure returns (int) {
return _multiplyDecimalRound(x, y, PRECISE_UNIT);
}
function multiplyDecimalRound(int x, int y) internal pure returns (int) {
return _multiplyDecimalRound(x, y, UNIT);
}
function divideDecimal(int x, int y) internal pure returns (int) {
return (x * UNIT) / y;
}
function _divideDecimalRound(
int x,
int y,
int precisionUnit
) private pure returns (int) {
int resultTimesTen = (x * (precisionUnit * 10)) / y;
return _roundDividingByTen(resultTimesTen);
}
function divideDecimalRound(int x, int y) internal pure returns (int) {
return _divideDecimalRound(x, y, UNIT);
}
function divideDecimalRoundPrecise(int x, int y) internal pure returns (int) {
return _divideDecimalRound(x, y, PRECISE_UNIT);
}
function decimalToPreciseDecimal(int i) internal pure returns (int) {
return i * UNIT_TO_HIGH_PRECISION_CONVERSION_FACTOR;
}
function preciseDecimalToDecimal(int i) internal pure returns (int) {
int quotientTimesTen = i / (UNIT_TO_HIGH_PRECISION_CONVERSION_FACTOR / 10);
return _roundDividingByTen(quotientTimesTen);
}
}
文件 40 的 40:SocketV1Controller.sol
pragma solidity ^0.8.4;
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
contract SocketV1Controller {
struct MiddlewareRequest {
uint256 id;
uint256 optionalNativeAmount;
address inputToken;
bytes data;
}
struct BridgeRequest {
uint256 id;
uint256 optionalNativeAmount;
address inputToken;
bytes data;
}
struct UserRequest {
address receiverAddress;
uint256 toChainId;
uint256 amount;
MiddlewareRequest middlewareRequest;
BridgeRequest bridgeRequest;
}
function decodeSocketRegistryCalldata(bytes memory _data)
internal
pure
returns (UserRequest memory userRequest)
{
bytes memory callDataWithoutSelector = slice(
_data,
4,
_data.length - 4
);
(userRequest) = abi.decode(callDataWithoutSelector, (UserRequest));
}
function verifySocketCalldata(
bytes memory _data,
uint256 _chainId,
address _inputToken,
address _receiverAddress
) internal pure {
UserRequest memory userRequest;
(userRequest) = decodeSocketRegistryCalldata(_data);
if (userRequest.toChainId != _chainId) {
revert("Invalid chainId");
}
if (userRequest.receiverAddress != _receiverAddress) {
revert("Invalid receiver address");
}
}
function sendTokens(
address token,
address allowanceTarget,
address socketRegistry,
address destinationAddress,
uint256 amount,
uint256 destinationChainId,
bytes memory data
) internal {
verifySocketCalldata(
data,
destinationChainId,
token,
destinationAddress
);
IERC20(token).approve(allowanceTarget, amount);
(bool success, ) = socketRegistry.call(data);
require(success, "Failed to call socketRegistry");
}
function slice(
bytes memory _bytes,
uint256 _start,
uint256 _length
) internal pure returns (bytes memory) {
require(_length + 31 >= _length, "slice_overflow");
require(_bytes.length >= _start + _length, "slice_outOfBounds");
bytes memory tempBytes;
assembly {
switch iszero(_length)
case 0 {
tempBytes := mload(0x40)
let lengthmod := and(_length, 31)
let mc := add(
add(tempBytes, lengthmod),
mul(0x20, iszero(lengthmod))
)
let end := add(mc, _length)
for {
let cc := add(
add(
add(_bytes, lengthmod),
mul(0x20, iszero(lengthmod))
),
_start
)
} lt(mc, end) {
mc := add(mc, 0x20)
cc := add(cc, 0x20)
} {
mstore(mc, mload(cc))
}
mstore(tempBytes, _length)
mstore(0x40, and(add(mc, 31), not(31)))
}
default {
tempBytes := mload(0x40)
mstore(tempBytes, 0)
mstore(0x40, add(tempBytes, 0x20))
}
}
return tempBytes;
}
}
{
"compilationTarget": {
"contracts/LyraExecutor/LyraTradeExecutor.sol": "LyraTradeExecutor"
},
"evmVersion": "london",
"libraries": {},
"metadata": {
"bytecodeHash": "ipfs"
},
"optimizer": {
"enabled": true,
"runs": 100
},
"remappings": []
}
[{"inputs":[{"internalType":"address","name":"vault","type":"address"},{"internalType":"address","name":"_wantTokenL2","type":"address"},{"internalType":"address","name":"_l2HandlerAddress","type":"address"},{"internalType":"address","name":"_L1CrossDomainMessenger","type":"address"},{"internalType":"address","name":"_socketRegistry","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Claim","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Deposit","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"oldRegistry","type":"address"},{"indexed":true,"internalType":"address","name":"newRegistry","type":"address"}],"name":"UpdatedSocketRegistry","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Withdraw","type":"event"},{"inputs":[],"name":"L1CrossDomainMessenger","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes","name":"_data","type":"bytes"}],"name":"closePosition","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"confirmDeposit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"confirmWithdraw","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"depositStatus","outputs":[{"internalType":"bool","name":"inProcess","type":"bool"},{"internalType":"address","name":"from","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"governance","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes","name":"_data","type":"bytes"}],"name":"initiateDeposit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes","name":"_data","type":"bytes"}],"name":"initiateWithdraw","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"keeper","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes","name":"_data","type":"bytes"}],"name":"openPosition","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"positionHandlerL2Address","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"positionInWantToken","outputs":[{"internalType":"uint256","name":"posValue","type":"uint256"},{"internalType":"uint256","name":"lastUpdatedBlock","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_l2HandlerAddress","type":"address"}],"name":"setL2Handler","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_posValue","type":"uint256"}],"name":"setPosValue","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_socketRegistry","type":"address"}],"name":"setSocketRegistry","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"socketRegistry","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_token","type":"address"}],"name":"sweep","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"totalFunds","outputs":[{"internalType":"uint256","name":"posValue","type":"uint256"},{"internalType":"uint256","name":"lastUpdatedBlock","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"vault","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"vaultWantToken","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"wantTokenL1","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"wantTokenL2","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"withdrawalStatus","outputs":[{"internalType":"bool","name":"inProcess","type":"bool"},{"internalType":"address","name":"from","type":"address"}],"stateMutability":"view","type":"function"}]