编译器
0.8.24+commit.e11b9ed9
文件 1 的 12:Address.sol
pragma solidity ^0.8.20;
import {Errors} from "./Errors.sol";
library Address {
error AddressEmptyCode(address target);
function sendValue(address payable recipient, uint256 amount) internal {
if (address(this).balance < amount) {
revert Errors.InsufficientBalance(address(this).balance, amount);
}
(bool success, ) = recipient.call{value: amount}("");
if (!success) {
revert Errors.FailedCall();
}
}
function functionCall(address target, bytes memory data) internal returns (bytes memory) {
return functionCallWithValue(target, data, 0);
}
function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {
if (address(this).balance < value) {
revert Errors.InsufficientBalance(address(this).balance, value);
}
(bool success, bytes memory returndata) = target.call{value: value}(data);
return verifyCallResultFromTarget(target, success, returndata);
}
function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
(bool success, bytes memory returndata) = target.staticcall(data);
return verifyCallResultFromTarget(target, success, returndata);
}
function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
(bool success, bytes memory returndata) = target.delegatecall(data);
return verifyCallResultFromTarget(target, success, returndata);
}
function verifyCallResultFromTarget(
address target,
bool success,
bytes memory returndata
) internal view returns (bytes memory) {
if (!success) {
_revert(returndata);
} else {
if (returndata.length == 0 && target.code.length == 0) {
revert AddressEmptyCode(target);
}
return returndata;
}
}
function verifyCallResult(bool success, bytes memory returndata) internal pure returns (bytes memory) {
if (!success) {
_revert(returndata);
} else {
return returndata;
}
}
function _revert(bytes memory returndata) private pure {
if (returndata.length > 0) {
assembly {
let returndata_size := mload(returndata)
revert(add(32, returndata), returndata_size)
}
} else {
revert Errors.FailedCall();
}
}
}
文件 2 的 12:Errors.sol
pragma solidity ^0.8.20;
library Errors {
error InsufficientBalance(uint256 balance, uint256 needed);
error FailedCall();
error FailedDeployment();
}
文件 3 的 12:IERC1363.sol
pragma solidity ^0.8.20;
import {IERC20} from "./IERC20.sol";
import {IERC165} from "./IERC165.sol";
interface IERC1363 is IERC20, IERC165 {
function transferAndCall(address to, uint256 value) external returns (bool);
function transferAndCall(address to, uint256 value, bytes calldata data) external returns (bool);
function transferFromAndCall(address from, address to, uint256 value) external returns (bool);
function transferFromAndCall(address from, address to, uint256 value, bytes calldata data) external returns (bool);
function approveAndCall(address spender, uint256 value) external returns (bool);
function approveAndCall(address spender, uint256 value, bytes calldata data) external returns (bool);
}
文件 4 的 12:IERC165.sol
pragma solidity ^0.8.20;
import {IERC165} from "../utils/introspection/IERC165.sol";
文件 5 的 12:IERC20.sol
pragma solidity ^0.8.20;
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 value) external returns (bool);
function allowance(address owner, address spender) external view returns (uint256);
function approve(address spender, uint256 value) external returns (bool);
function transferFrom(address from, address to, uint256 value) external returns (bool);
}
文件 6 的 12:IERC20Metadata.sol
pragma solidity ^0.8.20;
import {IERC20} from "../IERC20.sol";
interface IERC20Metadata is IERC20 {
function name() external view returns (string memory);
function symbol() external view returns (string memory);
function decimals() external view returns (uint8);
}
文件 7 的 12:ILeveragedToken.sol
pragma solidity ^0.8.13;
import {IERC20Metadata} from "openzeppelin-contracts/contracts/token/ERC20/extensions/IERC20Metadata.sol";
interface ILeveragedToken is IERC20Metadata {
event Minted(
address indexed recipient,
uint256 baseAssetAmount,
uint256 leveragedTokenAmount,
bytes32 indexed referralCode
);
event Redeemed(
address indexed recipient,
address indexed caller,
uint256 baseAssetAmount,
uint256 leveragedTokenAmount,
bytes32 indexed referralCode
);
event MintedAmountIncreased(address indexed user, uint256 amount);
event Rebalanced(uint256 currentLeverage);
event PausedSet(bool isPaused);
error InsufficientAmount();
error CannotRebalance();
error RebalanceNotSubmittedDueToSlippage();
error LeverageUpdatePending();
error Paused();
error Inactive();
error NoMargin();
error MaxMarketValueExceeded();
error MaxMarketSizeExceeded();
error NegativeSize();
error Liquidatable();
function mintFor(
uint256 baseAmountIn,
uint256 minLeveragedTokenAmountOut,
address recipient,
bytes memory updateData,
bytes32 referralCode
) external returns (uint256 leveragedTokenAmountOut);
function redeemFor(
uint256 leveragedTokenAmount,
uint256 minBaseAmountReceived,
address recipient,
address caller,
bytes memory updateData,
bytes32 referralCode
) external returns (uint256 baseAmountReceived);
function rebalance() external;
function rebalanceWithPriceUpdate(bytes memory updateData) external;
function burn(uint256 value) external;
function setIsPaused(bool newIsPaused) external;
function targetAsset() external view returns (string memory targetAsset);
function marketId() external view returns (uint128 marketId);
function targetLeverage() external view returns (uint256 targetLeverage);
function isLong() external view returns (bool isLong);
function isActive() external view returns (bool isActive);
function isPaused() external view returns (bool isPaused);
function accountId() external view returns (uint128 accountId);
function mintedTimestamp(
address user
) external view returns (uint256 mintedTimestamp);
function rebalanceThreshold()
external
view
returns (uint256 rebalanceThreshold);
function exchangeRate() external view returns (uint256 exchangeRate);
function exchangeRate(
bytes memory updateData
) external returns (uint256 exchangeRate);
function computePriceImpact(
uint256 baseAmount,
bool isDeposit
) external view returns (uint256 slippage);
function canRebalance() external view returns (bool canRebalance);
function decayingRedemptionFee(
address user,
uint256 ltAmount
) external view returns (uint256 fee);
function hasPendingLeverageUpdate()
external
view
returns (bool hasPendingLeverageUpdate);
function hasOpenPosition() external view returns (bool hasOpenPosition);
function totalValue() external view returns (uint256 totalValue);
function leverageDeviationFactor()
external
view
returns (uint256 leverageDeviationFactor);
function leverage() external view returns (uint256 leverage);
function notionalValue() external view returns (uint256 notionalValue);
function initialMargin() external view returns (uint256 initialMargin);
function remainingMargin() external view returns (uint256 remainingMargin);
function assetPrice() external view returns (uint256 assetPrice);
}
文件 8 的 12:ISpotMarket.sol
pragma solidity ^0.8.4;
interface ISpotMarket {
error ImplementationIsSterile(address implementation);
error NoChange();
error NotAContract(address contr);
error NotNominated(address addr);
error Unauthorized(address addr);
error UpgradeSimulationFailed();
error ZeroAddress();
event OwnerChanged(address oldOwner, address newOwner);
event OwnerNominated(address newOwner);
event Upgraded(address indexed self, address implementation);
function acceptOwnership() external;
function getImplementation() external view returns (address);
function nominateNewOwner(address newNominatedOwner) external;
function nominatedOwner() external view returns (address);
function owner() external view returns (address);
function renounceNomination() external;
function simulateUpgradeTo(address newImplementation) external;
function upgradeTo(address newImplementation) external;
error FeatureUnavailable(bytes32 which);
error InvalidMarketOwner();
error InvalidSynthImplementation(uint256 synthImplementation);
error MismatchAssociatedSystemKind(bytes32 expected, bytes32 actual);
error MissingAssociatedSystem(bytes32 id);
error OnlyMarketOwner(address marketOwner, address sender);
error OverflowInt256ToUint256();
event AssociatedSystemSet(
bytes32 indexed kind,
bytes32 indexed id,
address proxy,
address impl
);
event DecayRateUpdated(uint128 indexed marketId, uint256 rate);
event MarketNominationRenounced(uint128 indexed marketId, address nominee);
event MarketOwnerChanged(
uint128 indexed marketId,
address oldOwner,
address newOwner
);
event MarketOwnerNominated(uint128 indexed marketId, address newOwner);
event SynthImplementationSet(address synthImplementation);
event SynthImplementationUpgraded(
uint256 indexed synthMarketId,
address indexed proxy,
address implementation
);
event SynthPriceDataUpdated(
uint256 indexed synthMarketId,
bytes32 indexed buyFeedId,
bytes32 indexed sellFeedId,
uint256 strictStalenessTolerance
);
event SynthRegistered(
uint256 indexed synthMarketId,
address synthTokenAddress
);
event SynthetixSystemSet(
address synthetix,
address usdTokenAddress,
address oracleManager
);
function acceptMarketOwnership(uint128 synthMarketId) external;
function createSynth(
string memory tokenName,
string memory tokenSymbol,
address synthOwner
) external returns (uint128 synthMarketId);
function getAssociatedSystem(
bytes32 id
) external view returns (address addr, bytes32 kind);
function getMarketOwner(
uint128 synthMarketId
) external view returns (address marketOwner);
function getNominatedMarketOwner(
uint128 synthMarketId
) external view returns (address marketOwner);
function getPriceData(
uint128 synthMarketId
)
external
view
returns (
bytes32 buyFeedId,
bytes32 sellFeedId,
uint256 strictPriceStalenessTolerance
);
function getSynth(
uint128 marketId
) external view returns (address synthAddress);
function getSynthImpl(
uint128 marketId
) external view returns (address implAddress);
function initOrUpgradeNft(
bytes32 id,
string memory name,
string memory symbol,
string memory uri,
address impl
) external;
function initOrUpgradeToken(
bytes32 id,
string memory name,
string memory symbol,
uint8 decimals,
address impl
) external;
function minimumCredit(
uint128 marketId
) external view returns (uint256 lockedAmount);
function name(
uint128 marketId
) external view returns (string memory marketName);
function nominateMarketOwner(
uint128 synthMarketId,
address newNominatedOwner
) external;
function registerUnmanagedSystem(bytes32 id, address endpoint) external;
function renounceMarketNomination(uint128 synthMarketId) external;
function renounceMarketOwnership(uint128 synthMarketId) external;
function reportedDebt(
uint128 marketId
) external view returns (uint256 reportedDebtAmount);
function setDecayRate(uint128 marketId, uint256 rate) external;
function setSynthImplementation(address synthImplementation) external;
function setSynthetix(address synthetix) external;
function supportsInterface(
bytes4 interfaceId
) external view returns (bool isSupported);
function updatePriceData(
uint128 synthMarketId,
bytes32 buyFeedId,
bytes32 sellFeedId,
uint256 strictPriceStalenessTolerance
) external;
function upgradeSynthImpl(uint128 marketId) external;
error ExceedsMaxSynthAmount(
uint256 maxSynthAmount,
uint256 synthAmountCharged
);
error ExceedsMaxUsdAmount(uint256 maxUsdAmount, uint256 usdAmountCharged);
error InsufficientAmountReceived(uint256 expected, uint256 current);
error InvalidMarket(uint128 marketId);
error InvalidPrices();
error OverflowUint256ToInt256();
event SynthBought(
uint256 indexed synthMarketId,
uint256 synthReturned,
OrderFees.Data fees,
uint256 collectedFees,
address referrer,
uint256 price
);
event SynthSold(
uint256 indexed synthMarketId,
uint256 amountReturned,
OrderFees.Data fees,
uint256 collectedFees,
address referrer,
uint256 price
);
function buy(
uint128 marketId,
uint256 usdAmount,
uint256 minAmountReceived,
address referrer
) external returns (uint256 synthAmount, OrderFees.Data memory fees);
function buyExactIn(
uint128 marketId,
uint256 usdAmount,
uint256 minAmountReceived,
address referrer
) external returns (uint256 synthAmount, OrderFees.Data memory fees);
function buyExactOut(
uint128 marketId,
uint256 synthAmount,
uint256 maxUsdAmount,
address referrer
) external returns (uint256 usdAmountCharged, OrderFees.Data memory fees);
function getMarketSkew(
uint128 marketId
) external view returns (int256 marketSkew);
function quoteBuyExactIn(
uint128 marketId,
uint256 usdAmount,
uint8 stalenessTolerance
) external view returns (uint256 synthAmount, OrderFees.Data memory fees);
function quoteBuyExactOut(
uint128 marketId,
uint256 synthAmount,
uint8 stalenessTolerance
)
external
view
returns (uint256 usdAmountCharged, OrderFees.Data memory fees);
function quoteSellExactIn(
uint128 marketId,
uint256 synthAmount,
uint8 stalenessTolerance
) external view returns (uint256 returnAmount, OrderFees.Data memory fees);
function quoteSellExactOut(
uint128 marketId,
uint256 usdAmount,
uint8 stalenessTolerance
) external view returns (uint256 synthToBurn, OrderFees.Data memory fees);
function sell(
uint128 marketId,
uint256 synthAmount,
uint256 minUsdAmount,
address referrer
) external returns (uint256 usdAmountReceived, OrderFees.Data memory fees);
function sellExactIn(
uint128 marketId,
uint256 synthAmount,
uint256 minAmountReceived,
address referrer
) external returns (uint256 returnAmount, OrderFees.Data memory fees);
function sellExactOut(
uint128 marketId,
uint256 usdAmount,
uint256 maxSynthAmount,
address referrer
) external returns (uint256 synthToBurn, OrderFees.Data memory fees);
error IneligibleForCancellation(uint256 timestamp, uint256 expirationTime);
error InsufficientSharesAmount(uint256 expected, uint256 actual);
error InvalidAsyncTransactionType(uint8 transactionType);
error InvalidClaim(uint256 asyncOrderId);
error InvalidCommitmentAmount(uint256 minimumAmount, uint256 amount);
error InvalidSettlementStrategy(uint256 settlementStrategyId);
error OrderAlreadySettled(uint256 asyncOrderId, uint256 settledAt);
event OrderCancelled(
uint128 indexed marketId,
uint128 indexed asyncOrderId,
AsyncOrderClaim.Data asyncOrderClaim,
address indexed sender
);
event OrderCommitted(
uint128 indexed marketId,
uint8 indexed orderType,
uint256 amountProvided,
uint128 asyncOrderId,
address indexed sender,
address referrer
);
function cancelOrder(uint128 marketId, uint128 asyncOrderId) external;
function commitOrder(
uint128 marketId,
uint8 orderType,
uint256 amountProvided,
uint256 settlementStrategyId,
uint256 minimumSettlementAmount,
address referrer
) external returns (AsyncOrderClaim.Data memory asyncOrderClaim);
function getAsyncOrderClaim(
uint128 marketId,
uint128 asyncOrderId
) external pure returns (AsyncOrderClaim.Data memory asyncOrderClaim);
error InvalidVerificationResponse();
error MinimumSettlementAmountNotMet(uint256 minimum, uint256 actual);
error OutsideSettlementWindow(
uint256 timestamp,
uint256 startTime,
uint256 expirationTime
);
error OverflowUint256ToUint64();
error SettlementStrategyNotFound(uint8 strategyType);
event OrderSettled(
uint128 indexed marketId,
uint128 indexed asyncOrderId,
uint256 finalOrderAmount,
OrderFees.Data fees,
uint256 collectedFees,
address indexed settler,
uint256 price,
uint8 orderType
);
function settleOrder(
uint128 marketId,
uint128 asyncOrderId
) external returns (uint256 finalOrderAmount, OrderFees.Data memory fees);
error InvalidSettlementWindowDuration(uint256 duration);
event SettlementStrategyAdded(
uint128 indexed synthMarketId,
uint256 indexed strategyId
);
event SettlementStrategySet(
uint128 indexed synthMarketId,
uint256 indexed strategyId,
SettlementStrategy.Data strategy
);
function addSettlementStrategy(
uint128 marketId,
SettlementStrategy.Data memory strategy
) external returns (uint256 strategyId);
function getSettlementStrategy(
uint128 marketId,
uint256 strategyId
) external view returns (SettlementStrategy.Data memory settlementStrategy);
function setSettlementStrategy(
uint128 marketId,
uint256 strategyId,
SettlementStrategy.Data memory strategy
) external;
function setSettlementStrategyEnabled(
uint128 marketId,
uint256 strategyId,
bool enabled
) external;
error FailedTransfer(address from, address to, uint256 value);
error InvalidCollateralType(address configuredCollateralType);
error WrapperExceedsMaxAmount(
uint256 maxWrappableAmount,
uint256 currentSupply,
uint256 amountToWrap
);
event SynthUnwrapped(
uint256 indexed synthMarketId,
uint256 amountUnwrapped,
OrderFees.Data fees,
uint256 feesCollected
);
event SynthWrapped(
uint256 indexed synthMarketId,
uint256 amountWrapped,
OrderFees.Data fees,
uint256 feesCollected
);
event WrapperSet(
uint256 indexed synthMarketId,
address indexed wrapCollateralType,
uint256 maxWrappableAmount
);
function getWrapper(
uint128 marketId
)
external
view
returns (address wrapCollateralType, uint256 maxWrappableAmount);
function setWrapper(
uint128 marketId,
address wrapCollateralType,
uint256 maxWrappableAmount
) external;
function unwrap(
uint128 marketId,
uint256 unwrapAmount,
uint256 minAmountReceived
)
external
returns (uint256 returnCollateralAmount, OrderFees.Data memory fees);
function wrap(
uint128 marketId,
uint256 wrapAmount,
uint256 minAmountReceived
) external returns (uint256 amountToMint, OrderFees.Data memory fees);
error InvalidCollateralLeverage(uint256);
error InvalidFeeCollectorInterface(address invalidFeeCollector);
error InvalidWrapperFees();
event AsyncFixedFeeSet(
uint256 indexed synthMarketId,
uint256 asyncFixedFee
);
event AtomicFixedFeeSet(
uint256 indexed synthMarketId,
uint256 atomicFixedFee
);
event CollateralLeverageSet(
uint256 indexed synthMarketId,
uint256 collateralLeverage
);
event FeeCollectorSet(uint256 indexed synthMarketId, address feeCollector);
event MarketSkewScaleSet(uint256 indexed synthMarketId, uint256 skewScale);
event MarketUtilizationFeesSet(
uint256 indexed synthMarketId,
uint256 utilizationFeeRate
);
event ReferrerShareUpdated(
uint128 indexed marketId,
address referrer,
uint256 sharePercentage
);
event TransactorFixedFeeSet(
uint256 indexed synthMarketId,
address transactor,
uint256 fixedFeeAmount
);
event WrapperFeesSet(
uint256 indexed synthMarketId,
int256 wrapFee,
int256 unwrapFee
);
function getCollateralLeverage(
uint128 synthMarketId
) external view returns (uint256 collateralLeverage);
function getCustomTransactorFees(
uint128 synthMarketId,
address transactor
) external view returns (uint256 fixedFeeAmount);
function getFeeCollector(
uint128 synthMarketId
) external view returns (address feeCollector);
function getMarketFees(
uint128 synthMarketId
)
external
view
returns (
uint256 atomicFixedFee,
uint256 asyncFixedFee,
int256 wrapFee,
int256 unwrapFee
);
function getMarketSkewScale(
uint128 synthMarketId
) external view returns (uint256 skewScale);
function getMarketUtilizationFees(
uint128 synthMarketId
) external view returns (uint256 utilizationFeeRate);
function getReferrerShare(
uint128 synthMarketId,
address referrer
) external view returns (uint256 sharePercentage);
function setAsyncFixedFee(
uint128 synthMarketId,
uint256 asyncFixedFee
) external;
function setAtomicFixedFee(
uint128 synthMarketId,
uint256 atomicFixedFee
) external;
function setCollateralLeverage(
uint128 synthMarketId,
uint256 collateralLeverage
) external;
function setCustomTransactorFees(
uint128 synthMarketId,
address transactor,
uint256 fixedFeeAmount
) external;
function setFeeCollector(
uint128 synthMarketId,
address feeCollector
) external;
function setMarketSkewScale(
uint128 synthMarketId,
uint256 skewScale
) external;
function setMarketUtilizationFees(
uint128 synthMarketId,
uint256 utilizationFeeRate
) external;
function setWrapperFees(
uint128 synthMarketId,
int256 wrapFee,
int256 unwrapFee
) external;
function updateReferrerShare(
uint128 synthMarketId,
address referrer,
uint256 sharePercentage
) external;
error ValueAlreadyInSet();
error ValueNotInSet();
event FeatureFlagAllowAllSet(bytes32 indexed feature, bool allowAll);
event FeatureFlagAllowlistAdded(bytes32 indexed feature, address account);
event FeatureFlagAllowlistRemoved(bytes32 indexed feature, address account);
event FeatureFlagDeniersReset(bytes32 indexed feature, address[] deniers);
event FeatureFlagDenyAllSet(bytes32 indexed feature, bool denyAll);
function addToFeatureFlagAllowlist(
bytes32 feature,
address account
) external;
function getDeniers(
bytes32 feature
) external view returns (address[] memory);
function getFeatureFlagAllowAll(
bytes32 feature
) external view returns (bool);
function getFeatureFlagAllowlist(
bytes32 feature
) external view returns (address[] memory);
function getFeatureFlagDenyAll(
bytes32 feature
) external view returns (bool);
function isFeatureAllowed(
bytes32 feature,
address account
) external view returns (bool);
function removeFromFeatureFlagAllowlist(
bytes32 feature,
address account
) external;
function setDeniers(bytes32 feature, address[] memory deniers) external;
function setFeatureFlagAllowAll(bytes32 feature, bool allowAll) external;
function setFeatureFlagDenyAll(bytes32 feature, bool denyAll) external;
}
interface OrderFees {
struct Data {
uint256 fixedFees;
uint256 utilizationFees;
int256 skewFees;
int256 wrapperFees;
}
}
interface AsyncOrderClaim {
struct Data {
uint128 id;
address owner;
uint8 orderType;
uint256 amountEscrowed;
uint256 settlementStrategyId;
uint256 commitmentTime;
uint256 minimumSettlementAmount;
uint256 settledAt;
address referrer;
}
}
interface SettlementStrategy {
struct Data {
uint8 strategyType;
uint256 settlementDelay;
uint256 settlementWindowDuration;
address priceVerificationContract;
bytes32 feedId;
string url;
uint256 settlementReward;
uint256 priceDeviationTolerance;
uint256 minimumUsdExchangeAmount;
uint256 maxRoundingLoss;
bool disabled;
}
}
文件 9 的 12:IWrapperHelper.sol
pragma solidity ^0.8.13;
import {ISpotMarket} from "../interfaces/synthetix/ISpotMarket.sol";
interface IWrapperHelper {
function spotMarket() external view returns (ISpotMarket spotMarket);
function mintWithUSDC(
address leveragedTokenAddress,
uint256 usdcAmount,
uint256 minLeveragedTokenAmountOut,
bytes calldata updateData,
bytes32 referralCode
) external returns (uint256);
function redeemIntoUSDC(
address leveragedTokenAddress,
uint256 amount,
uint256 minUsdOut,
bytes calldata updateData,
bytes32 referralCode
) external returns (uint256);
}
文件 10 的 12:SafeERC20.sol
pragma solidity ^0.8.20;
import {IERC20} from "../IERC20.sol";
import {IERC1363} from "../../../interfaces/IERC1363.sol";
import {Address} from "../../../utils/Address.sol";
library SafeERC20 {
using Address for address;
error SafeERC20FailedOperation(address token);
error SafeERC20FailedDecreaseAllowance(address spender, uint256 currentAllowance, uint256 requestedDecrease);
function safeTransfer(IERC20 token, address to, uint256 value) internal {
_callOptionalReturn(token, abi.encodeCall(token.transfer, (to, value)));
}
function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {
_callOptionalReturn(token, abi.encodeCall(token.transferFrom, (from, to, value)));
}
function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {
uint256 oldAllowance = token.allowance(address(this), spender);
forceApprove(token, spender, oldAllowance + value);
}
function safeDecreaseAllowance(IERC20 token, address spender, uint256 requestedDecrease) internal {
unchecked {
uint256 currentAllowance = token.allowance(address(this), spender);
if (currentAllowance < requestedDecrease) {
revert SafeERC20FailedDecreaseAllowance(spender, currentAllowance, requestedDecrease);
}
forceApprove(token, spender, currentAllowance - requestedDecrease);
}
}
function forceApprove(IERC20 token, address spender, uint256 value) internal {
bytes memory approvalCall = abi.encodeCall(token.approve, (spender, value));
if (!_callOptionalReturnBool(token, approvalCall)) {
_callOptionalReturn(token, abi.encodeCall(token.approve, (spender, 0)));
_callOptionalReturn(token, approvalCall);
}
}
function transferAndCallRelaxed(IERC1363 token, address to, uint256 value, bytes memory data) internal {
if (to.code.length == 0) {
safeTransfer(token, to, value);
} else if (!token.transferAndCall(to, value, data)) {
revert SafeERC20FailedOperation(address(token));
}
}
function transferFromAndCallRelaxed(
IERC1363 token,
address from,
address to,
uint256 value,
bytes memory data
) internal {
if (to.code.length == 0) {
safeTransferFrom(token, from, to, value);
} else if (!token.transferFromAndCall(from, to, value, data)) {
revert SafeERC20FailedOperation(address(token));
}
}
function approveAndCallRelaxed(IERC1363 token, address to, uint256 value, bytes memory data) internal {
if (to.code.length == 0) {
forceApprove(token, to, value);
} else if (!token.approveAndCall(to, value, data)) {
revert SafeERC20FailedOperation(address(token));
}
}
function _callOptionalReturn(IERC20 token, bytes memory data) private {
bytes memory returndata = address(token).functionCall(data);
if (returndata.length != 0 && !abi.decode(returndata, (bool))) {
revert SafeERC20FailedOperation(address(token));
}
}
function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) {
(bool success, bytes memory returndata) = address(token).call(data);
return success && (returndata.length == 0 || abi.decode(returndata, (bool))) && address(token).code.length > 0;
}
}
文件 11 的 12:ScaledNumber.sol
pragma solidity ^0.8.13;
library ScaledNumber {
uint8 internal constant _DEFAULT_DECIMALS = 18;
uint256 public constant ONE = 10 ** _DEFAULT_DECIMALS;
function div(
uint256 value,
uint256 divisor
) internal pure returns (uint256) {
return (value * 10 ** _DEFAULT_DECIMALS) / divisor;
}
function mul(
uint256 value,
uint256 multiplier
) internal pure returns (uint256) {
return (value * multiplier) / 10 ** _DEFAULT_DECIMALS;
}
function absSub(uint256 a, uint256 b) internal pure returns (uint256) {
return a > b ? a - b : b - a;
}
}
文件 12 的 12:WrapperHelper.sol
pragma solidity ^0.8.13;
import {IERC20} from "openzeppelin-contracts/contracts/token/ERC20/IERC20.sol";
import {SafeERC20} from "openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol";
import {ScaledNumber} from "../libraries/ScaledNumber.sol";
import {ILeveragedToken} from "../interfaces/ILeveragedToken.sol";
import {ISpotMarket} from "../interfaces/synthetix/ISpotMarket.sol";
import {IWrapperHelper} from "../interfaces/IWrapperHelper.sol";
contract WrapperHelper is IWrapperHelper {
using SafeERC20 for IERC20;
using ScaledNumber for uint256;
uint128 internal constant _SPOT_MARKET_ID = 1;
uint256 internal constant _USDC_DECIMALS = 6;
uint256 internal constant _SYNTH_DECIMALS = 18;
address internal constant _USDC =
0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913;
address internal constant _SUSDC =
0xC74eA762cF06c9151cE074E6a569a5945b6302E7;
address internal constant _SNXUSD =
0x09d51516F38980035153a554c26Df3C6f51a23C3;
address internal constant _SPOT_MARKET_ADDRESS =
0x18141523403e2595D31b22604AcB8Fc06a4CaA61;
ISpotMarket public immutable override spotMarket;
constructor() {
spotMarket = ISpotMarket(_SPOT_MARKET_ADDRESS);
IERC20(_USDC).approve(_SPOT_MARKET_ADDRESS, type(uint256).max);
IERC20(_SUSDC).approve(_SPOT_MARKET_ADDRESS, type(uint256).max);
IERC20(_SNXUSD).approve(_SPOT_MARKET_ADDRESS, type(uint256).max);
}
function mintWithUSDC(
address leveragedTokenAddress,
uint256 usdcAmount,
uint256 minLeveragedTokenAmountOut,
bytes calldata updateData,
bytes32 referralCode
) external override returns (uint256) {
uint256 convertedAmount = (usdcAmount * 10 ** _SYNTH_DECIMALS) /
10 ** _USDC_DECIMALS;
IERC20(_USDC).safeTransferFrom(msg.sender, address(this), usdcAmount);
spotMarket.wrap(_SPOT_MARKET_ID, usdcAmount, convertedAmount);
(uint256 snxUsdAmount, ) = spotMarket.sellExactIn(
_SPOT_MARKET_ID,
convertedAmount,
convertedAmount,
address(0)
);
IERC20(_SNXUSD).approve(leveragedTokenAddress, snxUsdAmount);
return
ILeveragedToken(leveragedTokenAddress).mintFor(
snxUsdAmount,
minLeveragedTokenAmountOut,
msg.sender,
updateData,
referralCode
);
}
function redeemIntoUSDC(
address leveragedTokenAddress,
uint256 amount,
uint256 minUsdOut,
bytes calldata updateData,
bytes32 referralCode
) external override returns (uint256) {
IERC20(leveragedTokenAddress).safeTransferFrom(
msg.sender,
address(this),
amount
);
uint256 amountRecieved = ILeveragedToken(leveragedTokenAddress)
.redeemFor(
amount,
minUsdOut,
address(this),
msg.sender,
updateData,
referralCode
);
(uint256 synthAmount, ) = spotMarket.buyExactIn(
_SPOT_MARKET_ID,
amountRecieved,
amountRecieved,
address(0)
);
uint256 usdcAmount = (synthAmount * 10 ** _USDC_DECIMALS) /
10 ** _SYNTH_DECIMALS;
spotMarket.unwrap(_SPOT_MARKET_ID, synthAmount, usdcAmount);
IERC20(_USDC).safeTransfer(msg.sender, usdcAmount);
return usdcAmount;
}
}
{
"compilationTarget": {
"src/helpers/WrapperHelper.sol": "WrapperHelper"
},
"evmVersion": "cancun",
"libraries": {},
"metadata": {
"bytecodeHash": "ipfs"
},
"optimizer": {
"enabled": true,
"runs": 200
},
"remappings": [
":@openzeppelin/contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/contracts/",
":@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/",
":chainlink/=lib/chainlink/contracts/",
":ds-test/=lib/forge-std/lib/ds-test/src/",
":erc4626-tests/=lib/openzeppelin-contracts-upgradeable/lib/erc4626-tests/",
":forge-std/=lib/forge-std/src/",
":openzeppelin-contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/",
":openzeppelin-contracts/=lib/openzeppelin-contracts/",
":pyth-sdk-solidity/=lib/pyth-sdk-solidity/"
]
}
[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"address","name":"target","type":"address"}],"name":"AddressEmptyCode","type":"error"},{"inputs":[],"name":"FailedCall","type":"error"},{"inputs":[{"internalType":"uint256","name":"balance","type":"uint256"},{"internalType":"uint256","name":"needed","type":"uint256"}],"name":"InsufficientBalance","type":"error"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"SafeERC20FailedOperation","type":"error"},{"inputs":[{"internalType":"address","name":"leveragedTokenAddress","type":"address"},{"internalType":"uint256","name":"usdcAmount","type":"uint256"},{"internalType":"uint256","name":"minLeveragedTokenAmountOut","type":"uint256"},{"internalType":"bytes","name":"updateData","type":"bytes"},{"internalType":"bytes32","name":"referralCode","type":"bytes32"}],"name":"mintWithUSDC","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"leveragedTokenAddress","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"minUsdOut","type":"uint256"},{"internalType":"bytes","name":"updateData","type":"bytes"},{"internalType":"bytes32","name":"referralCode","type":"bytes32"}],"name":"redeemIntoUSDC","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"spotMarket","outputs":[{"internalType":"contract ISpotMarket","name":"","type":"address"}],"stateMutability":"view","type":"function"}]