├── .circleci ├── README.md ├── config.template.yml ├── config.yml ├── pack.js └── src │ ├── commands │ └── cmd-wait-for-port.yml │ ├── jobs │ ├── job-audit.yml │ ├── job-cannon.yml │ ├── job-fork-tests-ovm.yml │ ├── job-fork-tests.yml │ ├── job-integration-tests.yml │ ├── job-lint.yml │ ├── job-pack-browser.yml │ ├── job-prepare.yml │ ├── job-simulate-release.yml │ ├── job-static-analysis.yml │ ├── job-test-deploy-script.yml │ ├── job-unit-tests-coverage-report.yml │ ├── job-unit-tests-coverage.yml │ ├── job-unit-tests-gas-report.yml │ ├── job-unit-tests.yml │ ├── job-validate-deployments.yml │ └── job-validate-etherscan.yml │ ├── snippets │ ├── job-header-machine.yml │ ├── job-header-node.yml │ ├── job-header-sec-tools.yml │ ├── require-audit.yml │ ├── require-cannon.yml │ ├── require-prepare.yml │ ├── require-unit-tests-coverage.yml │ └── require-unit-tests.yml │ └── workflows │ └── workflow-all.yml ├── .env.example ├── .eslintignore ├── .eslintrc.js ├── .gitattributes ├── .github └── workflows │ ├── codeql.yml │ └── slither-analysis.yml ├── .gitignore ├── .npmrc ├── .nvmrc ├── .prettierignore ├── .prettierrc ├── .solcover.js ├── .solhint.json ├── LICENSE ├── README.md ├── bin.js ├── browser.js.LICENSE.txt ├── cannonfile.aggregator.toml ├── cannonfile.optimism.toml ├── cannonfile.release.toml ├── cannonfile.toml ├── codechecks.unit.yml ├── codecov.yml ├── contracts ├── AddressResolver.sol ├── AddressSetLib.sol ├── BaseDebtCache.sol ├── BaseDebtMigrator.sol ├── BaseMigration.sol ├── BaseOneNetAggregator.sol ├── BaseRewardEscrowV2.sol ├── BaseSynthetix.sol ├── BaseSynthetixBridge.sol ├── Bytes32SetLib.sol ├── CircuitBreaker.sol ├── Collateral.sol ├── CollateralErc20.sol ├── CollateralEth.sol ├── CollateralManager.sol ├── CollateralManagerState.sol ├── CollateralShort.sol ├── CollateralUtil.sol ├── ContractStorage.sol ├── DappMaintenance.sol ├── DebtCache.sol ├── DebtMigratorOnEthereum.sol ├── DebtMigratorOnOptimism.sol ├── DelegateApprovals.sol ├── Depot.sol ├── DirectIntegrationManager.sol ├── DynamicSynthRedeemer.sol ├── EmptyCollateralManager.sol ├── EmptyEtherWrapper.sol ├── EmptyFuturesMarketManager.sol ├── EscrowChecker.sol ├── EternalStorage.sol ├── EtherWrapper.sol ├── ExchangeCircuitBreaker.sol ├── ExchangeRates.sol ├── ExchangeRatesWithDexPricing.sol ├── ExchangeSettlementLib.sol ├── ExchangeState.sol ├── Exchanger.sol ├── ExchangerWithFeeRecAlternatives.sol ├── ExternStateToken.sol ├── FeePool.sol ├── FeePoolEternalStorage.sol ├── FlexibleStorage.sol ├── FuturesMarketData.sol ├── FuturesMarketManager.sol ├── FuturesMarketSettings.sol ├── ImmutableReadProxy.sol ├── ImportableRewardEscrowV2.sol ├── Issuer.sol ├── LimitedSetup.sol ├── Liquidator.sol ├── LiquidatorRewards.sol ├── Math.sol ├── MinimalProxyFactory.sol ├── MintableSynthetix.sol ├── MixinFuturesMarketSettings.sol ├── MixinPerpsV2MarketSettings.sol ├── MixinResolver.sol ├── MixinSystemSettings.sol ├── MultiCollateralSynth.sol ├── NativeEtherWrapper.sol ├── OneNetAggregatorDebtRatio.sol ├── OneNetAggregatorIssuedSynths.sol ├── Owned.sol ├── OwnerRelayOnEthereum.sol ├── OwnerRelayOnOptimism.sol ├── Pausable.sol ├── PerpsV2ExchangeRate.sol ├── PerpsV2Market.sol ├── PerpsV2MarketBase.sol ├── PerpsV2MarketData.sol ├── PerpsV2MarketDelayedExecution.sol ├── PerpsV2MarketDelayedIntent.sol ├── PerpsV2MarketLiquidate.sol ├── PerpsV2MarketProxyable.sol ├── PerpsV2MarketSettings.sol ├── PerpsV2MarketState.sol ├── PerpsV2MarketStateLegacyR1.sol ├── PerpsV2MarketViews.sol ├── Proxy.sol ├── ProxyERC20.sol ├── ProxyPerpsV2.sol ├── Proxyable.sol ├── PurgeableSynth.sol ├── ReadProxy.sol ├── RewardEscrow.sol ├── RewardEscrowV2.sol ├── RewardEscrowV2Frozen │ ├── BaseRewardEscrowV2Frozen.sol │ ├── IRewardEscrowV2Frozen.sol │ ├── ImportableRewardEscrowV2Frozen.sol │ └── RewardEscrowV2Frozen.sol ├── RewardEscrowV2Storage.sol ├── RewardsDistribution.sol ├── RewardsDistributionRecipient.sol ├── SafeCast.sol ├── SafeDecimalMath.sol ├── ShortingRewards.sol ├── SignedSafeDecimalMath.sol ├── SignedSafeMath.sol ├── StakingRewards.sol ├── State.sol ├── StateShared.sol ├── SupplySchedule.sol ├── Synth.sol ├── SynthRedeemer.sol ├── SynthUtil.sol ├── Synthetix.sol ├── SynthetixBridgeEscrow.sol ├── SynthetixBridgeToBase.sol ├── SynthetixBridgeToOptimism.sol ├── SynthetixDebtShare.sol ├── SynthetixEscrow.sol ├── SystemSettings.sol ├── SystemSettingsLib.sol ├── SystemStatus.sol ├── TemporarilyOwned.sol ├── TokenState.sol ├── TradingRewards.sol ├── VirtualSynth.sol ├── VirtualSynthMastercopy.sol ├── Wrapper.sol ├── WrapperFactory.sol ├── frozen │ ├── FuturesMarket.sol │ ├── FuturesMarketBase.sol │ ├── MixinFuturesNextPriceOrders.sol │ └── MixinFuturesViews.sol ├── interfaces │ ├── .solhint.json │ ├── AggregatorV2V3Interface.sol │ ├── IAddressResolver.sol │ ├── IBaseSynthetixBridge.sol │ ├── ICircuitBreaker.sol │ ├── ICollateralErc20.sol │ ├── ICollateralEth.sol │ ├── ICollateralLoan.sol │ ├── ICollateralManager.sol │ ├── ICollateralUtil.sol │ ├── IDebtCache.sol │ ├── IDebtMigrator.sol │ ├── IDelegateApprovals.sol │ ├── IDepot.sol │ ├── IDexPriceAggregator.sol │ ├── IDirectIntegrationManager.sol │ ├── IDynamicSynthRedeemer.sol │ ├── IERC20.sol │ ├── IEtherWrapper.sol │ ├── IExchangeCircuitBreaker.sol │ ├── IExchangeRates.sol │ ├── IExchangeState.sol │ ├── IExchanger.sol │ ├── IFeePool.sol │ ├── IFlexibleStorage.sol │ ├── IFuturesMarket.sol │ ├── IFuturesMarketBaseTypes.sol │ ├── IFuturesMarketManager.sol │ ├── IFuturesMarketSettings.sol │ ├── IHasBalance.sol │ ├── IIssuer.sol │ ├── ILiquidator.sol │ ├── ILiquidatorRewards.sol │ ├── IOwnerRelayOnOptimism.sol │ ├── IPerpsV2ExchangeRate.sol │ ├── IPerpsV2Market.sol │ ├── IPerpsV2MarketBaseTypes.sol │ ├── IPerpsV2MarketBaseTypesLegacyR1.sol │ ├── IPerpsV2MarketConsolidated.sol │ ├── IPerpsV2MarketDelayedExecution.sol │ ├── IPerpsV2MarketDelayedIntent.sol │ ├── IPerpsV2MarketLiquidate.sol │ ├── IPerpsV2MarketSettings.sol │ ├── IPerpsV2MarketState.sol │ ├── IPerpsV2MarketViews.sol │ ├── IPyth.sol │ ├── IRewardEscrow.sol │ ├── IRewardEscrowV2.sol │ ├── IRewardsDistribution.sol │ ├── IShortingRewards.sol │ ├── IStakingRewards.sol │ ├── ISupplySchedule.sol │ ├── ISynth.sol │ ├── ISynthRedeemer.sol │ ├── ISynthetix.sol │ ├── ISynthetixBridgeEscrow.sol │ ├── ISynthetixBridgeToBase.sol │ ├── ISynthetixBridgeToOptimism.sol │ ├── ISynthetixDebtShare.sol │ ├── ISynthetixState.sol │ ├── ISystemSettings.sol │ ├── ISystemStatus.sol │ ├── ITradingRewards.sol │ ├── IVirtualSynth.sol │ ├── IWETH.sol │ ├── IWrapper.sol │ ├── IWrapperFactory.sol │ └── PythStructs.sol ├── legacy │ ├── FeePoolState.sol │ ├── LegacyOwned.sol │ ├── LegacyTokenState.sol │ ├── OneNetAggregatorsDEFI.sol │ └── SynthetixState.sol ├── migrations │ ├── Migration_Acrab.sol │ ├── Migration_AcrabOptimism.sol │ ├── Migration_AcrabOptimismPatch1.sol │ ├── Migration_AcrabPatch1.sol │ ├── Migration_Aljanah.sol │ ├── Migration_AljanahOptimism.sol │ ├── Migration_Han.sol │ ├── Migration_HanOptimism.sol │ └── StakingRewardUpdater.sol └── test-helpers │ ├── FakeTradingRewards.sol │ ├── GenericMock.sol │ ├── MockAggregatorV2V3.sol │ ├── MockContractStorage.sol │ ├── MockDexPriceAggregator.sol │ ├── MockEtherWrapper.sol │ ├── MockExchanger.sol │ ├── MockFlagsInterface.sol │ ├── MockFuturesMarket.sol │ ├── MockMigration.sol │ ├── MockMintableSynthetix.sol │ ├── MockMutator.sol │ ├── MockPayable.sol │ ├── MockPerpsV2Market.sol │ ├── MockPerpsV2StateConsumer.sol │ ├── MockPyth.sol │ ├── MockReverter.sol │ ├── MockRewardsRecipient.sol │ ├── MockSynth.sol │ ├── MockThirdPartyExchangeContract.sol │ ├── MockToken.sol │ ├── MockWETH.sol │ ├── MockWrapperFactory.sol │ ├── OneWeekSetup.sol │ ├── PublicEST.sol │ ├── PublicEST8Decimals.sol │ ├── PublicMath.sol │ ├── PublicSafeDecimalMath.sol │ ├── TestableAddressSet.sol │ ├── TestableAddressSetProxyable.sol │ ├── TestableBytes32Set.sol │ ├── TestableBytes32SetProxyable.sol │ ├── TestableDebtCache.sol │ ├── TestableDynamicFee.sol │ ├── TestableFuturesMarket.sol │ ├── TestableMinimalProxyFactory.sol │ ├── TestableMixinResolver.sol │ ├── TestablePausable.sol │ ├── TestablePerpsV2Market.sol │ ├── TestablePerpsV2MarketEmpty.sol │ ├── TestableProxyable.sol │ ├── TestableState.sol │ ├── TestableStateShared.sol │ ├── TestableTempOwned.sol │ ├── TokenExchanger.sol │ ├── UsingReadProxy.sol │ └── WETH.sol ├── examples ├── browser.html └── historical-state.js ├── funding.json ├── hardhat.config.js ├── hardhat ├── extensions │ └── extension-log.js ├── index.js ├── tasks │ ├── task-compile.js │ ├── task-describe.js │ ├── task-fund-local-accounts.js │ ├── task-interact.js │ ├── task-node.js │ ├── task-ops.js │ ├── task-simulate-migration.js │ ├── task-status │ │ ├── index.js │ │ └── statusActions.js │ ├── task-test-integration.js │ ├── task-test-merge-gas-reports.js │ └── task-test.js └── util │ ├── balances.js │ ├── collectContractBytecodes.js │ ├── describeSources.js │ └── optimizeIfRequired.js ├── hooks └── lint ├── index.js ├── output.txt ├── output_new.txt ├── package-lock.json ├── package.json ├── publish ├── README.md ├── assets.json ├── cannon.js ├── deployed │ ├── local-ovm │ │ ├── .gitignore │ │ ├── .npmignore │ │ ├── config.json │ │ ├── deployment.json │ │ ├── feeds.json │ │ ├── futures-markets.json │ │ ├── index.js │ │ ├── offchain-feeds.json │ │ ├── params.json │ │ ├── perpsv2-markets.json │ │ ├── rewards.json │ │ ├── shorting-rewards.json │ │ └── synths.json │ ├── local │ │ ├── .gitignore │ │ ├── config.json │ │ ├── deployment.json │ │ ├── feeds.json │ │ ├── futures-markets.json │ │ ├── index.js │ │ ├── offchain-feeds.json │ │ ├── params.json │ │ ├── perpsv2-markets.json │ │ ├── rewards.json │ │ ├── shorting-rewards.json │ │ └── synths.json │ ├── mainnet-ovm │ │ ├── config.json │ │ ├── deployment.json │ │ ├── feeds.json │ │ ├── futures-markets.json │ │ ├── index.js │ │ ├── offchain-feeds.json │ │ ├── owner-actions.json │ │ ├── params.json │ │ ├── perpsv2-markets.json │ │ ├── rewards.json │ │ ├── synths.json │ │ └── versions.json │ ├── mainnet │ │ ├── config.json │ │ ├── deployment.json │ │ ├── feeds.json │ │ ├── futures-markets.json │ │ ├── index.js │ │ ├── offchain-feeds.json │ │ ├── owner-actions.json │ │ ├── params.json │ │ ├── perpsv2-markets.json │ │ ├── rewards.json │ │ ├── shorting-rewards.json │ │ ├── synths.json │ │ └── versions.json │ ├── sepolia-ovm │ │ ├── config.json │ │ ├── deployment.json │ │ ├── feeds.json │ │ ├── futures-markets.json │ │ ├── index.js │ │ ├── offchain-feeds.json │ │ ├── owner-actions.json │ │ ├── params.json │ │ ├── perpsv2-markets.json │ │ ├── rewards.json │ │ ├── shorting-rewards.json │ │ ├── synths.json │ │ └── versions.json │ └── sepolia │ │ ├── config.json │ │ ├── deployment.json │ │ ├── feeds.json │ │ ├── futures-markets.json │ │ ├── index.js │ │ ├── offchain-feeds.json │ │ ├── owner-actions.json │ │ ├── params.json │ │ ├── perpsv2-markets.json │ │ ├── rewards.json │ │ ├── shorting-rewards.json │ │ ├── synths.json │ │ └── versions.json ├── index.js ├── non-upgradeable.json ├── releases.json └── src │ ├── Deployer.js │ ├── NonceManager.js │ ├── SafeBatchSubmitter.js │ ├── command-utils │ ├── contract.js │ ├── perps-v2-utils.js │ ├── safe-initializer.js │ └── transact.js │ ├── commands │ ├── .gitignore │ ├── build.js │ ├── check-settlement-owing.js │ ├── connect-bridge.js │ ├── deploy-migration.js │ ├── deploy-shorting-rewards.js │ ├── deploy-staking-rewards.js │ ├── deploy │ │ ├── add-synths-to-protocol.js │ │ ├── check-aggregator-prices.js │ │ ├── configure-futures.js │ │ ├── configure-legacy-settings.js │ │ ├── configure-loans.js │ │ ├── configure-offchain-price-feeds.js │ │ ├── configure-perpsv2.js │ │ ├── configure-reward-escrow.js │ │ ├── configure-standalone-price-feeds.js │ │ ├── configure-synths.js │ │ ├── configure-system-settings.js │ │ ├── deploy-core.js │ │ ├── deploy-dapp-utils.js │ │ ├── deploy-futures.js │ │ ├── deploy-loans.js │ │ ├── deploy-perpsv2.js │ │ ├── deploy-synths.js │ │ ├── generate-solidity-output.js │ │ ├── get-deploy-parameter-factory.js │ │ ├── import-addresses.js │ │ ├── import-excluded-debt.js │ │ ├── import-fee-periods.js │ │ ├── index.js │ │ ├── perform-safety-checks.js │ │ ├── rebuild-legacy-resolver-caches.js │ │ ├── rebuild-resolver-caches.js │ │ ├── system-and-parameter-check.js │ │ └── take-debt-snapshot-when-required.js │ ├── extract-staking-balances.js │ ├── finalize-release.js │ ├── initiate-liquidator-rewards.js │ ├── liquidator-rewards-restitution.js │ ├── migrate-debt-shares.js │ ├── nominate.js │ ├── owner.js │ ├── persist-tokens.js │ ├── prepare-deploy-detect-diff.js │ ├── prepare-deploy.js │ ├── purge-synths.js │ ├── release.js │ ├── remove-synths.js │ ├── replace-synths.js │ ├── settle.js │ ├── verify.js │ ├── versions-history.js │ └── versions-update.js │ ├── contract-overrides.js │ ├── contract-size.js │ ├── solidity-header.js │ ├── solidity.js │ └── util.js ├── safe.js ├── slither.config.json ├── test ├── contracts │ ├── AddressResolver.js │ ├── AddressSetLib.js │ ├── BaseMigration.spec.js │ ├── BaseSynthetix.js │ ├── BaseSynthetixBridge.unit.js │ ├── Bytes32SetLib.js │ ├── CircuitBreaker.js │ ├── ContractStorage.js │ ├── DappMaintenance.js │ ├── DebtCache.js │ ├── DebtMigratorOnEthereum.js │ ├── DebtMigratorOnOptimism.js │ ├── DelegateApprovals.js │ ├── DirectIntegrationManager.js │ ├── DynamicSynthRedeemer.js │ ├── FeePool.js │ ├── FeePoolEternalStorage.js │ ├── FlexibleStorage.js │ ├── FuturesMarketManager.js │ ├── ImportableRewardEscrowV2.js │ ├── Issuer.js │ ├── LimitedSetup.js │ ├── Liquidator.js │ ├── LiquidatorRewards.js │ ├── Math.js │ ├── MinimalProxyFactory.js │ ├── MintableSynthetix.spec.js │ ├── MintableSynthetix.unit.js │ ├── MixinResolver.js │ ├── MultiCollateralSynth.js │ ├── OneNetAggregator.js │ ├── Owned.js │ ├── Pausable.js │ ├── PerpsV2ExchangeRate.js │ ├── PerpsV2Market.delayedOrder.js │ ├── PerpsV2Market.js │ ├── PerpsV2Market.offchainDelayedOrder.js │ ├── PerpsV2MarketData.js │ ├── PerpsV2MarketManager.js │ ├── PerpsV2MarketSettings.js │ ├── PerpsV2MarketState.js │ ├── PerpsV2MarketState.linked.js │ ├── ProxyERC20.js │ ├── ProxyPerpsV2.js │ ├── PurgeableSynth.js │ ├── ReadProxy.js │ ├── RewardEscrow.js │ ├── RewardEscrowV2.js │ ├── RewardEscrowV2Storage.js │ ├── RewardsDistribution.js │ ├── RewardsIntegrationTests.js │ ├── SafeDecimalMath.js │ ├── StakingRewards.js │ ├── State.js │ ├── StateShared.js │ ├── SupplySchedule.js │ ├── Synth.js │ ├── SynthUtil.js │ ├── Synthetix.js │ ├── SynthetixBridgeEscrow.spec.js │ ├── SynthetixBridgeEscrow.unit.js │ ├── SynthetixBridgeToBase.spec.js │ ├── SynthetixBridgeToBase.unit.js │ ├── SynthetixBridgeToOptimism.spec.js │ ├── SynthetixBridgeToOptimism.unit.js │ ├── SynthetixDebtShare.js │ ├── SynthetixEscrow.js │ ├── SystemSettings.js │ ├── SystemStatus.js │ ├── TokenState.js │ ├── Wrapper.js │ ├── WrapperFactory.js │ ├── common.js │ ├── helpers.js │ └── setup.js ├── deployments │ └── index.js ├── dynamic-fee-calc.csv ├── etherscan │ ├── index.js │ └── spec.js ├── integration │ ├── README.md │ ├── abis │ │ └── WETH.json │ ├── behaviors │ │ ├── erc20.behavior.js │ │ ├── exchange.behavior.js │ │ ├── futures.behavior.js │ │ ├── liquidations.behavior.js │ │ ├── perpsV2.behavior.js │ │ ├── redeem.behavior.js │ │ ├── redeem.dynamic.behavior.js │ │ ├── rewardEscrow.behavior.js │ │ ├── short.behavior.js │ │ ├── stake.behavior.js │ │ └── wrap.behavior.js │ ├── dual │ │ ├── _synthTransfer.integration.js │ │ ├── closeFeePeriod.integration.js │ │ ├── debtMigration.integration.js │ │ ├── deposit.integration.js │ │ ├── depositAndMigrateEscrow.integration.js │ │ ├── depositReward.integration.js │ │ ├── depositTo.integration.js │ │ ├── inflationDiversion.integration.js │ │ ├── migrateEscrow.integration.js │ │ ├── relay.integration.js │ │ ├── relayBatch.integration.js │ │ ├── staking.integration.js │ │ ├── withdraw.integration.js │ │ └── withdrawTo.integration.js │ ├── l1 │ │ ├── Liquidations.l1.integrations.js │ │ ├── Redemption.Dynamic.l1.integration.js │ │ ├── Redemption.l1.integration.js │ │ ├── RewardEscrow.l1.integration.js │ │ ├── Shorts.l1.integration.js │ │ ├── Synthetix.l1.integration.js │ │ ├── SynthsUSD.l1.integration.js │ │ └── WrapperFactory.l1.integration.js │ ├── l2 │ │ ├── Futures.l2.integration.js │ │ ├── Liquidations.l2.integration.js │ │ ├── PerpsV2.l2.integration.js │ │ ├── Redemption.Dynamic.l2.integration.js │ │ ├── Redemption.l2.integration.js │ │ ├── RewardEscrow.l2.integration.js │ │ ├── Shorts.l2.integration.js │ │ ├── Synthetix.l2.integration.js │ │ ├── SynthsUSD.l2.integration.js │ │ ├── WrapperFactory.l2.integration.js │ │ └── directRelay.l2.integration.js │ └── utils │ │ ├── approve.js │ │ ├── balances.js │ │ ├── bootstrap.js │ │ ├── contracts.js │ │ ├── deploy.js │ │ ├── escrow.js │ │ ├── exchanging.js │ │ ├── gas.js │ │ ├── issuance.js │ │ ├── l2.js │ │ ├── loans.js │ │ ├── optimism-temp.js │ │ ├── optimism.js │ │ ├── owned.js │ │ ├── rates.js │ │ ├── rpc.js │ │ ├── settings.js │ │ ├── skip.js │ │ ├── staking.js │ │ ├── status.js │ │ ├── users.js │ │ └── wait.js ├── legacy │ ├── BaseRewardEscrowV2.js │ ├── Collateral.js │ ├── CollateralErc20.js │ ├── CollateralEth.js │ ├── CollateralManager.js │ ├── CollateralShort.js │ ├── CollateralUtil.js │ ├── Depot.js │ ├── DynamicFee.js │ ├── EternalStorage.js │ ├── EtherWrapper.js │ ├── ExchangeCircuitBreaker.js │ ├── ExchangeRates.js │ ├── ExchangeState.js │ ├── Exchanger.spec.js │ ├── ExchangerWithFeeRecAlternatives.behaviors.js │ ├── ExchangerWithFeeRecAlternatives.unit.js │ ├── ExternStateToken.js │ ├── FuturesMarket.js │ ├── FuturesMarket.nextPrice.js │ ├── FuturesMarketData.js │ ├── FuturesMarketSettings.js │ ├── NativeEtherWrapper.js │ ├── OwnerRelayOnEthereum.js │ ├── OwnerRelayOnOptimism.js │ ├── ShortingRewards.js │ ├── SynthRedeemer.unit.js │ ├── TemporarilyOwned.js │ ├── TradingRewards.behaviors.js │ ├── TradingRewards.helper.js │ ├── TradingRewards.spec.js │ ├── TradingRewards.unit.js │ ├── VirtualSynth.behaviors.js │ ├── VirtualSynth.unit.js │ └── VirtualSynthMastercopy.unit.js ├── publish │ ├── index.js │ └── test.log ├── test-utils │ ├── rpc.js │ ├── wait.js │ └── wallets.js └── utils │ └── index.js └── webpack.config.js /.circleci/README.md: -------------------------------------------------------------------------------- 1 | Important: Do not edit ./circleci/config.yml directly, since it is a generated file. 2 | 3 | Instead, edit files under ./circleci/src and build with `npm run build:ci`, which builds the config file using Mustache. 4 | -------------------------------------------------------------------------------- /.circleci/config.template.yml: -------------------------------------------------------------------------------- 1 | # DO NOT EDIT MANUALLY! instead run `npm run build:ci` 2 | # autogenerated by `.circleci/pack.js` from contents of `jobs` .yml files 3 | version: 2.1 4 | orbs: 5 | rust: circleci/rust@1.6.0 6 | commands: 7 | {{> commands}} 8 | jobs: 9 | {{> jobs}} 10 | workflows: 11 | {{> workflows}} 12 | -------------------------------------------------------------------------------- /.circleci/src/commands/cmd-wait-for-port.yml: -------------------------------------------------------------------------------- 1 | # Wait until a connection is established with http://localhost:{port} 2 | parameters: 3 | port: 4 | type: integer 5 | steps: 6 | - run: 7 | shell: /bin/sh 8 | command: | 9 | wget --retry-connrefused --waitretry=1 --read-timeout=180 --timeout=180 -t 300 http://localhost:<> 10 | : 11 | -------------------------------------------------------------------------------- /.circleci/src/jobs/job-audit.yml: -------------------------------------------------------------------------------- 1 | # Bootstraps dependencies 2 | {{> job-header-sec-tools.yml}} 3 | steps: 4 | - checkout 5 | - run: 6 | name: Audit dependencies 7 | command: | 8 | npm audit --audit-level=critical 9 | - run: 10 | name: Lint lockfile 11 | command: | 12 | lockfile-lint -p package-lock.json --type npm --allowed-hosts npm --validate-https --empty-hostname false 13 | -------------------------------------------------------------------------------- /.circleci/src/jobs/job-fork-tests-ovm.yml: -------------------------------------------------------------------------------- 1 | # Starts a fork of OVM, deploys the latest release, and runs L2 integration tests 2 | {{> job-header-node.yml}} 3 | resource_class: large 4 | steps: 5 | - checkout 6 | - attach_workspace: 7 | at: . 8 | - run: 9 | command: npm run fork:ovm 10 | background: true 11 | - cmd-wait-for-port: 12 | port: 8545 13 | - run: 14 | name: Run integration tests on l2 15 | command: | 16 | # Only compile and deploy when there are new contracts 17 | NEW_CONTRACTS=$(node bin.js sips --layer=ovm --unreleased --with-sources) 18 | if [ -z "$NEW_CONTRACTS" ]; then 19 | npx hardhat test:integration:l2 --use-fork 20 | else 21 | npx hardhat test:integration:l2 --deploy --use-sips --use-fork --ignore-safety-checks 22 | fi; 23 | - store_test_results: 24 | path: /tmp/junit/ 25 | - store_artifacts: 26 | path: /tmp/junit/ 27 | -------------------------------------------------------------------------------- /.circleci/src/jobs/job-fork-tests.yml: -------------------------------------------------------------------------------- 1 | # Starts a fork of mainnet, deploys the latest release, and runs L1 integration tests 2 | {{> job-header-node.yml}} 3 | resource_class: large 4 | steps: 5 | - checkout 6 | - attach_workspace: 7 | at: . 8 | - run: 9 | command: npm run fork:mainnet 10 | background: true 11 | - cmd-wait-for-port: 12 | port: 9545 13 | - run: 14 | name: Run integration tests on l1 15 | command: | 16 | # Only compile and deploy when there are new contracts 17 | NEW_CONTRACTS=$(node bin.js sips --layer=base --unreleased --with-sources) 18 | if [ -z "$NEW_CONTRACTS" ]; then 19 | npx hardhat test:integration:l1 --use-fork --provider-port 9545 20 | else 21 | npx hardhat test:integration:l1 --deploy --use-sips --use-fork --provider-port 9545 22 | fi; 23 | - store_test_results: 24 | path: /tmp/junit/ 25 | - store_artifacts: 26 | path: /tmp/junit/ 27 | -------------------------------------------------------------------------------- /.circleci/src/jobs/job-lint.yml: -------------------------------------------------------------------------------- 1 | # Runs all linters 2 | {{> job-header-node.yml}} 3 | steps: 4 | - checkout 5 | - attach_workspace: 6 | at: . 7 | - run: npm run lint 8 | -------------------------------------------------------------------------------- /.circleci/src/jobs/job-pack-browser.yml: -------------------------------------------------------------------------------- 1 | # Packs js code for browser usage 2 | {{> job-header-node.yml}} 3 | steps: 4 | - checkout 5 | - attach_workspace: 6 | at: . 7 | - run: npm run pack 8 | - store_artifacts: 9 | path: browser.js 10 | -------------------------------------------------------------------------------- /.circleci/src/jobs/job-prepare.yml: -------------------------------------------------------------------------------- 1 | # Bootstraps dependencies 2 | {{> job-header-node.yml}} 3 | # set custom delimiter to avoid checksum parsing 4 | {{=<% %>=}} 5 | steps: 6 | - run: 7 | name: Set node & npm versions 8 | command: | 9 | echo $(node --version) > /tmp/node_version 10 | echo $(npm --version) > /tmp/npm_version 11 | - checkout 12 | - attach_workspace: 13 | at: . 14 | - restore_cache: 15 | key: dependencies-{{ checksum "/tmp/node_version" }}-v{{ checksum "/tmp/npm_version" }}-{{ checksum "package-lock.json" }} 16 | - run: 17 | name: Set custom npm cache directory 18 | command: npm config set cache .npm-cache --global 19 | - run: 20 | name: Install dependencies 21 | command: npm ci --prefer-offline --no-audit 22 | - save_cache: 23 | key: dependencies-{{ checksum "/tmp/node_version" }}-v{{ checksum "/tmp/npm_version" }}-{{ checksum "package-lock.json" }} 24 | paths: 25 | - .npm-cache 26 | - node_modules 27 | - persist_to_workspace: 28 | root: . 29 | paths: 30 | - .npm-cache 31 | - node_modules 32 | -------------------------------------------------------------------------------- /.circleci/src/jobs/job-simulate-release.yml: -------------------------------------------------------------------------------- 1 | # Starts a fork of mainnet, deploys the latest release, and runs L1 integration tests 2 | {{> job-header-node.yml}} 3 | steps: 4 | - checkout 5 | - attach_workspace: 6 | at: . 7 | - run: 8 | command: npm run fork -- --target-network mainnet --port 8545 9 | background: true 10 | - cmd-wait-for-port: 11 | port: 8545 12 | - run: 13 | name: Simulate release on L1 fork 14 | command: | 15 | # Only compile and deploy when there are new contracts 16 | UPCOMING_RELEASE=$(node bin.js releases --layer=base --unreleased --with-sources --name-only) 17 | if [ ! -z "$UPCOMING_RELEASE" ]; then 18 | npx hardhat simulate:migration --generate --test 19 | fi; 20 | - store_test_results: 21 | path: /tmp/junit/ 22 | - store_artifacts: 23 | path: /tmp/junit/ 24 | -------------------------------------------------------------------------------- /.circleci/src/jobs/job-static-analysis.yml: -------------------------------------------------------------------------------- 1 | # Runs all static analysis checks 2 | {{> job-header-node.yml}} 3 | steps: 4 | - checkout 5 | - attach_workspace: 6 | at: . 7 | - run: 8 | name: Show Slither output 9 | # ignore slither error codes 10 | command: | 11 | set +e 12 | slither . --disable-color 2>&1 | tee slitherReport.txt 13 | exit 0 14 | - store_artifacts: 15 | path: slitherReport.txt 16 | destination: slitherReport.txt 17 | 18 | -------------------------------------------------------------------------------- /.circleci/src/jobs/job-test-deploy-script.yml: -------------------------------------------------------------------------------- 1 | # Validates that the deploy command is working as expected 2 | {{> job-header-machine.yml}} 3 | resource_class: large 4 | steps: 5 | # get foundry 6 | - restore_cache: 7 | keys: 8 | - foundry-bin-latest-${foundry_cache_version} 9 | - rust/install: {} 10 | - run: 11 | name: "Install Foundry" 12 | working_directory: ~/ 13 | environment: 14 | SHELL: /bin/bash 15 | command: |- 16 | export PATH="$PATH:$HOME/.foundry/bin" 17 | echo 'export PATH=$PATH:$HOME/.foundry/bin' >> $BASH_ENV 18 | 19 | if command -v anvil; then 20 | echo "Anvil already installed" 21 | anvil --version 22 | else 23 | curl -L https://foundry.paradigm.xyz | bash 24 | foundryup 25 | fi 26 | rm -rf * 27 | 28 | - save_cache: 29 | key: foundry-bin-latest-${foundry_cache_version} 30 | paths: 31 | - ~/.foundry/bin 32 | 33 | - checkout 34 | - attach_workspace: 35 | at: . 36 | - run: 37 | name: Test and output logs 38 | command: | 39 | # Only compile and deploy when there are new contracts 40 | UPCOMING_RELEASE=$(node bin.js releases --layer=base --unreleased --with-sources --name-only) 41 | if [ ! -z "$UPCOMING_RELEASE" ]; then 42 | set +e 43 | npm run test:publish 44 | EXIT_CODE=$? 45 | if [ $EXIT_CODE -gt 0 ]; then 46 | tail -n 2000 test/publish/test.log; # show tail of logs here if test failed 47 | fi 48 | npx ansi-to-html --newline --bg black test/publish/test.log > test/publish/test-log.html 49 | exit $EXIT_CODE 50 | fi; 51 | - store_artifacts: 52 | path: test/publish/test-log.html 53 | destination: test-log.html 54 | -------------------------------------------------------------------------------- /.circleci/src/jobs/job-unit-tests-coverage-report.yml: -------------------------------------------------------------------------------- 1 | # Measures unit and spec test coverage 2 | {{> job-header-sec-tools.yml}} 3 | steps: 4 | - checkout 5 | - attach_workspace: 6 | at: /tmp/coverage 7 | - run: 8 | name: Upload coverage 9 | command: | 10 | cp -R /tmp/coverage/coverage-*.json . 11 | codecov -t $CODECOV_TOKEN 12 | -------------------------------------------------------------------------------- /.circleci/src/jobs/job-unit-tests-coverage.yml: -------------------------------------------------------------------------------- 1 | # Measures unit and spec test coverage 2 | {{> job-header-node.yml}} 3 | resource_class: large 4 | parallelism: 8 5 | steps: 6 | - checkout 7 | - attach_workspace: 8 | at: . 9 | - run: 10 | name: Create shared coverage outputs folder 11 | command: mkdir -p /tmp/coverage 12 | - run: 13 | name: Coverage 14 | command: | 15 | TEST_FILES="{$(circleci tests glob "test/contracts/*.js" | \ 16 | circleci tests split --split-by=timings | xargs | sed -e 's/ /,/g')}" 17 | npm run coverage -- --testfiles "$TEST_FILES" 18 | - run: 19 | name: Save coverage 20 | command: | 21 | cp coverage.json /tmp/coverage/coverage-$CIRCLE_NODE_INDEX.json 22 | - persist_to_workspace: 23 | root: /tmp/coverage 24 | paths: 25 | - coverage-*.json 26 | -------------------------------------------------------------------------------- /.circleci/src/jobs/job-unit-tests-gas-report.yml: -------------------------------------------------------------------------------- 1 | # Measures deployment and transaction gas usage in unit tests 2 | {{> job-header-node.yml}} 3 | steps: 4 | - checkout 5 | - attach_workspace: 6 | at: . 7 | - run: 8 | name: Upload gas reports 9 | command: | 10 | npx hardhat test:merge-gas-reports gasReporterOutput-*.json 11 | # required for codechecks 12 | if [ "${CIRCLE_BRANCH}" != "master" ]; then 13 | git branch -f master origin/master 14 | fi 15 | npx codechecks codechecks.unit.yml 16 | - store_artifacts: 17 | path: gasReporterOutput.json 18 | -------------------------------------------------------------------------------- /.circleci/src/jobs/job-unit-tests.yml: -------------------------------------------------------------------------------- 1 | # Runs all unit and spec tests 2 | {{> job-header-node.yml}} 3 | resource_class: large 4 | parallelism: 8 5 | steps: 6 | - checkout 7 | - attach_workspace: 8 | at: . 9 | - run: npx hardhat compile --showsize --optimizer 10 | - run: 11 | name: Test and output gas used 12 | command: | 13 | set +e 14 | circleci tests glob 'test/contracts/*.js' | 15 | circleci tests split | 16 | xargs npm test -- --gas 17 | EXIT_CODE=$? 18 | printf "\\n" 19 | exit $EXIT_CODE 20 | - run: 21 | name: Save gas report 22 | command: | 23 | mv gasReporterOutput.json ./gasReporterOutput-$CIRCLE_NODE_INDEX.json 24 | - persist_to_workspace: 25 | root: . 26 | paths: 27 | - gasReporterOutput-*.json 28 | - store_test_results: 29 | path: /tmp/junit/ 30 | - store_artifacts: 31 | path: /tmp/junit/ 32 | -------------------------------------------------------------------------------- /.circleci/src/jobs/job-validate-deployments.yml: -------------------------------------------------------------------------------- 1 | # Validates deployment json data against on-chain data 2 | {{> job-header-node.yml}} 3 | steps: 4 | - checkout 5 | - attach_workspace: 6 | at: . 7 | - run: 8 | name: Only run when publish/deployed/*/deployment.json changes 9 | command: | 10 | changes=$(git diff --name-status origin/develop | grep 'publish\/deployed\/[a-z0-9\-]*\/deployment\.json$' || true) 11 | if [ -z "$changes" ]; then 12 | circleci-agent step halt 13 | fi; 14 | - run: npm run test:deployments 15 | -------------------------------------------------------------------------------- /.circleci/src/jobs/job-validate-etherscan.yml: -------------------------------------------------------------------------------- 1 | # Validates that sources have been verified in etherscan 2 | {{> job-header-node.yml}} 3 | parameters: 4 | network: 5 | type: string 6 | steps: 7 | - checkout 8 | - attach_workspace: 9 | at: . 10 | - run: npm run test:etherscan -- --network << parameters.network >> 11 | -------------------------------------------------------------------------------- /.circleci/src/snippets/job-header-machine.yml: -------------------------------------------------------------------------------- 1 | working_directory: ~/repo 2 | machine: 3 | image: ubuntu-2204:current 4 | docker_layer_caching: true 5 | environment: 6 | foundry_cache_version: "1" 7 | -------------------------------------------------------------------------------- /.circleci/src/snippets/job-header-node.yml: -------------------------------------------------------------------------------- 1 | working_directory: ~/repo 2 | docker: 3 | - image: synthetixio/docker-node:18.19-ubuntu 4 | -------------------------------------------------------------------------------- /.circleci/src/snippets/job-header-sec-tools.yml: -------------------------------------------------------------------------------- 1 | working_directory: ~/repo 2 | docker: 3 | - image: synthetixio/docker-sec-tools:18.19-ubuntu 4 | -------------------------------------------------------------------------------- /.circleci/src/snippets/require-audit.yml: -------------------------------------------------------------------------------- 1 | requires: 2 | - job-audit 3 | -------------------------------------------------------------------------------- /.circleci/src/snippets/require-cannon.yml: -------------------------------------------------------------------------------- 1 | requires: 2 | - job-cannon 3 | -------------------------------------------------------------------------------- /.circleci/src/snippets/require-prepare.yml: -------------------------------------------------------------------------------- 1 | requires: 2 | - job-prepare 3 | -------------------------------------------------------------------------------- /.circleci/src/snippets/require-unit-tests-coverage.yml: -------------------------------------------------------------------------------- 1 | requires: 2 | - job-prepare 3 | - job-unit-tests-coverage 4 | -------------------------------------------------------------------------------- /.circleci/src/snippets/require-unit-tests.yml: -------------------------------------------------------------------------------- 1 | requires: 2 | - job-prepare 3 | - job-unit-tests 4 | -------------------------------------------------------------------------------- /.env.example: -------------------------------------------------------------------------------- 1 | ETHERSCAN_KEY=SomeEtherscanKey 2 | OVM_ETHERSCAN_KEY=SomeEtherscanKey 3 | PROVIDER_URL=https://network.infura.io/v3/SomeInfuraKey (runtime replaces "network") 4 | PROVIDER_URL_MAINNET=https://mainnet.infura.io/v3/SomeInfuraKey 5 | DEPLOY_PRIVATE_KEY=SomeEthereumPrivateKey (including 0x prefix) 6 | TESTNET_DEPLOY_PRIVATE_KEY=SomeEthereumPrivateKey (including 0x prefix) 7 | CIRCLECI_TOKEN=Create one via https://app.circleci.com/settings/user/tokens 8 | PINATA_KEY= # used in persist-tokens to upload to IPFS 9 | PINATA_SECRET= # used in persist-tokens to upload to IPFS 10 | -------------------------------------------------------------------------------- /.eslintignore: -------------------------------------------------------------------------------- 1 | build/* 2 | coverage/* 3 | optimism/* 4 | browser.js 5 | -------------------------------------------------------------------------------- /.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | extends: ['standard', 'plugin:prettier/recommended', 'plugin:node/recommended'], 3 | parserOptions: { 4 | ecmaVersion: 2020, 5 | }, 6 | globals: {}, 7 | env: { 8 | mocha: true, 9 | node: true, 10 | }, 11 | plugins: ['havven', 'no-only-tests'], 12 | rules: { 13 | 'havven/no-assert-revert-without-await': 'error', 14 | 'havven/no-assert-invalid-opcode-without-await': 'error', 15 | 'prefer-arrow-callback': 'error', 16 | 'prefer-const': 'error', 17 | 'no-process-exit': 'off', 18 | 'standard/computed-property-even-spacing': 'off', 19 | 'no-only-tests/no-only-tests': 'error', 20 | }, 21 | }; 22 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | *.sol linguist-language=Solidity 2 | test/* linguist-detectable=false 3 | -------------------------------------------------------------------------------- /.github/workflows/codeql.yml: -------------------------------------------------------------------------------- 1 | name: CodeQL 2 | 3 | on: 4 | push: 5 | branches: [master, develop] 6 | pull_request: 7 | branches: [master, develop] 8 | paths-ignore: 9 | - node_modules 10 | - "**/*.md" 11 | - "**/*.txt" 12 | schedule: 13 | - cron: "0 6 * * 3" 14 | 15 | jobs: 16 | analyze: 17 | runs-on: ubuntu-latest 18 | 19 | steps: 20 | - name: Checkout repository 21 | uses: actions/checkout@ec3a7ce113134d7a93b817d10a8272cb61118579 # pin@v2 22 | 23 | - name: Initialize CodeQL 24 | uses: github/codeql-action/init@81bfc289f5947eca8a3358341c874cb4f4697b64 # pin@codeql-bundle-20220322 25 | with: 26 | queries: security-and-quality 27 | languages: javascript 28 | 29 | - name: Autobuild 30 | uses: github/codeql-action/autobuild@81bfc289f5947eca8a3358341c874cb4f4697b64 # pin@codeql-bundle-20220322 31 | 32 | - name: Perform CodeQL Analysis 33 | uses: github/codeql-action/analyze@81bfc289f5947eca8a3358341c874cb4f4697b64 # pin@codeql-bundle-20220322 34 | -------------------------------------------------------------------------------- /.github/workflows/slither-analysis.yml: -------------------------------------------------------------------------------- 1 | # based on this thread https://github.com/crytic/slither/issues/948#issuecomment-925506993 2 | name: Slither 3 | 4 | on: 5 | push: 6 | pull_request: 7 | branches: [master, develop] 8 | 9 | jobs: 10 | slither: 11 | name: Slither Analysis 12 | # run only on master/develop branch and pull requests 13 | if: github.ref == 'refs/heads/master' || github.ref == 'refs/heads/develop' || github.event_name == 'pull_request' 14 | runs-on: ubuntu-latest 15 | 16 | container: 17 | image: synthetixio/docker-sec-tools:18.19-ubuntu 18 | 19 | steps: 20 | - name: Checkout 21 | uses: actions/checkout@2541b1294d2704b0964813337f33b291d3f8596b # pin@v3.0.2 22 | 23 | - name: Set npm cache directory 24 | run: npm config set cache .npm-cache --global 25 | 26 | - name: Get npm cache directory 27 | id: npm-cache-dir 28 | run: echo "::set-output name=dir::$(npm config get cache)" 29 | 30 | - name: Get node version 31 | id: node-version 32 | run: echo "::set-output name=version::$(node --version)" 33 | 34 | - uses: actions/cache@c3f1317a9e7b1ef106c153ac8c0f00fed3ddbc0d # pin@v3.0.4 35 | with: 36 | path: ${{ steps.npm-cache-dir.outputs.dir }} 37 | key: ${{ runner.os }}-ubuntu-${{ steps.node-version.outputs.version }}-${{ hashFiles('**/package-lock.json') }} 38 | restore-keys: | 39 | ${{ runner.os }}-ubuntu-${{ steps.node-version.outputs.version }}- 40 | 41 | - name: Install dependencies 42 | run: npm ci --prefer-offline 43 | 44 | - name: Run slither 45 | run: slither . --sarif slither.sarif || true 46 | 47 | - name: Upload lint results 48 | if: always() 49 | uses: github/codeql-action/upload-sarif@81bfc289f5947eca8a3358341c874cb4f4697b64 # pin@codeql-bundle-20220322 50 | with: 51 | sarif_file: slither.sarif 52 | continue-on-error: true 53 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /**/__pycache__/* 2 | test_settings.py 3 | deploy_settings.py 4 | *.pyc 5 | 6 | # gitignore - Truffle proj 7 | .idea/ 8 | bin/ 9 | node_modules 10 | yarn-error.log 11 | 12 | # mkdocs 13 | site/ 14 | 15 | # Our environment settings 16 | .env 17 | 18 | # Build artifacts 19 | build*/ 20 | 21 | # For eth-gas-reporter in tests 22 | test-gas-used.log 23 | 24 | # vscode 25 | .vscode/ 26 | 27 | .DS_Store 28 | coverage.json 29 | coverage 30 | browser.js 31 | .coverage_* 32 | 33 | # CircleCI local artifacts 34 | process.yml 35 | 36 | # Temp files 37 | .tmp/ 38 | 39 | # CSV files 40 | *.csv 41 | 42 | .db 43 | 44 | optimism 45 | 46 | # python venv 47 | .venv/ 48 | 49 | # sarif files 50 | slither.sarif 51 | 52 | .npm-cache 53 | 54 | # cannon build files 55 | cannon/ 56 | deployments/ 57 | -------------------------------------------------------------------------------- /.npmrc: -------------------------------------------------------------------------------- 1 | save-exact=false 2 | ignore-scripts=true 3 | -------------------------------------------------------------------------------- /.nvmrc: -------------------------------------------------------------------------------- 1 | 16 2 | -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | build 2 | .coverage_* 3 | coverage 4 | .circleci/src 5 | .circleci/config.template.yml 6 | -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "overrides": [ 3 | { 4 | "files": "*.sol", 5 | "options": { 6 | "printWidth": 125, 7 | "tabWidth": 4, 8 | "useTabs": false, 9 | "singleQuote": false, 10 | "bracketSpacing": false, 11 | "explicitTypes": "preserve" 12 | } 13 | }, 14 | { 15 | "files": ["*.js", "*.md"], 16 | "options": { 17 | "printWidth": 100, 18 | "semi": true, 19 | "singleQuote": true, 20 | "bracketSpacing": true, 21 | "trailingComma": "es5" 22 | } 23 | }, 24 | { 25 | "files": ["*.js", "*.json"], 26 | "options": { 27 | "useTabs": true 28 | } 29 | }, 30 | { 31 | "files": "*.md", 32 | "options": { 33 | "useTabs": false 34 | } 35 | } 36 | ] 37 | } 38 | -------------------------------------------------------------------------------- /.solcover.js: -------------------------------------------------------------------------------- 1 | const { 2 | constants: { inflationStartTimestampInSecs }, 3 | } = require('.'); 4 | 5 | module.exports = { 6 | port: 8545, 7 | skipFiles: [ 8 | 'legacy', 9 | 'migrations', 10 | 'test-helpers', 11 | 'BaseRewardEscrowV2', 12 | 'Collateral.sol', 13 | 'CollateralErc20.sol', 14 | 'CollateralEth.sol', 15 | 'CollateralShort.sol', 16 | 'CollateralUtil.sol', 17 | 'CollateralManager.sol', 18 | 'CollateralManagerState.sol', 19 | 'Depot.sol', 20 | 'EmptyEtherWrapper.sol', 21 | 'EscrowChecker.sol', 22 | 'EternalStorage.sol', 23 | 'EtherWrapper.sol', 24 | 'ExchangeRates.sol', 25 | 'ExchangeRatesWithDexPricing.sol', 26 | 'ExchangerWithFeeRecAlternatives', 27 | 'ExchangeSettlementLib.sol', 28 | 'ExchangeState.sol', 29 | 'ExternStateToken.sol', 30 | 'FuturesMarketBase.sol', 31 | 'FuturesMarketData.sol', 32 | 'FuturesMarketSettings.sol', 33 | 'MixinFuturesMarketSettings.sol', 34 | 'MixinFuturesNextPriceOrders.sol', 35 | 'MixinFuturesViews.sol', 36 | 'NativeEtherWrapper.sol', 37 | 'OwnerRelayOnEthereum.sol', 38 | 'OwnerRelayOnOptimism.sol', 39 | 'RewardEscrowV2Frozen', 40 | 'ShortingRewards.sol', 41 | 'SynthRedeemer.sol', 42 | 'TemporarilyOwned.sol', 43 | 'TradingRewards.sol', 44 | 'VirtualSynth.sol', 45 | 'VirtualSynthMastercopy.sol', 46 | ], 47 | providerOptions: { 48 | default_balance_ether: 10000000000000, // extra zero just in case (coverage consumes more gas) 49 | time: new Date(inflationStartTimestampInSecs * 1000), 50 | network_id: 55, 51 | }, 52 | mocha: { 53 | grep: '@cov-skip', // Find everything with this tag 54 | invert: true, // Run the grep's inverse set. 55 | timeout: 360e3, 56 | }, 57 | // Reduce instrumentation footprint - volume of solidity code 58 | // passed to compiler causes it to crash (See discussion PR #732) 59 | // Line and branch coverage will still be reported. 60 | measureStatementCoverage: false, 61 | }; 62 | -------------------------------------------------------------------------------- /.solhint.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": ["solhint:recommended"], 3 | "plugins": [], 4 | "rules": { 5 | "avoid-call-value": "off", 6 | "compiler-version": ["error", "^0.5.0"], 7 | "const-name-snakecase": "off", 8 | "func-order": "off", 9 | "func-param-name-mixedcase": "off", 10 | "imports-on-top": "off", 11 | "mark-callable-contracts": "off", 12 | "max-line-length": "off", 13 | "no-empty-blocks": "off", 14 | "no-inline-assembly": "off", 15 | "not-rely-on-time": "off", 16 | "no-unused-vars": "warn", 17 | "quotes": ["error", "double"], 18 | "reason-string": "off", 19 | "var-name-mixedcase": "off", 20 | "visibility-modifier-order": "off" 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 Synthetix 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /browser.js.LICENSE.txt: -------------------------------------------------------------------------------- 1 | /*! 2 | * The buffer module from node.js, for the browser. 3 | * 4 | * @author Feross Aboukhadijeh 5 | * @license MIT 6 | */ 7 | 8 | /*! ieee754. BSD-3-Clause License. Feross Aboukhadijeh */ 9 | 10 | /*! safe-buffer. MIT License. Feross Aboukhadijeh */ 11 | 12 | /** 13 | * [js-sha3]{@link https://github.com/emn178/js-sha3} 14 | * 15 | * @version 0.8.0 16 | * @author Chen, Yi-Cyuan [emn178@gmail.com] 17 | * @copyright Chen, Yi-Cyuan 2015-2018 18 | * @license MIT 19 | */ 20 | -------------------------------------------------------------------------------- /cannonfile.aggregator.toml: -------------------------------------------------------------------------------- 1 | name = "chainlink" 2 | version = "0.7-mock" 3 | description = "Deploys a testing aggregator with a given rate dated into the future" 4 | 5 | [setting.rate] 6 | defaultValue = "1000000000000000000" 7 | 8 | [setting.timestamp] 9 | # by default, its dated into the future 10 | defaultValue = "10000000000000" 11 | 12 | [setting.decimals] 13 | defaultValue = "6" 14 | 15 | [setting.salt] 16 | defaultValue = "default" 17 | 18 | [contract.aggregator] 19 | artifact = "MockAggregatorV2V3" 20 | salt = "<%= settings.salt %>" 21 | 22 | [invoke.set_decimals] 23 | target = ["aggregator"] 24 | func = "setDecimals" 25 | args = ["<%= settings.decimals %>"] 26 | depends = ["contract.aggregator"] 27 | 28 | [invoke.set_answer] 29 | target = ["aggregator"] 30 | 31 | func = "setLatestAnswer" 32 | args = ["<%= settings.rate %>", "<%= settings.timestamp %>"] 33 | 34 | depends = ["contract.aggregator"] 35 | -------------------------------------------------------------------------------- /cannonfile.release.toml: -------------------------------------------------------------------------------- 1 | name = "synthetix" 2 | description = "Infinite liquidity is here." 3 | version = "<%= package.version %>" 4 | 5 | # overrides the deployed contracts used by the deployer 6 | # not to be confused with the cannon network 7 | [setting.network] 8 | defaultValue = "sepolia" 9 | 10 | [run.synthetix] 11 | exec = "./publish/cannon.js" 12 | func = "deploy" 13 | args = ["<%= settings.network %>"] 14 | modified = ["contracts", "publish/src", "publish/deployed/local"] 15 | outputs = [] -------------------------------------------------------------------------------- /codechecks.unit.yml: -------------------------------------------------------------------------------- 1 | checks: 2 | - name: eth-gas-reporter/codechecks 3 | options: 4 | name: unit-test-gas-report-unoptimized 5 | settings: 6 | branches: 7 | - develop 8 | - master 9 | -------------------------------------------------------------------------------- /codecov.yml: -------------------------------------------------------------------------------- 1 | codecov: 2 | require_ci_to_pass: false 3 | bot: null 4 | -------------------------------------------------------------------------------- /contracts/BaseMigration.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.5.16; 2 | 3 | import "./Owned.sol"; 4 | 5 | contract BaseMigration is Owned { 6 | constructor(address _owner) internal Owned(_owner) {} 7 | 8 | // safety value to return ownership (anyone can invoke) 9 | function returnOwnership(address forContract) public { 10 | bytes memory payload = abi.encodeWithSignature("nominateNewOwner(address)", owner); 11 | 12 | // solhint-disable avoid-low-level-calls 13 | (bool success, ) = forContract.call(payload); 14 | 15 | if (!success) { 16 | // then try legacy way 17 | bytes memory legacyPayload = abi.encodeWithSignature("nominateOwner(address)", owner); 18 | 19 | // solhint-disable avoid-low-level-calls 20 | (bool legacySuccess, ) = forContract.call(legacyPayload); 21 | 22 | require(legacySuccess, "Legacy nomination failed"); 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /contracts/DappMaintenance.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.5.16; 2 | 3 | import "./Owned.sol"; 4 | 5 | // https://docs.synthetix.io/contracts/source/contracts/dappmaintenance 6 | 7 | /** 8 | * @title DappMaintenance contract. 9 | * @dev When the Synthetix system is on maintenance (upgrade, release...etc) the dApps also need 10 | * to be put on maintenance so no transactions can be done. The DappMaintenance contract is here to keep a state of 11 | * the dApps which indicates if yes or no, they should be up or down. 12 | */ 13 | contract DappMaintenance is Owned { 14 | bool public isPausedStaking = false; 15 | bool public isPausedSX = false; 16 | 17 | /** 18 | * @dev Constructor 19 | */ 20 | constructor(address _owner) public Owned(_owner) { 21 | require(_owner != address(0), "Owner address cannot be 0"); 22 | owner = _owner; 23 | emit OwnerChanged(address(0), _owner); 24 | } 25 | 26 | function setMaintenanceModeAll(bool isPaused) external onlyOwner { 27 | isPausedStaking = isPaused; 28 | isPausedSX = isPaused; 29 | emit StakingMaintenance(isPaused); 30 | emit SXMaintenance(isPaused); 31 | } 32 | 33 | function setMaintenanceModeStaking(bool isPaused) external onlyOwner { 34 | isPausedStaking = isPaused; 35 | emit StakingMaintenance(isPausedStaking); 36 | } 37 | 38 | function setMaintenanceModeSX(bool isPaused) external onlyOwner { 39 | isPausedSX = isPaused; 40 | emit SXMaintenance(isPausedSX); 41 | } 42 | 43 | event StakingMaintenance(bool isPaused); 44 | event SXMaintenance(bool isPaused); 45 | } 46 | -------------------------------------------------------------------------------- /contracts/EmptyEtherWrapper.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.5.16; 2 | 3 | // Stub functions required by the DebtCache and FeePool contracts. 4 | // https://docs.synthetix.io/contracts/source/contracts/etherwrapper 5 | contract EmptyEtherWrapper { 6 | constructor() public {} 7 | 8 | /* ========== VIEWS ========== */ 9 | 10 | function totalIssuedSynths() public view returns (uint) { 11 | return 0; 12 | } 13 | 14 | function distributeFees() external {} 15 | } 16 | -------------------------------------------------------------------------------- /contracts/EscrowChecker.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.5.16; 2 | 3 | interface ISynthetixEscrow { 4 | function numVestingEntries(address account) external view returns (uint); 5 | 6 | function getVestingScheduleEntry(address account, uint index) external view returns (uint[2] memory); 7 | } 8 | 9 | // https://docs.synthetix.io/contracts/source/contracts/escrowchecker 10 | contract EscrowChecker { 11 | ISynthetixEscrow public synthetix_escrow; 12 | 13 | constructor(ISynthetixEscrow _esc) public { 14 | synthetix_escrow = _esc; 15 | } 16 | 17 | function checkAccountSchedule(address account) public view returns (uint[16] memory) { 18 | uint[16] memory _result; 19 | uint schedules = synthetix_escrow.numVestingEntries(account); 20 | for (uint i = 0; i < schedules; i++) { 21 | uint[2] memory pair = synthetix_escrow.getVestingScheduleEntry(account, i); 22 | _result[i * 2] = pair[0]; 23 | _result[i * 2 + 1] = pair[1]; 24 | } 25 | return _result; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /contracts/FeePoolEternalStorage.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.5.16; 2 | 3 | // Inheritance 4 | import "./EternalStorage.sol"; 5 | import "./LimitedSetup.sol"; 6 | 7 | // https://docs.synthetix.io/contracts/source/contracts/feepooleternalstorage 8 | contract FeePoolEternalStorage is EternalStorage, LimitedSetup { 9 | bytes32 internal constant LAST_FEE_WITHDRAWAL = "last_fee_withdrawal"; 10 | 11 | constructor(address _owner, address _feePool) public EternalStorage(_owner, _feePool) LimitedSetup(6 weeks) {} 12 | 13 | function importFeeWithdrawalData(address[] calldata accounts, uint[] calldata feePeriodIDs) 14 | external 15 | onlyOwner 16 | onlyDuringSetup 17 | { 18 | require(accounts.length == feePeriodIDs.length, "Length mismatch"); 19 | 20 | for (uint8 i = 0; i < accounts.length; i++) { 21 | this.setUIntValue(keccak256(abi.encodePacked(LAST_FEE_WITHDRAWAL, accounts[i])), feePeriodIDs[i]); 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /contracts/ImmutableReadProxy.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.5.16; 2 | 3 | // solhint-disable payable-fallback 4 | 5 | /// a variant of ReadProxy.sol that's not Owned, and so has an immutable target 6 | /// that can be used e.g. to read a oracle feed, and provide its interface, but from a 7 | /// different address 8 | contract ImmutableReadProxy { 9 | address public target; 10 | 11 | constructor(address _target) public { 12 | target = _target; 13 | } 14 | 15 | function() external { 16 | // The basics of a proxy read call 17 | // Note that msg.sender in the underlying will always be the address of this contract. 18 | assembly { 19 | calldatacopy(0, 0, calldatasize) 20 | 21 | // Use of staticcall - this will revert if the underlying function mutates state 22 | let result := staticcall(gas, sload(target_slot), 0, calldatasize, 0, 0) 23 | returndatacopy(0, 0, returndatasize) 24 | 25 | if iszero(result) { 26 | revert(0, returndatasize) 27 | } 28 | return(0, returndatasize) 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /contracts/LimitedSetup.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.5.16; 2 | 3 | // https://docs.synthetix.io/contracts/source/contracts/limitedsetup 4 | contract LimitedSetup { 5 | uint public setupExpiryTime; 6 | 7 | /** 8 | * @dev LimitedSetup Constructor. 9 | * @param setupDuration The time the setup period will last for. 10 | */ 11 | constructor(uint setupDuration) internal { 12 | setupExpiryTime = now + setupDuration; 13 | } 14 | 15 | modifier onlyDuringSetup { 16 | require(now < setupExpiryTime, "Can only perform this action during setup"); 17 | _; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /contracts/Math.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.5.16; 2 | 3 | // Libraries 4 | import "./SafeDecimalMath.sol"; 5 | 6 | // https://docs.synthetix.io/contracts/source/libraries/math 7 | library Math { 8 | using SafeMath for uint; 9 | using SafeDecimalMath for uint; 10 | 11 | /** 12 | * @dev Uses "exponentiation by squaring" algorithm where cost is 0(logN) 13 | * vs 0(N) for naive repeated multiplication. 14 | * Calculates x^n with x as fixed-point and n as regular unsigned int. 15 | * Calculates to 18 digits of precision with SafeDecimalMath.unit() 16 | */ 17 | function powDecimal(uint x, uint n) internal pure returns (uint) { 18 | // https://mpark.github.io/programming/2014/08/18/exponentiation-by-squaring/ 19 | 20 | uint result = SafeDecimalMath.unit(); 21 | while (n > 0) { 22 | if (n % 2 != 0) { 23 | result = result.multiplyDecimal(x); 24 | } 25 | x = x.multiplyDecimal(x); 26 | n /= 2; 27 | } 28 | return result; 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /contracts/MinimalProxyFactory.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.5.16; 2 | 3 | // https://docs.synthetix.io/contracts/source/contracts/minimalproxyfactory 4 | contract MinimalProxyFactory { 5 | function _cloneAsMinimalProxy(address _base, string memory _revertMsg) internal returns (address clone) { 6 | bytes memory createData = _generateMinimalProxyCreateData(_base); 7 | 8 | assembly { 9 | clone := create( 10 | 0, // no value 11 | add(createData, 0x20), // data 12 | 55 // data is always 55 bytes (10 constructor + 45 code) 13 | ) 14 | } 15 | 16 | // If CREATE fails for some reason, address(0) is returned 17 | require(clone != address(0), _revertMsg); 18 | } 19 | 20 | function _generateMinimalProxyCreateData(address _base) internal pure returns (bytes memory) { 21 | return 22 | abi.encodePacked( 23 | //---- constructor ----- 24 | bytes10(0x3d602d80600a3d3981f3), 25 | //---- proxy code ----- 26 | bytes10(0x363d3d373d3d3d363d73), 27 | _base, 28 | bytes15(0x5af43d82803e903d91602b57fd5bf3) 29 | ); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /contracts/OneNetAggregatorDebtRatio.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.5.16; 2 | 3 | import "./BaseOneNetAggregator.sol"; 4 | 5 | contract OneNetAggregatorDebtRatio is BaseOneNetAggregator { 6 | bytes32 public constant CONTRACT_NAME = "OneNetAggregatorDebtRatio"; 7 | 8 | constructor(AddressResolver _resolver) public BaseOneNetAggregator(_resolver) {} 9 | 10 | function getRoundData(uint80) 11 | public 12 | view 13 | returns ( 14 | uint80, 15 | int256, 16 | uint256, 17 | uint256, 18 | uint80 19 | ) 20 | { 21 | uint totalIssuedSynths = 22 | IIssuer(resolver.requireAndGetAddress("Issuer", "aggregate debt info")).totalIssuedSynths("sUSD", true); 23 | uint totalDebtShares = 24 | ISynthetixDebtShare(resolver.requireAndGetAddress("SynthetixDebtShare", "aggregate debt info")).totalSupply(); 25 | 26 | uint result = 27 | totalDebtShares == 0 ? 10**27 : totalIssuedSynths.decimalToPreciseDecimal().divideDecimalRound(totalDebtShares); 28 | 29 | uint dataTimestamp = now; 30 | 31 | if (overrideTimestamp != 0) { 32 | dataTimestamp = overrideTimestamp; 33 | } 34 | 35 | return (1, int256(result), dataTimestamp, dataTimestamp, 1); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /contracts/OneNetAggregatorIssuedSynths.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.5.16; 2 | 3 | import "./BaseOneNetAggregator.sol"; 4 | 5 | contract OneNetAggregatorIssuedSynths is BaseOneNetAggregator { 6 | bytes32 public constant CONTRACT_NAME = "OneNetAggregatorIssuedSynths"; 7 | 8 | constructor(AddressResolver _resolver) public BaseOneNetAggregator(_resolver) {} 9 | 10 | function getRoundData(uint80) 11 | public 12 | view 13 | returns ( 14 | uint80, 15 | int256, 16 | uint256, 17 | uint256, 18 | uint80 19 | ) 20 | { 21 | uint totalIssuedSynths = 22 | IIssuer(resolver.requireAndGetAddress("Issuer", "aggregate debt info")).totalIssuedSynths("sUSD", true); 23 | 24 | uint dataTimestamp = now; 25 | 26 | if (overrideTimestamp != 0) { 27 | dataTimestamp = overrideTimestamp; 28 | } 29 | 30 | return (1, int256(totalIssuedSynths), dataTimestamp, dataTimestamp, 1); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /contracts/Owned.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.5.16; 2 | 3 | // https://docs.synthetix.io/contracts/source/contracts/owned 4 | contract Owned { 5 | address public owner; 6 | address public nominatedOwner; 7 | 8 | constructor(address _owner) public { 9 | require(_owner != address(0), "Owner address cannot be 0"); 10 | owner = _owner; 11 | emit OwnerChanged(address(0), _owner); 12 | } 13 | 14 | function nominateNewOwner(address _owner) external onlyOwner { 15 | nominatedOwner = _owner; 16 | emit OwnerNominated(_owner); 17 | } 18 | 19 | function acceptOwnership() external { 20 | require(msg.sender == nominatedOwner, "You must be nominated before you can accept ownership"); 21 | emit OwnerChanged(owner, nominatedOwner); 22 | owner = nominatedOwner; 23 | nominatedOwner = address(0); 24 | } 25 | 26 | modifier onlyOwner { 27 | _onlyOwner(); 28 | _; 29 | } 30 | 31 | function _onlyOwner() private view { 32 | require(msg.sender == owner, "Only the contract owner may perform this action"); 33 | } 34 | 35 | event OwnerNominated(address newOwner); 36 | event OwnerChanged(address oldOwner, address newOwner); 37 | } 38 | -------------------------------------------------------------------------------- /contracts/Pausable.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.5.16; 2 | 3 | // Inheritance 4 | import "./Owned.sol"; 5 | 6 | // https://docs.synthetix.io/contracts/source/contracts/pausable 7 | contract Pausable is Owned { 8 | uint public lastPauseTime; 9 | bool public paused; 10 | 11 | constructor() internal { 12 | // This contract is abstract, and thus cannot be instantiated directly 13 | require(owner != address(0), "Owner must be set"); 14 | // Paused will be false, and lastPauseTime will be 0 upon initialisation 15 | } 16 | 17 | /** 18 | * @notice Change the paused state of the contract 19 | * @dev Only the contract owner may call this. 20 | */ 21 | function setPaused(bool _paused) external onlyOwner { 22 | // Ensure we're actually changing the state before we do anything 23 | if (_paused == paused) { 24 | return; 25 | } 26 | 27 | // Set our paused state. 28 | paused = _paused; 29 | 30 | // If applicable, set the last pause time. 31 | if (paused) { 32 | lastPauseTime = now; 33 | } 34 | 35 | // Let everyone know that our pause state has changed. 36 | emit PauseChanged(paused); 37 | } 38 | 39 | event PauseChanged(bool isPaused); 40 | 41 | modifier notPaused { 42 | require(!paused, "This action cannot be performed while the contract is paused"); 43 | _; 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /contracts/ReadProxy.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.5.16; 2 | 3 | import "./Owned.sol"; 4 | 5 | // solhint-disable payable-fallback 6 | 7 | // https://docs.synthetix.io/contracts/source/contracts/readproxy 8 | contract ReadProxy is Owned { 9 | address public target; 10 | 11 | constructor(address _owner) public Owned(_owner) {} 12 | 13 | function setTarget(address _target) external onlyOwner { 14 | target = _target; 15 | emit TargetUpdated(target); 16 | } 17 | 18 | function() external { 19 | // The basics of a proxy read call 20 | // Note that msg.sender in the underlying will always be the address of this contract. 21 | assembly { 22 | calldatacopy(0, 0, calldatasize) 23 | 24 | // Use of staticcall - this will revert if the underlying function mutates state 25 | let result := staticcall(gas, sload(target_slot), 0, calldatasize, 0, 0) 26 | returndatacopy(0, 0, returndatasize) 27 | 28 | if iszero(result) { 29 | revert(0, returndatasize) 30 | } 31 | return(0, returndatasize) 32 | } 33 | } 34 | 35 | event TargetUpdated(address newTarget); 36 | } 37 | -------------------------------------------------------------------------------- /contracts/RewardsDistributionRecipient.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.5.16; 2 | 3 | // Inheritance 4 | import "./Owned.sol"; 5 | 6 | // https://docs.synthetix.io/contracts/source/contracts/rewardsdistributionrecipient 7 | contract RewardsDistributionRecipient is Owned { 8 | address public rewardsDistribution; 9 | 10 | function notifyRewardAmount(uint256 reward) external; 11 | 12 | modifier onlyRewardsDistribution() { 13 | require(msg.sender == rewardsDistribution, "Caller is not RewardsDistribution contract"); 14 | _; 15 | } 16 | 17 | function setRewardsDistribution(address _rewardsDistribution) external onlyOwner { 18 | rewardsDistribution = _rewardsDistribution; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /contracts/State.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.5.16; 2 | 3 | // Inheritance 4 | import "./Owned.sol"; 5 | 6 | // https://docs.synthetix.io/contracts/source/contracts/state 7 | contract State is Owned { 8 | // the address of the contract that can modify variables 9 | // this can only be changed by the owner of this contract 10 | address public associatedContract; 11 | 12 | constructor(address _associatedContract) internal { 13 | // This contract is abstract, and thus cannot be instantiated directly 14 | require(owner != address(0), "Owner must be set"); 15 | 16 | associatedContract = _associatedContract; 17 | emit AssociatedContractUpdated(_associatedContract); 18 | } 19 | 20 | /* ========== SETTERS ========== */ 21 | 22 | // Change the associated contract to a new address 23 | function setAssociatedContract(address _associatedContract) external onlyOwner { 24 | associatedContract = _associatedContract; 25 | emit AssociatedContractUpdated(_associatedContract); 26 | } 27 | 28 | /* ========== MODIFIERS ========== */ 29 | 30 | modifier onlyAssociatedContract { 31 | require(msg.sender == associatedContract, "Only the associated contract can perform this action"); 32 | _; 33 | } 34 | 35 | /* ========== EVENTS ========== */ 36 | 37 | event AssociatedContractUpdated(address associatedContract); 38 | } 39 | -------------------------------------------------------------------------------- /contracts/SynthetixBridgeEscrow.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.5.16; 2 | 3 | // Inheritance 4 | import "./Owned.sol"; 5 | import "./MixinResolver.sol"; 6 | import "./interfaces/ISynthetixBridgeEscrow.sol"; 7 | 8 | // Internal references. 9 | import "openzeppelin-solidity-2.3.0/contracts/token/ERC20/SafeERC20.sol"; 10 | 11 | contract SynthetixBridgeEscrow is Owned, ISynthetixBridgeEscrow { 12 | using SafeERC20 for IERC20; 13 | 14 | constructor(address _owner) public Owned(_owner) {} 15 | 16 | function approveBridge( 17 | address _token, 18 | address _bridge, 19 | uint256 _amount 20 | ) external onlyOwner { 21 | IERC20(_token).safeApprove(_bridge, _amount); 22 | emit BridgeApproval(_token, _bridge, _amount); 23 | } 24 | 25 | /* ========== EVENTS ========== */ 26 | event BridgeApproval(address _token, address indexed spender, uint value); 27 | } 28 | -------------------------------------------------------------------------------- /contracts/TemporarilyOwned.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.5.16; 2 | 3 | contract TemporarilyOwned { 4 | address public temporaryOwner; 5 | address public nominatedOwner; 6 | uint public expiryTime; 7 | 8 | constructor(address _temporaryOwner, uint _ownershipDuration) public { 9 | require(_temporaryOwner != address(0), "Temp owner address cannot be 0"); 10 | require(_ownershipDuration > 0, "Duration cannot be 0"); 11 | 12 | temporaryOwner = _temporaryOwner; 13 | expiryTime = block.timestamp + _ownershipDuration; 14 | } 15 | 16 | function setNewExpiryTime(uint _duration) external onlyTemporaryOwner { 17 | require(block.timestamp + _duration < expiryTime, "New expiry time must be sooner than it currently is"); 18 | expiryTime = block.timestamp + _duration; 19 | } 20 | 21 | function nominateNewOwner(address _owner) external onlyTemporaryOwner { 22 | nominatedOwner = _owner; 23 | emit OwnerNominated(_owner); 24 | } 25 | 26 | function acceptOwnership() external { 27 | require(block.timestamp < expiryTime, "Ownership expired"); 28 | require(msg.sender == nominatedOwner, "You must be nominated before you can accept ownership"); 29 | emit OwnerChanged(temporaryOwner, nominatedOwner); 30 | temporaryOwner = nominatedOwner; 31 | nominatedOwner = address(0); 32 | } 33 | 34 | modifier onlyTemporaryOwner { 35 | _onlyTemporaryOwner(); 36 | _; 37 | } 38 | 39 | function _onlyTemporaryOwner() private view { 40 | require(block.timestamp < expiryTime, "Ownership expired"); 41 | require(msg.sender == temporaryOwner, "Only executable by temp owner"); 42 | } 43 | 44 | event OwnerNominated(address newOwner); 45 | event OwnerChanged(address oldOwner, address newOwner); 46 | } 47 | -------------------------------------------------------------------------------- /contracts/TokenState.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.5.16; 2 | 3 | // Inheritance 4 | import "./Owned.sol"; 5 | import "./State.sol"; 6 | 7 | // https://docs.synthetix.io/contracts/source/contracts/tokenstate 8 | contract TokenState is Owned, State { 9 | /* ERC20 fields. */ 10 | mapping(address => uint) public balanceOf; 11 | mapping(address => mapping(address => uint)) public allowance; 12 | 13 | constructor(address _owner, address _associatedContract) public Owned(_owner) State(_associatedContract) {} 14 | 15 | /* ========== SETTERS ========== */ 16 | 17 | /** 18 | * @notice Set ERC20 allowance. 19 | * @dev Only the associated contract may call this. 20 | * @param tokenOwner The authorising party. 21 | * @param spender The authorised party. 22 | * @param value The total value the authorised party may spend on the 23 | * authorising party's behalf. 24 | */ 25 | function setAllowance( 26 | address tokenOwner, 27 | address spender, 28 | uint value 29 | ) external onlyAssociatedContract { 30 | allowance[tokenOwner][spender] = value; 31 | } 32 | 33 | /** 34 | * @notice Set the balance in a given account 35 | * @dev Only the associated contract may call this. 36 | * @param account The account whose value to set. 37 | * @param value The new balance of the given account. 38 | */ 39 | function setBalanceOf(address account, uint value) external onlyAssociatedContract { 40 | balanceOf[account] = value; 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /contracts/VirtualSynthMastercopy.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.5.16; 2 | 3 | import "./VirtualSynth.sol"; 4 | 5 | // https://docs.synthetix.io/contracts/source/contracts/virtualsynthmastercopy 6 | // Note: this is the "frozen" mastercopy of the VirtualSynth contract that should be linked to from 7 | // proxies. 8 | contract VirtualSynthMastercopy is VirtualSynth { 9 | constructor() public ERC20() { 10 | // Freeze mastercopy on deployment so it can never be initialized with real arguments 11 | initialized = true; 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /contracts/interfaces/.solhint.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": ["solhint:recommended"], 3 | "plugins": [], 4 | "rules": { 5 | "compiler-version": ["error", ">=0.4.24"] 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /contracts/interfaces/AggregatorV2V3Interface.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.5.16; 2 | 3 | //import "@chainlink/contracts-0.0.10/src/v0.5/interfaces/AggregatorV2V3Interface.sol"; 4 | 5 | interface AggregatorV2V3Interface { 6 | function latestRound() external view returns (uint256); 7 | 8 | function decimals() external view returns (uint8); 9 | 10 | function getAnswer(uint256 roundId) external view returns (int256); 11 | 12 | function getTimestamp(uint256 roundId) external view returns (uint256); 13 | 14 | function getRoundData(uint80 _roundId) 15 | external 16 | view 17 | returns ( 18 | uint80 roundId, 19 | int256 answer, 20 | uint256 startedAt, 21 | uint256 updatedAt, 22 | uint80 answeredInRound 23 | ); 24 | 25 | function latestRoundData() 26 | external 27 | view 28 | returns ( 29 | uint80 roundId, 30 | int256 answer, 31 | uint256 startedAt, 32 | uint256 updatedAt, 33 | uint80 answeredInRound 34 | ); 35 | } 36 | -------------------------------------------------------------------------------- /contracts/interfaces/IAddressResolver.sol: -------------------------------------------------------------------------------- 1 | pragma solidity >=0.4.24; 2 | 3 | // https://docs.synthetix.io/contracts/source/interfaces/iaddressresolver 4 | interface IAddressResolver { 5 | function getAddress(bytes32 name) external view returns (address); 6 | 7 | function getSynth(bytes32 key) external view returns (address); 8 | 9 | function requireAndGetAddress(bytes32 name, string calldata reason) external view returns (address); 10 | } 11 | -------------------------------------------------------------------------------- /contracts/interfaces/IBaseSynthetixBridge.sol: -------------------------------------------------------------------------------- 1 | pragma solidity >=0.4.24; 2 | pragma experimental ABIEncoderV2; 3 | 4 | interface IBaseSynthetixBridge { 5 | function suspendInitiation() external; 6 | 7 | function resumeInitiation() external; 8 | } 9 | -------------------------------------------------------------------------------- /contracts/interfaces/ICircuitBreaker.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.5.16; 2 | 3 | // https://docs.synthetix.io/contracts/source/interfaces/ICircuitBreaker 4 | interface ICircuitBreaker { 5 | // Views 6 | function isInvalid(address oracleAddress, uint value) external view returns (bool); 7 | 8 | function priceDeviationThresholdFactor() external view returns (uint); 9 | 10 | function isDeviationAboveThreshold(uint base, uint comparison) external view returns (bool); 11 | 12 | function lastValue(address oracleAddress) external view returns (uint); 13 | 14 | function circuitBroken(address oracleAddress) external view returns (bool); 15 | 16 | // Mutative functions 17 | function resetLastValue(address[] calldata oracleAddresses, uint[] calldata values) external; 18 | 19 | function probeCircuitBreaker(address oracleAddress, uint value) external returns (bool circuitBroken); 20 | } 21 | -------------------------------------------------------------------------------- /contracts/interfaces/ICollateralErc20.sol: -------------------------------------------------------------------------------- 1 | pragma solidity >=0.4.24; 2 | 3 | interface ICollateralErc20 { 4 | function open( 5 | uint collateral, 6 | uint amount, 7 | bytes32 currency 8 | ) external returns (uint id); 9 | 10 | function close(uint id) external returns (uint amount, uint collateral); 11 | 12 | function deposit( 13 | address borrower, 14 | uint id, 15 | uint amount 16 | ) external returns (uint principal, uint collateral); 17 | 18 | function withdraw(uint id, uint amount) external returns (uint principal, uint collateral); 19 | 20 | function repay( 21 | address borrower, 22 | uint id, 23 | uint amount 24 | ) external returns (uint principal, uint collateral); 25 | 26 | function draw(uint id, uint amount) external returns (uint principal, uint collateral); 27 | 28 | function liquidate( 29 | address borrower, 30 | uint id, 31 | uint amount 32 | ) external; 33 | } 34 | -------------------------------------------------------------------------------- /contracts/interfaces/ICollateralEth.sol: -------------------------------------------------------------------------------- 1 | pragma solidity >=0.4.24; 2 | 3 | interface ICollateralEth { 4 | function open(uint amount, bytes32 currency) external payable returns (uint id); 5 | 6 | function close(uint id) external returns (uint amount, uint collateral); 7 | 8 | function deposit(address borrower, uint id) external payable returns (uint principal, uint collateral); 9 | 10 | function withdraw(uint id, uint amount) external returns (uint principal, uint collateral); 11 | 12 | function repay( 13 | address borrower, 14 | uint id, 15 | uint amount 16 | ) external returns (uint principal, uint collateral); 17 | 18 | function draw(uint id, uint amount) external returns (uint principal, uint collateral); 19 | 20 | function liquidate( 21 | address borrower, 22 | uint id, 23 | uint amount 24 | ) external; 25 | 26 | function claim(uint amount) external; 27 | } 28 | -------------------------------------------------------------------------------- /contracts/interfaces/ICollateralLoan.sol: -------------------------------------------------------------------------------- 1 | pragma solidity >=0.4.24; 2 | 3 | pragma experimental ABIEncoderV2; 4 | 5 | interface ICollateralLoan { 6 | struct Loan { 7 | // ID for the loan 8 | uint id; 9 | // Acccount that created the loan 10 | address payable account; 11 | // Amount of collateral deposited 12 | uint collateral; 13 | // The synth that was borowed 14 | bytes32 currency; 15 | // Amount of synths borrowed 16 | uint amount; 17 | // Indicates if the position was short sold 18 | bool short; 19 | // interest amounts accrued 20 | uint accruedInterest; 21 | // last interest index 22 | uint interestIndex; 23 | // time of last interaction. 24 | uint lastInteraction; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /contracts/interfaces/ICollateralUtil.sol: -------------------------------------------------------------------------------- 1 | pragma solidity >=0.4.24; 2 | 3 | pragma experimental ABIEncoderV2; 4 | 5 | import "./ICollateralLoan.sol"; 6 | 7 | interface ICollateralUtil { 8 | function getCollateralRatio(ICollateralLoan.Loan calldata loan, bytes32 collateralKey) 9 | external 10 | view 11 | returns (uint cratio); 12 | 13 | function maxLoan( 14 | uint amount, 15 | bytes32 currency, 16 | uint minCratio, 17 | bytes32 collateralKey 18 | ) external view returns (uint max); 19 | 20 | function liquidationAmount( 21 | ICollateralLoan.Loan calldata loan, 22 | uint minCratio, 23 | bytes32 collateralKey 24 | ) external view returns (uint amount); 25 | 26 | function collateralRedeemed( 27 | bytes32 currency, 28 | uint amount, 29 | bytes32 collateralKey 30 | ) external view returns (uint collateral); 31 | } 32 | -------------------------------------------------------------------------------- /contracts/interfaces/IDebtMigrator.sol: -------------------------------------------------------------------------------- 1 | pragma solidity >=0.4.24; 2 | pragma experimental ABIEncoderV2; 3 | 4 | interface IDebtMigrator { 5 | function finalizeDebtMigration( 6 | address account, 7 | uint debtSharesMigrated, 8 | uint escrowMigrated, 9 | uint liquidSnxMigrated, 10 | bytes calldata debtPayload 11 | ) external; 12 | } 13 | -------------------------------------------------------------------------------- /contracts/interfaces/IDelegateApprovals.sol: -------------------------------------------------------------------------------- 1 | pragma solidity >=0.4.24; 2 | 3 | // https://docs.synthetix.io/contracts/source/interfaces/idelegateapprovals 4 | interface IDelegateApprovals { 5 | // Views 6 | function canBurnFor(address authoriser, address delegate) external view returns (bool); 7 | 8 | function canIssueFor(address authoriser, address delegate) external view returns (bool); 9 | 10 | function canClaimFor(address authoriser, address delegate) external view returns (bool); 11 | 12 | function canExchangeFor(address authoriser, address delegate) external view returns (bool); 13 | 14 | // Mutative 15 | function approveAllDelegatePowers(address delegate) external; 16 | 17 | function removeAllDelegatePowers(address delegate) external; 18 | 19 | function approveBurnOnBehalf(address delegate) external; 20 | 21 | function removeBurnOnBehalf(address delegate) external; 22 | 23 | function approveIssueOnBehalf(address delegate) external; 24 | 25 | function removeIssueOnBehalf(address delegate) external; 26 | 27 | function approveClaimOnBehalf(address delegate) external; 28 | 29 | function removeClaimOnBehalf(address delegate) external; 30 | 31 | function approveExchangeOnBehalf(address delegate) external; 32 | 33 | function removeExchangeOnBehalf(address delegate) external; 34 | } 35 | -------------------------------------------------------------------------------- /contracts/interfaces/IDepot.sol: -------------------------------------------------------------------------------- 1 | pragma solidity >=0.4.24; 2 | 3 | // https://docs.synthetix.io/contracts/source/interfaces/idepot 4 | interface IDepot { 5 | // Views 6 | function fundsWallet() external view returns (address payable); 7 | 8 | function maxEthPurchase() external view returns (uint); 9 | 10 | function minimumDepositAmount() external view returns (uint); 11 | 12 | function synthsReceivedForEther(uint amount) external view returns (uint); 13 | 14 | function totalSellableDeposits() external view returns (uint); 15 | 16 | // Mutative functions 17 | function depositSynths(uint amount) external; 18 | 19 | function exchangeEtherForSynths() external payable returns (uint); 20 | 21 | function exchangeEtherForSynthsAtRate(uint guaranteedRate) external payable returns (uint); 22 | 23 | function withdrawMyDepositedSynths() external; 24 | 25 | // Note: On mainnet no SNX has been deposited. The following functions are kept alive for testnet SNX faucets. 26 | function exchangeEtherForSNX() external payable returns (uint); 27 | 28 | function exchangeEtherForSNXAtRate(uint guaranteedRate, uint guaranteedSynthetixRate) external payable returns (uint); 29 | 30 | function exchangeSynthsForSNX(uint synthAmount) external returns (uint); 31 | 32 | function synthetixReceivedForEther(uint amount) external view returns (uint); 33 | 34 | function synthetixReceivedForSynths(uint amount) external view returns (uint); 35 | 36 | function withdrawSynthetix(uint amount) external; 37 | } 38 | -------------------------------------------------------------------------------- /contracts/interfaces/IDexPriceAggregator.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.5.16; 2 | 3 | // https://sips.synthetix.io/sips/sip-120/ 4 | // Uniswap V3 based DecPriceAggregator (unaudited) e.g. https://etherscan.io/address/0xf120f029ac143633d1942e48ae2dfa2036c5786c#code 5 | // https://github.com/sohkai/uniswap-v3-spot-twap-oracle 6 | // inteface: https://github.com/sohkai/uniswap-v3-spot-twap-oracle/blob/8f9777a6160a089c99f39f2ee297119ee293bc4b/contracts/interfaces/IDexPriceAggregator.sol 7 | // implementation: https://github.com/sohkai/uniswap-v3-spot-twap-oracle/blob/8f9777a6160a089c99f39f2ee297119ee293bc4b/contracts/DexPriceAggregatorUniswapV3.sol 8 | interface IDexPriceAggregator { 9 | function assetToAsset( 10 | address tokenIn, 11 | uint amountIn, 12 | address tokenOut, 13 | uint twapPeriod 14 | ) external view returns (uint amountOut); 15 | } 16 | -------------------------------------------------------------------------------- /contracts/interfaces/IDirectIntegrationManager.sol: -------------------------------------------------------------------------------- 1 | pragma solidity >=0.4.24; 2 | pragma experimental ABIEncoderV2; 3 | 4 | // https://docs.synthetix.io/contracts/source/interfaces/IDirectIntegration 5 | interface IDirectIntegrationManager { 6 | struct ParameterIntegrationSettings { 7 | bytes32 currencyKey; 8 | address dexPriceAggregator; 9 | address atomicEquivalentForDexPricing; 10 | uint atomicExchangeFeeRate; 11 | uint atomicTwapWindow; 12 | uint atomicMaxVolumePerBlock; 13 | uint atomicVolatilityConsiderationWindow; 14 | uint atomicVolatilityUpdateThreshold; 15 | uint exchangeFeeRate; 16 | uint exchangeMaxDynamicFee; 17 | uint exchangeDynamicFeeRounds; 18 | uint exchangeDynamicFeeThreshold; 19 | uint exchangeDynamicFeeWeightDecay; 20 | } 21 | 22 | function getExchangeParameters(address integration, bytes32 key) 23 | external 24 | view 25 | returns (ParameterIntegrationSettings memory settings); 26 | 27 | function setExchangeParameters( 28 | address integration, 29 | bytes32[] calldata currencyKeys, 30 | ParameterIntegrationSettings calldata params 31 | ) external; 32 | } 33 | -------------------------------------------------------------------------------- /contracts/interfaces/IDynamicSynthRedeemer.sol: -------------------------------------------------------------------------------- 1 | pragma solidity >=0.4.24; 2 | 3 | import "./IERC20.sol"; 4 | 5 | interface IDynamicSynthRedeemer { 6 | function suspendRedemption() external; 7 | 8 | function resumeRedemption() external; 9 | 10 | // Rate applied to chainlink price for redemptions 11 | function getDiscountRate() external view returns (uint); 12 | 13 | function redeem(bytes32 currencyKey) external; 14 | 15 | function redeemAll(bytes32[] calldata currencyKeys) external; 16 | 17 | function redeemPartial(bytes32 currencyKey, uint amountOfSynth) external; 18 | } 19 | -------------------------------------------------------------------------------- /contracts/interfaces/IERC20.sol: -------------------------------------------------------------------------------- 1 | pragma solidity >=0.4.24; 2 | 3 | // https://docs.synthetix.io/contracts/source/interfaces/ierc20 4 | interface IERC20 { 5 | // ERC20 Optional Views 6 | function name() external view returns (string memory); 7 | 8 | function symbol() external view returns (string memory); 9 | 10 | function decimals() external view returns (uint8); 11 | 12 | // Views 13 | function totalSupply() external view returns (uint); 14 | 15 | function balanceOf(address owner) external view returns (uint); 16 | 17 | function allowance(address owner, address spender) external view returns (uint); 18 | 19 | // Mutative functions 20 | function transfer(address to, uint value) external returns (bool); 21 | 22 | function approve(address spender, uint value) external returns (bool); 23 | 24 | function transferFrom( 25 | address from, 26 | address to, 27 | uint value 28 | ) external returns (bool); 29 | 30 | // Events 31 | event Transfer(address indexed from, address indexed to, uint value); 32 | 33 | event Approval(address indexed owner, address indexed spender, uint value); 34 | } 35 | -------------------------------------------------------------------------------- /contracts/interfaces/IEtherWrapper.sol: -------------------------------------------------------------------------------- 1 | pragma solidity >=0.4.24; 2 | 3 | import "./IWETH.sol"; 4 | 5 | // https://docs.synthetix.io/contracts/source/interfaces/ietherwrapper 6 | contract IEtherWrapper { 7 | function mint(uint amount) external; 8 | 9 | function burn(uint amount) external; 10 | 11 | function distributeFees() external; 12 | 13 | function capacity() external view returns (uint); 14 | 15 | function getReserves() external view returns (uint); 16 | 17 | function totalIssuedSynths() external view returns (uint); 18 | 19 | function calculateMintFee(uint amount) public view returns (uint); 20 | 21 | function calculateBurnFee(uint amount) public view returns (uint); 22 | 23 | function maxETH() public view returns (uint256); 24 | 25 | function mintFeeRate() public view returns (uint256); 26 | 27 | function burnFeeRate() public view returns (uint256); 28 | 29 | function weth() public view returns (IWETH); 30 | } 31 | -------------------------------------------------------------------------------- /contracts/interfaces/IExchangeCircuitBreaker.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.5.16; 2 | 3 | import "./IExchangeRates.sol"; 4 | 5 | // https://docs.synthetix.io/contracts/source/interfaces/IExchangeCircuitBreaker 6 | interface IExchangeCircuitBreaker { 7 | // Views 8 | 9 | function exchangeRates() external view returns (IExchangeRates); 10 | 11 | function rateWithInvalid(bytes32 currencyKey) external view returns (uint, bool); 12 | 13 | function rateWithBreakCircuit(bytes32 currencyKey) external returns (uint lastValidRate, bool circuitBroken); 14 | } 15 | -------------------------------------------------------------------------------- /contracts/interfaces/IExchangeState.sol: -------------------------------------------------------------------------------- 1 | pragma solidity >=0.4.24; 2 | 3 | // https://docs.synthetix.io/contracts/source/interfaces/iexchangestate 4 | interface IExchangeState { 5 | // Views 6 | struct ExchangeEntry { 7 | bytes32 src; 8 | uint amount; 9 | bytes32 dest; 10 | uint amountReceived; 11 | uint exchangeFeeRate; 12 | uint timestamp; 13 | uint roundIdForSrc; 14 | uint roundIdForDest; 15 | } 16 | 17 | function getLengthOfEntries(address account, bytes32 currencyKey) external view returns (uint); 18 | 19 | function getEntryAt( 20 | address account, 21 | bytes32 currencyKey, 22 | uint index 23 | ) 24 | external 25 | view 26 | returns ( 27 | bytes32 src, 28 | uint amount, 29 | bytes32 dest, 30 | uint amountReceived, 31 | uint exchangeFeeRate, 32 | uint timestamp, 33 | uint roundIdForSrc, 34 | uint roundIdForDest 35 | ); 36 | 37 | function getMaxTimestamp(address account, bytes32 currencyKey) external view returns (uint); 38 | 39 | // Mutative functions 40 | function appendExchangeEntry( 41 | address account, 42 | bytes32 src, 43 | uint amount, 44 | bytes32 dest, 45 | uint amountReceived, 46 | uint exchangeFeeRate, 47 | uint timestamp, 48 | uint roundIdForSrc, 49 | uint roundIdForDest 50 | ) external; 51 | 52 | function removeEntries(address account, bytes32 currencyKey) external; 53 | } 54 | -------------------------------------------------------------------------------- /contracts/interfaces/IFeePool.sol: -------------------------------------------------------------------------------- 1 | pragma solidity >=0.4.24; 2 | 3 | // https://docs.synthetix.io/contracts/source/interfaces/ifeepool 4 | interface IFeePool { 5 | // Views 6 | 7 | // solhint-disable-next-line func-name-mixedcase 8 | function FEE_ADDRESS() external view returns (address); 9 | 10 | function feesAvailable(address account) external view returns (uint, uint); 11 | 12 | function feesBurned(address account) external view returns (uint); 13 | 14 | function feesToBurn(address account) external view returns (uint); 15 | 16 | function feePeriodDuration() external view returns (uint); 17 | 18 | function isFeesClaimable(address account) external view returns (bool); 19 | 20 | function targetThreshold() external view returns (uint); 21 | 22 | function totalFeesAvailable() external view returns (uint); 23 | 24 | function totalFeesBurned() external view returns (uint); 25 | 26 | function totalRewardsAvailable() external view returns (uint); 27 | 28 | // Mutative Functions 29 | function claimFees() external returns (bool); 30 | 31 | function claimOnBehalf(address claimingForAddress) external returns (bool); 32 | 33 | function closeCurrentFeePeriod() external; 34 | 35 | function closeSecondary(uint snxBackedDebt, uint debtShareSupply) external; 36 | 37 | function recordFeePaid(uint sUSDAmount) external; 38 | 39 | function setRewardsToDistribute(uint amount) external; 40 | } 41 | -------------------------------------------------------------------------------- /contracts/interfaces/IFuturesMarketBaseTypes.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.5.16; 2 | 3 | interface IFuturesMarketBaseTypes { 4 | /* ========== TYPES ========== */ 5 | 6 | enum Status { 7 | Ok, 8 | InvalidPrice, 9 | PriceOutOfBounds, 10 | CanLiquidate, 11 | CannotLiquidate, 12 | MaxMarketSizeExceeded, 13 | MaxLeverageExceeded, 14 | InsufficientMargin, 15 | NotPermitted, 16 | NilOrder, 17 | NoPositionOpen, 18 | PriceTooVolatile 19 | } 20 | 21 | // If margin/size are positive, the position is long; if negative then it is short. 22 | struct Position { 23 | uint64 id; 24 | uint64 lastFundingIndex; 25 | uint128 margin; 26 | uint128 lastPrice; 27 | int128 size; 28 | } 29 | 30 | // next-price order storage 31 | struct NextPriceOrder { 32 | int128 sizeDelta; // difference in position to pass to modifyPosition 33 | uint128 targetRoundId; // price oracle roundId using which price this order needs to exucted 34 | uint128 commitDeposit; // the commitDeposit paid upon submitting that needs to be refunded if order succeeds 35 | uint128 keeperDeposit; // the keeperDeposit paid upon submitting that needs to be paid / refunded on tx confirmation 36 | bytes32 trackingCode; // tracking code to emit on execution for volume source fee sharing 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /contracts/interfaces/IFuturesMarketManager.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.5.16; 2 | 3 | interface IFuturesMarketManager { 4 | function markets(uint index, uint pageSize) external view returns (address[] memory); 5 | 6 | function markets( 7 | uint index, 8 | uint pageSize, 9 | bool proxiedMarkets 10 | ) external view returns (address[] memory); 11 | 12 | function numMarkets() external view returns (uint); 13 | 14 | function numMarkets(bool proxiedMarkets) external view returns (uint); 15 | 16 | function allMarkets() external view returns (address[] memory); 17 | 18 | function allMarkets(bool proxiedMarkets) external view returns (address[] memory); 19 | 20 | function marketForKey(bytes32 marketKey) external view returns (address); 21 | 22 | function marketsForKeys(bytes32[] calldata marketKeys) external view returns (address[] memory); 23 | 24 | function totalDebt() external view returns (uint debt, bool isInvalid); 25 | 26 | function isEndorsed(address account) external view returns (bool); 27 | 28 | function allEndorsedAddresses() external view returns (address[] memory); 29 | 30 | function addEndorsedAddresses(address[] calldata addresses) external; 31 | 32 | function removeEndorsedAddresses(address[] calldata addresses) external; 33 | } 34 | -------------------------------------------------------------------------------- /contracts/interfaces/IFuturesMarketSettings.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.5.16; 2 | 3 | interface IFuturesMarketSettings { 4 | struct Parameters { 5 | uint takerFee; 6 | uint makerFee; 7 | uint takerFeeNextPrice; 8 | uint makerFeeNextPrice; 9 | uint nextPriceConfirmWindow; 10 | uint maxLeverage; 11 | uint maxMarketValueUSD; 12 | uint maxFundingRate; 13 | uint skewScaleUSD; 14 | } 15 | 16 | function takerFee(bytes32 _marketKey) external view returns (uint); 17 | 18 | function makerFee(bytes32 _marketKey) external view returns (uint); 19 | 20 | function takerFeeNextPrice(bytes32 _marketKey) external view returns (uint); 21 | 22 | function makerFeeNextPrice(bytes32 _marketKey) external view returns (uint); 23 | 24 | function nextPriceConfirmWindow(bytes32 _marketKey) external view returns (uint); 25 | 26 | function maxLeverage(bytes32 _marketKey) external view returns (uint); 27 | 28 | function maxMarketValueUSD(bytes32 _marketKey) external view returns (uint); 29 | 30 | function maxFundingRate(bytes32 _marketKey) external view returns (uint); 31 | 32 | function skewScaleUSD(bytes32 _marketKey) external view returns (uint); 33 | 34 | function parameters(bytes32 _marketKey) 35 | external 36 | view 37 | returns ( 38 | uint _takerFee, 39 | uint _makerFee, 40 | uint _takerFeeNextPrice, 41 | uint _makerFeeNextPrice, 42 | uint _nextPriceConfirmWindow, 43 | uint _maxLeverage, 44 | uint _maxMarketValueUSD, 45 | uint _maxFundingRate, 46 | uint _skewScaleUSD 47 | ); 48 | 49 | function minKeeperFee() external view returns (uint); 50 | 51 | function liquidationFeeRatio() external view returns (uint); 52 | 53 | function liquidationBufferRatio() external view returns (uint); 54 | 55 | function minInitialMargin() external view returns (uint); 56 | } 57 | -------------------------------------------------------------------------------- /contracts/interfaces/IHasBalance.sol: -------------------------------------------------------------------------------- 1 | pragma solidity >=0.4.24; 2 | 3 | // https://docs.synthetix.io/contracts/source/interfaces/ihasbalance 4 | interface IHasBalance { 5 | // Views 6 | function balanceOf(address account) external view returns (uint); 7 | } 8 | -------------------------------------------------------------------------------- /contracts/interfaces/ILiquidator.sol: -------------------------------------------------------------------------------- 1 | pragma solidity >=0.4.24; 2 | 3 | interface ILiquidator { 4 | // Views 5 | function issuanceRatio() external view returns (uint); 6 | 7 | function liquidationDelay() external view returns (uint); 8 | 9 | function liquidationRatio() external view returns (uint); 10 | 11 | function liquidationEscrowDuration() external view returns (uint); 12 | 13 | function liquidationPenalty() external view returns (uint); 14 | 15 | function selfLiquidationPenalty() external view returns (uint); 16 | 17 | function liquidateReward() external view returns (uint); 18 | 19 | function flagReward() external view returns (uint); 20 | 21 | function liquidationCollateralRatio() external view returns (uint); 22 | 23 | function getLiquidationDeadlineForAccount(address account) external view returns (uint); 24 | 25 | function getLiquidationCallerForAccount(address account) external view returns (address); 26 | 27 | function isLiquidationOpen(address account, bool isSelfLiquidation) external view returns (bool); 28 | 29 | function isLiquidationDeadlinePassed(address account) external view returns (bool); 30 | 31 | function calculateAmountToFixCollateral( 32 | uint debtBalance, 33 | uint collateral, 34 | uint penalty 35 | ) external view returns (uint); 36 | 37 | function liquidationAmounts(address account, bool isSelfLiquidation) 38 | external 39 | view 40 | returns ( 41 | uint totalRedeemed, 42 | uint debtToRemove, 43 | uint escrowToLiquidate, 44 | uint initialDebtBalance 45 | ); 46 | 47 | // Mutative Functions 48 | function flagAccountForLiquidation(address account) external; 49 | 50 | // Restricted: used internally to Synthetix contracts 51 | function removeAccountInLiquidation(address account) external; 52 | 53 | function checkAndRemoveAccountInLiquidation(address account) external; 54 | } 55 | -------------------------------------------------------------------------------- /contracts/interfaces/ILiquidatorRewards.sol: -------------------------------------------------------------------------------- 1 | pragma solidity >=0.4.24; 2 | 3 | interface ILiquidatorRewards { 4 | // Views 5 | 6 | function earned(address account) external view returns (uint256); 7 | 8 | // Mutative 9 | 10 | function getReward(address account) external; 11 | 12 | function notifyRewardAmount(uint256 reward) external; 13 | 14 | function updateEntry(address account) external; 15 | } 16 | -------------------------------------------------------------------------------- /contracts/interfaces/IOwnerRelayOnOptimism.sol: -------------------------------------------------------------------------------- 1 | pragma solidity >=0.4.24; 2 | pragma experimental ABIEncoderV2; 3 | 4 | interface IOwnerRelayOnOptimism { 5 | function finalizeRelay(address target, bytes calldata payload) external; 6 | 7 | function finalizeRelayBatch(address[] calldata target, bytes[] calldata payloads) external; 8 | } 9 | -------------------------------------------------------------------------------- /contracts/interfaces/IPerpsV2ExchangeRate.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.5.16; 2 | pragma experimental ABIEncoderV2; 3 | 4 | import "./IPyth.sol"; 5 | 6 | // https://docs.synthetix.io/contracts/source/contracts/IPerpsV2ExchangeRate 7 | interface IPerpsV2ExchangeRate { 8 | function setOffchainOracle(IPyth _offchainOracle) external; 9 | 10 | function setOffchainPriceFeedId(bytes32 assetId, bytes32 priceFeedId) external; 11 | 12 | /* ========== VIEWS ========== */ 13 | 14 | function offchainOracle() external view returns (IPyth); 15 | 16 | function offchainPriceFeedId(bytes32 assetId) external view returns (bytes32); 17 | 18 | /* ---------- priceFeeds mutation ---------- */ 19 | 20 | function updatePythPrice(address sender, bytes[] calldata priceUpdateData) external payable; 21 | 22 | // it is a view but it can revert 23 | function resolveAndGetPrice(bytes32 assetId, uint maxAge) external view returns (uint price, uint publishTime); 24 | 25 | // it is a view but it can revert 26 | function resolveAndGetLatestPrice(bytes32 assetId) external view returns (uint price, uint publishTime); 27 | } 28 | -------------------------------------------------------------------------------- /contracts/interfaces/IPerpsV2Market.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.5.16; 2 | 3 | import "./IPerpsV2MarketBaseTypes.sol"; 4 | 5 | interface IPerpsV2Market { 6 | /* ========== FUNCTION INTERFACE ========== */ 7 | 8 | /* ---------- Market Operations ---------- */ 9 | 10 | function recomputeFunding() external returns (uint lastIndex); 11 | 12 | function transferMargin(int marginDelta) external; 13 | 14 | function withdrawAllMargin() external; 15 | 16 | function modifyPosition(int sizeDelta, uint desiredFillPrice) external; 17 | 18 | function modifyPositionWithTracking( 19 | int sizeDelta, 20 | uint desiredFillPrice, 21 | bytes32 trackingCode 22 | ) external; 23 | 24 | function closePosition(uint desiredFillPrice) external; 25 | 26 | function closePositionWithTracking(uint desiredFillPrice, bytes32 trackingCode) external; 27 | } 28 | -------------------------------------------------------------------------------- /contracts/interfaces/IPerpsV2MarketBaseTypes.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.5.16; 2 | 3 | interface IPerpsV2MarketBaseTypes { 4 | /* ========== TYPES ========== */ 5 | 6 | enum OrderType {Atomic, Delayed, Offchain} 7 | 8 | enum Status { 9 | Ok, 10 | InvalidPrice, 11 | InvalidOrderType, 12 | PriceOutOfBounds, 13 | CanLiquidate, 14 | CannotLiquidate, 15 | MaxMarketSizeExceeded, 16 | MaxLeverageExceeded, 17 | InsufficientMargin, 18 | NotPermitted, 19 | NilOrder, 20 | NoPositionOpen, 21 | PriceTooVolatile, 22 | PriceImpactToleranceExceeded, 23 | PositionFlagged, 24 | PositionNotFlagged 25 | } 26 | 27 | // If margin/size are positive, the position is long; if negative then it is short. 28 | struct Position { 29 | uint64 id; 30 | uint64 lastFundingIndex; 31 | uint128 margin; 32 | uint128 lastPrice; 33 | int128 size; 34 | } 35 | 36 | // Delayed order storage 37 | struct DelayedOrder { 38 | bool isOffchain; // flag indicating the delayed order is offchain 39 | int128 sizeDelta; // difference in position to pass to modifyPosition 40 | uint128 desiredFillPrice; // desired fill price as usd used on fillPrice at execution 41 | uint128 targetRoundId; // price oracle roundId using which price this order needs to executed 42 | uint128 commitDeposit; // the commitDeposit paid upon submitting that needs to be refunded if order succeeds 43 | uint128 keeperDeposit; // the keeperDeposit paid upon submitting that needs to be paid / refunded on tx confirmation 44 | uint256 executableAtTime; // The timestamp at which this order is executable at 45 | uint256 intentionTime; // The block timestamp of submission 46 | bytes32 trackingCode; // tracking code to emit on execution for volume source fee sharing 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /contracts/interfaces/IPerpsV2MarketBaseTypesLegacyR1.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.5.16; 2 | 3 | interface IPerpsV2MarketBaseTypesLegacyR1 { 4 | /* ========== TYPES ========== */ 5 | 6 | enum OrderType {Atomic, Delayed, Offchain} 7 | 8 | enum Status { 9 | Ok, 10 | InvalidPrice, 11 | InvalidOrderType, 12 | PriceOutOfBounds, 13 | CanLiquidate, 14 | CannotLiquidate, 15 | MaxMarketSizeExceeded, 16 | MaxLeverageExceeded, 17 | InsufficientMargin, 18 | NotPermitted, 19 | NilOrder, 20 | NoPositionOpen, 21 | PriceTooVolatile, 22 | PriceImpactToleranceExceeded, 23 | PositionFlagged, 24 | PositionNotFlagged 25 | } 26 | 27 | // If margin/size are positive, the position is long; if negative then it is short. 28 | struct Position { 29 | uint64 id; 30 | uint64 lastFundingIndex; 31 | uint128 margin; 32 | uint128 lastPrice; 33 | int128 size; 34 | } 35 | 36 | // Delayed order storage 37 | struct DelayedOrder { 38 | bool isOffchain; // flag indicating the delayed order is offchain 39 | int128 sizeDelta; // difference in position to pass to modifyPosition 40 | uint128 priceImpactDelta; // desired price delta 41 | uint128 targetRoundId; // price oracle roundId using which price this order needs to executed 42 | uint128 commitDeposit; // the commitDeposit paid upon submitting that needs to be refunded if order succeeds 43 | uint128 keeperDeposit; // the keeperDeposit paid upon submitting that needs to be paid / refunded on tx confirmation 44 | uint256 executableAtTime; // The timestamp at which this order is executable at 45 | uint256 intentionTime; // The block timestamp of submission 46 | bytes32 trackingCode; // tracking code to emit on execution for volume source fee sharing 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /contracts/interfaces/IPerpsV2MarketDelayedExecution.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.5.16; 2 | pragma experimental ABIEncoderV2; 3 | 4 | import "./IPerpsV2MarketBaseTypes.sol"; 5 | 6 | interface IPerpsV2MarketDelayedExecution { 7 | function executeDelayedOrder(address account) external; 8 | 9 | function executeOffchainDelayedOrder(address account, bytes[] calldata priceUpdateData) external payable; 10 | 11 | function cancelDelayedOrder(address account) external; 12 | 13 | function cancelOffchainDelayedOrder(address account) external; 14 | } 15 | -------------------------------------------------------------------------------- /contracts/interfaces/IPerpsV2MarketDelayedIntent.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.5.16; 2 | pragma experimental ABIEncoderV2; 3 | 4 | import "./IPerpsV2MarketBaseTypes.sol"; 5 | 6 | interface IPerpsV2MarketDelayedIntent { 7 | function submitCloseOffchainDelayedOrderWithTracking(uint desiredFillPrice, bytes32 trackingCode) external; 8 | 9 | function submitCloseDelayedOrderWithTracking( 10 | uint desiredTimeDelta, 11 | uint desiredFillPrice, 12 | bytes32 trackingCode 13 | ) external; 14 | 15 | function submitDelayedOrder( 16 | int sizeDelta, 17 | uint desiredTimeDelta, 18 | uint desiredFillPrice 19 | ) external; 20 | 21 | function submitDelayedOrderWithTracking( 22 | int sizeDelta, 23 | uint desiredTimeDelta, 24 | uint desiredFillPrice, 25 | bytes32 trackingCode 26 | ) external; 27 | 28 | function submitOffchainDelayedOrder(int sizeDelta, uint desiredFillPrice) external; 29 | 30 | function submitOffchainDelayedOrderWithTracking( 31 | int sizeDelta, 32 | uint desiredFillPrice, 33 | bytes32 trackingCode 34 | ) external; 35 | } 36 | -------------------------------------------------------------------------------- /contracts/interfaces/IPerpsV2MarketLiquidate.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.5.16; 2 | 3 | import "./IPerpsV2MarketBaseTypes.sol"; 4 | 5 | interface IPerpsV2MarketLiquidate { 6 | /* ========== FUNCTION INTERFACE ========== */ 7 | 8 | /* ---------- Market Operations ---------- */ 9 | 10 | function flagPosition(address account) external; 11 | 12 | function liquidatePosition(address account) external; 13 | 14 | function forceLiquidatePosition(address account) external; 15 | } 16 | -------------------------------------------------------------------------------- /contracts/interfaces/IRewardEscrow.sol: -------------------------------------------------------------------------------- 1 | pragma solidity >=0.4.24; 2 | 3 | // https://docs.synthetix.io/contracts/source/interfaces/irewardescrow 4 | interface IRewardEscrow { 5 | // Views 6 | function balanceOf(address account) external view returns (uint); 7 | 8 | function numVestingEntries(address account) external view returns (uint); 9 | 10 | function totalEscrowedAccountBalance(address account) external view returns (uint); 11 | 12 | function totalVestedAccountBalance(address account) external view returns (uint); 13 | 14 | function getVestingScheduleEntry(address account, uint index) external view returns (uint[2] memory); 15 | 16 | function getNextVestingIndex(address account) external view returns (uint); 17 | 18 | // Mutative functions 19 | function appendVestingEntry(address account, uint quantity) external; 20 | 21 | function vest() external; 22 | } 23 | -------------------------------------------------------------------------------- /contracts/interfaces/IRewardsDistribution.sol: -------------------------------------------------------------------------------- 1 | pragma solidity >=0.4.24; 2 | 3 | // https://docs.synthetix.io/contracts/source/interfaces/irewardsdistribution 4 | interface IRewardsDistribution { 5 | // Structs 6 | struct DistributionData { 7 | address destination; 8 | uint amount; 9 | } 10 | 11 | // Views 12 | function authority() external view returns (address); 13 | 14 | function distributions(uint index) external view returns (address destination, uint amount); // DistributionData 15 | 16 | function distributionsLength() external view returns (uint); 17 | 18 | // Mutative Functions 19 | function distributeRewards(uint amount) external returns (bool); 20 | } 21 | -------------------------------------------------------------------------------- /contracts/interfaces/IShortingRewards.sol: -------------------------------------------------------------------------------- 1 | pragma solidity >=0.4.24; 2 | 3 | // https://docs.synthetix.io/contracts/source/interfaces/istakingrewards 4 | interface IShortingRewards { 5 | // Views 6 | function lastTimeRewardApplicable() external view returns (uint256); 7 | 8 | function rewardPerToken() external view returns (uint256); 9 | 10 | function earned(address account) external view returns (uint256); 11 | 12 | function getRewardForDuration() external view returns (uint256); 13 | 14 | function totalSupply() external view returns (uint256); 15 | 16 | function balanceOf(address account) external view returns (uint256); 17 | 18 | // Mutative 19 | 20 | function enrol(address account, uint256 amount) external; 21 | 22 | function withdraw(address account, uint256 amount) external; 23 | 24 | function getReward(address account) external; 25 | } 26 | -------------------------------------------------------------------------------- /contracts/interfaces/IStakingRewards.sol: -------------------------------------------------------------------------------- 1 | pragma solidity >=0.4.24; 2 | 3 | // https://docs.synthetix.io/contracts/source/interfaces/istakingrewards 4 | interface IStakingRewards { 5 | // Views 6 | 7 | function balanceOf(address account) external view returns (uint256); 8 | 9 | function earned(address account) external view returns (uint256); 10 | 11 | function getRewardForDuration() external view returns (uint256); 12 | 13 | function lastTimeRewardApplicable() external view returns (uint256); 14 | 15 | function rewardPerToken() external view returns (uint256); 16 | 17 | function rewardsDistribution() external view returns (address); 18 | 19 | function rewardsToken() external view returns (address); 20 | 21 | function totalSupply() external view returns (uint256); 22 | 23 | // Mutative 24 | 25 | function exit() external; 26 | 27 | function getReward() external; 28 | 29 | function stake(uint256 amount) external; 30 | 31 | function withdraw(uint256 amount) external; 32 | } 33 | -------------------------------------------------------------------------------- /contracts/interfaces/ISupplySchedule.sol: -------------------------------------------------------------------------------- 1 | pragma solidity >=0.4.24; 2 | 3 | // https://docs.synthetix.io/contracts/source/interfaces/isupplyschedule 4 | interface ISupplySchedule { 5 | // Views 6 | function mintableSupply() external view returns (uint); 7 | 8 | function isMintable() external view returns (bool); 9 | 10 | function minterReward() external view returns (uint); 11 | 12 | // Mutative functions 13 | function recordMintEvent(uint supplyMinted) external returns (uint); 14 | } 15 | -------------------------------------------------------------------------------- /contracts/interfaces/ISynth.sol: -------------------------------------------------------------------------------- 1 | pragma solidity >=0.4.24; 2 | 3 | // https://docs.synthetix.io/contracts/source/interfaces/isynth 4 | interface ISynth { 5 | // Views 6 | function currencyKey() external view returns (bytes32); 7 | 8 | function transferableSynths(address account) external view returns (uint); 9 | 10 | // Mutative functions 11 | function transferAndSettle(address to, uint value) external returns (bool); 12 | 13 | function transferFromAndSettle( 14 | address from, 15 | address to, 16 | uint value 17 | ) external returns (bool); 18 | 19 | // Restricted: used internally to Synthetix 20 | function burn(address account, uint amount) external; 21 | 22 | function issue(address account, uint amount) external; 23 | } 24 | -------------------------------------------------------------------------------- /contracts/interfaces/ISynthRedeemer.sol: -------------------------------------------------------------------------------- 1 | pragma solidity >=0.4.24; 2 | 3 | import "./IERC20.sol"; 4 | 5 | interface ISynthRedeemer { 6 | // Rate of redemption - 0 for none 7 | function redemptions(address synthProxy) external view returns (uint redeemRate); 8 | 9 | // sUSD balance of deprecated token holder 10 | function balanceOf(IERC20 synthProxy, address account) external view returns (uint balanceOfInsUSD); 11 | 12 | // Full sUSD supply of token 13 | function totalSupply(IERC20 synthProxy) external view returns (uint totalSupplyInsUSD); 14 | 15 | function redeem(IERC20 synthProxy) external; 16 | 17 | function redeemAll(IERC20[] calldata synthProxies) external; 18 | 19 | function redeemPartial(IERC20 synthProxy, uint amountOfSynth) external; 20 | 21 | // Restricted to Issuer 22 | function deprecate(IERC20 synthProxy, uint rateToRedeem) external; 23 | } 24 | -------------------------------------------------------------------------------- /contracts/interfaces/ISynthetixBridgeEscrow.sol: -------------------------------------------------------------------------------- 1 | pragma solidity >=0.4.24; 2 | 3 | interface ISynthetixBridgeEscrow { 4 | function approveBridge( 5 | address _token, 6 | address _bridge, 7 | uint256 _amount 8 | ) external; 9 | } 10 | -------------------------------------------------------------------------------- /contracts/interfaces/ISynthetixBridgeToBase.sol: -------------------------------------------------------------------------------- 1 | pragma solidity >=0.4.24; 2 | pragma experimental ABIEncoderV2; 3 | 4 | import "./IRewardEscrowV2.sol"; 5 | 6 | interface ISynthetixBridgeToBase { 7 | // invoked by the xDomain messenger on L2 8 | function finalizeEscrowMigration( 9 | address account, 10 | uint256 escrowedAmount, 11 | VestingEntries.VestingEntry[] calldata vestingEntries 12 | ) external; 13 | 14 | // invoked by the xDomain messenger on L2 15 | function finalizeRewardDeposit(address from, uint amount) external; 16 | 17 | function finalizeFeePeriodClose(uint snxBackedDebt, uint debtSharesSupply) external; 18 | } 19 | -------------------------------------------------------------------------------- /contracts/interfaces/ISynthetixBridgeToOptimism.sol: -------------------------------------------------------------------------------- 1 | pragma solidity >=0.4.24; 2 | pragma experimental ABIEncoderV2; 3 | 4 | interface ISynthetixBridgeToOptimism { 5 | function closeFeePeriod(uint snxBackedDebt, uint debtSharesSupply) external; 6 | 7 | function migrateEscrow(uint256[][] calldata entryIDs) external; 8 | 9 | function depositTo(address to, uint amount) external; 10 | 11 | function depositReward(uint amount) external; 12 | 13 | function depositAndMigrateEscrow(uint256 depositAmount, uint256[][] calldata entryIDs) external; 14 | } 15 | -------------------------------------------------------------------------------- /contracts/interfaces/ISynthetixDebtShare.sol: -------------------------------------------------------------------------------- 1 | pragma solidity >=0.4.24; 2 | 3 | // https://docs.synthetix.io/contracts/source/interfaces/isynthetixdebtshare 4 | interface ISynthetixDebtShare { 5 | // Views 6 | 7 | function currentPeriodId() external view returns (uint128); 8 | 9 | function allowance(address account, address spender) external view returns (uint); 10 | 11 | function balanceOf(address account) external view returns (uint); 12 | 13 | function balanceOfOnPeriod(address account, uint periodId) external view returns (uint); 14 | 15 | function totalSupply() external view returns (uint); 16 | 17 | function sharePercent(address account) external view returns (uint); 18 | 19 | function sharePercentOnPeriod(address account, uint periodId) external view returns (uint); 20 | 21 | // Mutative functions 22 | 23 | function takeSnapshot(uint128 id) external; 24 | 25 | function mintShare(address account, uint256 amount) external; 26 | 27 | function burnShare(address account, uint256 amount) external; 28 | 29 | function approve(address, uint256) external pure returns (bool); 30 | 31 | function transfer(address to, uint256 amount) external pure returns (bool); 32 | 33 | function transferFrom( 34 | address from, 35 | address to, 36 | uint256 amount 37 | ) external returns (bool); 38 | 39 | function addAuthorizedBroker(address target) external; 40 | 41 | function removeAuthorizedBroker(address target) external; 42 | 43 | function addAuthorizedToSnapshot(address target) external; 44 | 45 | function removeAuthorizedToSnapshot(address target) external; 46 | } 47 | -------------------------------------------------------------------------------- /contracts/interfaces/ISynthetixState.sol: -------------------------------------------------------------------------------- 1 | pragma solidity >=0.4.24; 2 | 3 | // https://docs.synthetix.io/contracts/source/interfaces/isynthetixstate 4 | interface ISynthetixState { 5 | // Views 6 | function debtLedger(uint index) external view returns (uint); 7 | 8 | function issuanceData(address account) external view returns (uint initialDebtOwnership, uint debtEntryIndex); 9 | 10 | function debtLedgerLength() external view returns (uint); 11 | 12 | function hasIssued(address account) external view returns (bool); 13 | 14 | function lastDebtLedgerEntry() external view returns (uint); 15 | 16 | // Mutative functions 17 | function incrementTotalIssuerCount() external; 18 | 19 | function decrementTotalIssuerCount() external; 20 | 21 | function setCurrentIssuanceData(address account, uint initialDebtOwnership) external; 22 | 23 | function appendDebtLedgerValue(uint value) external; 24 | 25 | function clearIssuanceData(address account) external; 26 | } 27 | -------------------------------------------------------------------------------- /contracts/interfaces/IVirtualSynth.sol: -------------------------------------------------------------------------------- 1 | pragma solidity >=0.4.24; 2 | 3 | import "./ISynth.sol"; 4 | 5 | interface IVirtualSynth { 6 | // Views 7 | function balanceOfUnderlying(address account) external view returns (uint); 8 | 9 | function rate() external view returns (uint); 10 | 11 | function readyToSettle() external view returns (bool); 12 | 13 | function secsLeftInWaitingPeriod() external view returns (uint); 14 | 15 | function settled() external view returns (bool); 16 | 17 | function synth() external view returns (ISynth); 18 | 19 | // Mutative functions 20 | function settle(address account) external; 21 | } 22 | -------------------------------------------------------------------------------- /contracts/interfaces/IWETH.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.5.16; 2 | 3 | interface IWETH { 4 | // ERC20 Optional Views 5 | function name() external view returns (string memory); 6 | 7 | function symbol() external view returns (string memory); 8 | 9 | function decimals() external view returns (uint8); 10 | 11 | // Views 12 | function totalSupply() external view returns (uint); 13 | 14 | function balanceOf(address owner) external view returns (uint); 15 | 16 | function allowance(address owner, address spender) external view returns (uint); 17 | 18 | // Mutative functions 19 | function transfer(address to, uint value) external returns (bool); 20 | 21 | function approve(address spender, uint value) external returns (bool); 22 | 23 | function transferFrom( 24 | address from, 25 | address to, 26 | uint value 27 | ) external returns (bool); 28 | 29 | // WETH-specific functions. 30 | function deposit() external payable; 31 | 32 | function withdraw(uint amount) external; 33 | 34 | // Events 35 | event Transfer(address indexed from, address indexed to, uint value); 36 | event Approval(address indexed owner, address indexed spender, uint value); 37 | event Deposit(address indexed to, uint amount); 38 | event Withdrawal(address indexed to, uint amount); 39 | } 40 | -------------------------------------------------------------------------------- /contracts/interfaces/IWrapper.sol: -------------------------------------------------------------------------------- 1 | pragma solidity >=0.4.24; 2 | 3 | import "./IERC20.sol"; 4 | 5 | // https://docs.synthetix.io/contracts/source/interfaces/iwrapper 6 | interface IWrapper { 7 | function mint(uint amount) external; 8 | 9 | function burn(uint amount) external; 10 | 11 | function capacity() external view returns (uint); 12 | 13 | function totalIssuedSynths() external view returns (uint); 14 | 15 | function calculateMintFee(uint amount) external view returns (uint, bool); 16 | 17 | function calculateBurnFee(uint amount) external view returns (uint, bool); 18 | 19 | function maxTokenAmount() external view returns (uint256); 20 | 21 | function mintFeeRate() external view returns (int256); 22 | 23 | function burnFeeRate() external view returns (int256); 24 | } 25 | -------------------------------------------------------------------------------- /contracts/interfaces/IWrapperFactory.sol: -------------------------------------------------------------------------------- 1 | pragma solidity >=0.4.24; 2 | 3 | import "./IERC20.sol"; 4 | 5 | // https://docs.synthetix.io/contracts/source/interfaces/iwrapperfactory 6 | interface IWrapperFactory { 7 | function isWrapper(address possibleWrapper) external view returns (bool); 8 | 9 | function createWrapper( 10 | IERC20 token, 11 | bytes32 currencyKey, 12 | bytes32 synthContractName 13 | ) external returns (address); 14 | 15 | function distributeFees() external; 16 | } 17 | -------------------------------------------------------------------------------- /contracts/interfaces/PythStructs.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.5.16; 2 | 3 | // import "@pythnetwork/pyth-sdk-solidity/PythStructs.sol"; 4 | 5 | contract PythStructs { 6 | // A price with a degree of uncertainty, represented as a price +- a confidence interval. 7 | // 8 | // The confidence interval roughly corresponds to the standard error of a normal distribution. 9 | // Both the price and confidence are stored in a fixed-point numeric representation, 10 | // `x * (10^expo)`, where `expo` is the exponent. 11 | // 12 | // Please refer to the documentation at https://docs.pyth.network/consumers/best-practices for how 13 | // to how this price safely. 14 | struct Price { 15 | // Price 16 | int64 price; 17 | // Confidence interval around the price 18 | uint64 conf; 19 | // Price exponent 20 | int32 expo; 21 | // Unix timestamp describing when the price was published 22 | uint publishTime; 23 | } 24 | 25 | // PriceFeed represents a current aggregate price from pyth publisher feeds. 26 | struct PriceFeed { 27 | // The price ID. 28 | bytes32 id; 29 | // Latest available price 30 | Price price; 31 | // Latest available exponentially-weighted moving average price 32 | Price emaPrice; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /contracts/legacy/LegacyOwned.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.5.16; 2 | 3 | contract LegacyOwned { 4 | address public owner; 5 | address public nominatedOwner; 6 | 7 | constructor(address _owner) public { 8 | owner = _owner; 9 | } 10 | 11 | function nominateOwner(address _owner) external onlyOwner { 12 | nominatedOwner = _owner; 13 | emit OwnerNominated(_owner); 14 | } 15 | 16 | function acceptOwnership() external { 17 | require(msg.sender == nominatedOwner); 18 | emit OwnerChanged(owner, nominatedOwner); 19 | owner = nominatedOwner; 20 | nominatedOwner = address(0); 21 | } 22 | 23 | modifier onlyOwner { 24 | require(msg.sender == owner); 25 | _; 26 | } 27 | 28 | event OwnerNominated(address newOwner); 29 | event OwnerChanged(address oldOwner, address newOwner); 30 | } 31 | -------------------------------------------------------------------------------- /contracts/legacy/LegacyTokenState.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.5.16; 2 | 3 | import "./LegacyOwned.sol"; 4 | 5 | contract LegacyTokenState is LegacyOwned { 6 | // the address of the contract that can modify balances and allowances 7 | // this can only be changed by the owner of this contract 8 | address public associatedContract; 9 | 10 | // ERC20 fields. 11 | mapping(address => uint) public balanceOf; 12 | mapping(address => mapping(address => uint256)) public allowance; 13 | 14 | constructor(address _owner, address _associatedContract) public LegacyOwned(_owner) { 15 | associatedContract = _associatedContract; 16 | emit AssociatedContractUpdated(_associatedContract); 17 | } 18 | 19 | /* ========== SETTERS ========== */ 20 | 21 | // Change the associated contract to a new address 22 | function setAssociatedContract(address _associatedContract) external onlyOwner { 23 | associatedContract = _associatedContract; 24 | emit AssociatedContractUpdated(_associatedContract); 25 | } 26 | 27 | function setAllowance( 28 | address tokenOwner, 29 | address spender, 30 | uint value 31 | ) external onlyAssociatedContract { 32 | allowance[tokenOwner][spender] = value; 33 | } 34 | 35 | function setBalanceOf(address account, uint value) external onlyAssociatedContract { 36 | balanceOf[account] = value; 37 | } 38 | 39 | /* ========== MODIFIERS ========== */ 40 | 41 | modifier onlyAssociatedContract { 42 | require(msg.sender == associatedContract); 43 | _; 44 | } 45 | 46 | /* ========== EVENTS ========== */ 47 | 48 | event AssociatedContractUpdated(address _associatedContract); 49 | } 50 | -------------------------------------------------------------------------------- /contracts/legacy/OneNetAggregatorsDEFI.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.5.16; 2 | 3 | import "../BaseOneNetAggregator.sol"; 4 | 5 | contract OneNetAggregatorsDEFI is BaseOneNetAggregator { 6 | bytes32 public constant CONTRACT_NAME = "OneNetAggregatorsDEFI"; 7 | 8 | constructor(AddressResolver _resolver) public BaseOneNetAggregator(_resolver) {} 9 | 10 | function decimals() external view returns (uint8) { 11 | return 8; 12 | } 13 | 14 | function getRoundData(uint80) 15 | public 16 | view 17 | returns ( 18 | uint80, 19 | int256, 20 | uint256, 21 | uint256, 22 | uint80 23 | ) 24 | { 25 | // Fixed price of $3195 as defined in SIP-243: Deprecate sDEFI 26 | uint fixedPrice = 319500000000; 27 | uint dataTimestamp = now; 28 | 29 | return (1, int256(fixedPrice), dataTimestamp, dataTimestamp, 1); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /contracts/test-helpers/FakeTradingRewards.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.5.16; 2 | 3 | import "../TradingRewards.sol"; 4 | 5 | import "../interfaces/IExchanger.sol"; 6 | 7 | contract FakeTradingRewards is TradingRewards { 8 | IERC20 public _mockSynthetixToken; 9 | 10 | constructor( 11 | address owner, 12 | address periodController, 13 | address resolver, 14 | address mockSynthetixToken 15 | ) public TradingRewards(owner, periodController, resolver) { 16 | _mockSynthetixToken = IERC20(mockSynthetixToken); 17 | } 18 | 19 | // Synthetix is mocked with an ERC20 token passed via the constructor. 20 | function synthetix() internal view returns (IERC20) { 21 | return IERC20(_mockSynthetixToken); 22 | } 23 | 24 | // Return msg.sender so that onlyExchanger modifier can be bypassed. 25 | function exchanger() internal view returns (IExchanger) { 26 | return IExchanger(msg.sender); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /contracts/test-helpers/GenericMock.sol: -------------------------------------------------------------------------------- 1 | // Source adapted from https://github.com/EthWorks/Doppelganger/blob/master/contracts/Doppelganger.sol 2 | 3 | pragma solidity ^0.5.16; 4 | 5 | contract GenericMock { 6 | mapping(bytes4 => bytes) public mockConfig; 7 | 8 | // solhint-disable payable-fallback, no-complex-fallback 9 | function() external { 10 | bytes memory ret = mockConfig[msg.sig]; 11 | assembly { 12 | return(add(ret, 0x20), mload(ret)) 13 | } 14 | } 15 | 16 | function mockReturns(bytes4 key, bytes calldata value) external { 17 | mockConfig[key] = value; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /contracts/test-helpers/MockContractStorage.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.5.16; 2 | 3 | import "../ContractStorage.sol"; 4 | 5 | contract MockContractStorage is ContractStorage { 6 | struct SomeEntry { 7 | uint value; 8 | bool flag; 9 | } 10 | 11 | mapping(bytes32 => mapping(bytes32 => SomeEntry)) public entries; 12 | 13 | constructor(address _resolver) public ContractStorage(_resolver) {} 14 | 15 | function getEntry(bytes32 contractName, bytes32 record) external view returns (uint value, bool flag) { 16 | SomeEntry storage entry = entries[hashes[contractName]][record]; 17 | return (entry.value, entry.flag); 18 | } 19 | 20 | function persistEntry( 21 | bytes32 contractName, 22 | bytes32 record, 23 | uint value, 24 | bool flag 25 | ) external onlyContract(contractName) { 26 | entries[_memoizeHash(contractName)][record].value = value; 27 | entries[_memoizeHash(contractName)][record].flag = flag; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /contracts/test-helpers/MockDexPriceAggregator.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.5.16; 2 | 3 | import "../interfaces/IDexPriceAggregator.sol"; 4 | import "../interfaces/IERC20.sol"; 5 | import "../SafeDecimalMath.sol"; 6 | 7 | contract MockDexPriceAggregator is IDexPriceAggregator { 8 | uint public constant UNIT = 10**uint(18); 9 | 10 | mapping(address => uint) public rates; 11 | bool public assetToAssetShouldRevert; 12 | 13 | function assetToAsset( 14 | address tokenIn, 15 | uint amountIn, 16 | address tokenOut, 17 | uint 18 | ) external view returns (uint amountOut) { 19 | if (assetToAssetShouldRevert) { 20 | revert("mock assetToAsset() reverted"); 21 | } 22 | 23 | uint inDecimals = IERC20(tokenIn).decimals(); 24 | uint outDecimals = IERC20(tokenOut).decimals(); 25 | uint inAmountWithRatesDecimals = (amountIn * UNIT) / 10**uint(inDecimals); 26 | uint outAmountWithRatesDecimals = (inAmountWithRatesDecimals * rates[tokenIn]) / rates[tokenOut]; 27 | 28 | return ((outAmountWithRatesDecimals * 10**uint(outDecimals)) / UNIT); 29 | } 30 | 31 | // Rate should be specified with 18 decimals 32 | function setAssetToAssetRate(address _asset, uint _rate) external { 33 | rates[_asset] = _rate; 34 | } 35 | 36 | function setAssetToAssetShouldRevert(bool _shouldRevert) external { 37 | assetToAssetShouldRevert = _shouldRevert; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /contracts/test-helpers/MockEtherWrapper.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.5.16; 2 | 3 | import "../SafeDecimalMath.sol"; 4 | 5 | contract MockEtherWrapper { 6 | using SafeMath for uint; 7 | using SafeDecimalMath for uint; 8 | 9 | uint public totalIssuedSynths; 10 | 11 | constructor() public {} 12 | 13 | function setTotalIssuedSynths(uint value) external { 14 | totalIssuedSynths = value; 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /contracts/test-helpers/MockFlagsInterface.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.5.16; 2 | 3 | interface FlagsInterface { 4 | function getFlag(address) external view returns (bool); 5 | 6 | function getFlags(address[] calldata) external view returns (bool[] memory); 7 | } 8 | 9 | contract MockFlagsInterface is FlagsInterface { 10 | mapping(address => bool) public flags; 11 | 12 | constructor() public {} 13 | 14 | function getFlag(address aggregator) external view returns (bool) { 15 | return flags[aggregator]; 16 | } 17 | 18 | function getFlags(address[] calldata aggregators) external view returns (bool[] memory results) { 19 | results = new bool[](aggregators.length); 20 | 21 | for (uint i = 0; i < aggregators.length; i++) { 22 | results[i] = flags[aggregators[i]]; 23 | } 24 | } 25 | 26 | function flagAggregator(address aggregator) external { 27 | flags[aggregator] = true; 28 | } 29 | 30 | function unflagAggregator(address aggregator) external { 31 | flags[aggregator] = false; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /contracts/test-helpers/MockFuturesMarket.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.5.16; 2 | 3 | interface IFuturesMarketManagerInternal { 4 | function issueSUSD(address account, uint amount) external; 5 | 6 | function burnSUSD(address account, uint amount) external; 7 | } 8 | 9 | contract MockFuturesMarket { 10 | bytes32 public baseAsset; 11 | bytes32 public marketKey; 12 | uint public debt; 13 | bool public invalid; 14 | IFuturesMarketManagerInternal public manager; 15 | 16 | constructor( 17 | IFuturesMarketManagerInternal _manager, 18 | bytes32 _baseAsset, 19 | bytes32 _marketKey, 20 | uint _debt, 21 | bool _invalid 22 | ) public { 23 | manager = _manager; 24 | baseAsset = _baseAsset; 25 | marketKey = _marketKey; 26 | debt = _debt; 27 | invalid = _invalid; 28 | } 29 | 30 | function setManager(IFuturesMarketManagerInternal _manager) external { 31 | manager = _manager; 32 | } 33 | 34 | function setBaseAsset(bytes32 _baseAsset) external { 35 | baseAsset = _baseAsset; 36 | } 37 | 38 | function setMarketKey(bytes32 _marketKey) external { 39 | marketKey = _marketKey; 40 | } 41 | 42 | function setMarketDebt(uint _debt) external { 43 | debt = _debt; 44 | } 45 | 46 | function setInvalid(bool _invalid) external { 47 | invalid = _invalid; 48 | } 49 | 50 | function marketDebt() external view returns (uint _debt, bool _invalid) { 51 | return (debt, invalid); 52 | } 53 | 54 | function issueSUSD(address account, uint amount) external { 55 | manager.issueSUSD(account, amount); 56 | } 57 | 58 | function burnSUSD(address account, uint amount) external { 59 | manager.burnSUSD(account, amount); 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /contracts/test-helpers/MockMigration.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.5.16; 2 | 3 | import "../BaseMigration.sol"; 4 | import "../Owned.sol"; 5 | 6 | contract MockMigration is BaseMigration { 7 | constructor(address _owner) public BaseMigration(_owner) {} 8 | 9 | function acceptOwnership(address someContract) external { 10 | Owned(someContract).acceptOwnership(); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /contracts/test-helpers/MockMintableSynthetix.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.5.16; 2 | 3 | contract MockMintableSynthetix { 4 | address public mintSecondaryCallAccount; 5 | uint public mintSecondaryCallAmount; 6 | 7 | address public burnSecondaryCallAccount; 8 | uint public burnSecondaryCallAmount; 9 | 10 | function mintSecondary(address account, uint amount) external { 11 | mintSecondaryCallAccount = account; 12 | mintSecondaryCallAmount = amount; 13 | } 14 | 15 | function burnSecondary(address account, uint amount) external { 16 | burnSecondaryCallAccount = account; 17 | burnSecondaryCallAmount = amount; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /contracts/test-helpers/MockMutator.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.5.16; 2 | 3 | contract MockMutator { 4 | uint256 public count; 5 | 6 | function read() external view returns (uint) { 7 | return count; 8 | } 9 | 10 | function update() external { 11 | count = count + 1; 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /contracts/test-helpers/MockPayable.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.5.16; 2 | 3 | contract MockPayable { 4 | uint256 public paidTimes; 5 | 6 | function pay() external payable { 7 | require(msg.value > 0, "No value paid"); 8 | paidTimes = paidTimes + 1; 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /contracts/test-helpers/MockReverter.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.5.16; 2 | 3 | contract MockReverter { 4 | function revertWithMsg(string calldata _msg) external pure { 5 | revert(_msg); 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /contracts/test-helpers/MockRewardsRecipient.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.5.16; 2 | 3 | import "../RewardsDistributionRecipient.sol"; 4 | import "../Owned.sol"; 5 | 6 | contract MockRewardsRecipient is RewardsDistributionRecipient { 7 | uint256 public rewardsAvailable; 8 | 9 | constructor(address _owner) public Owned(_owner) {} 10 | 11 | function notifyRewardAmount(uint256 reward) external onlyRewardsDistribution { 12 | rewardsAvailable = rewardsAvailable + reward; 13 | emit RewardAdded(reward); 14 | } 15 | 16 | event RewardAdded(uint256 amount); 17 | } 18 | -------------------------------------------------------------------------------- /contracts/test-helpers/MockThirdPartyExchangeContract.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.5.16; 2 | 3 | import "../interfaces/IAddressResolver.sol"; 4 | import "../interfaces/ISynthetix.sol"; 5 | 6 | contract MockThirdPartyExchangeContract { 7 | IAddressResolver public resolver; 8 | 9 | constructor(IAddressResolver _resolver) public { 10 | resolver = _resolver; 11 | } 12 | 13 | function exchange( 14 | bytes32 src, 15 | uint amount, 16 | bytes32 dest 17 | ) external { 18 | ISynthetix synthetix = ISynthetix(resolver.getAddress("Synthetix")); 19 | 20 | synthetix.exchangeWithTrackingForInitiator(src, amount, dest, address(this), "TRACKING_CODE"); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /contracts/test-helpers/MockToken.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.5.16; 2 | 3 | import "openzeppelin-solidity-2.3.0/contracts/token/ERC20/ERC20.sol"; 4 | import "openzeppelin-solidity-2.3.0/contracts/token/ERC20/ERC20Detailed.sol"; 5 | 6 | contract MockToken is ERC20, ERC20Detailed { 7 | constructor( 8 | string memory name, 9 | string memory symbol, 10 | uint8 decimals 11 | ) public ERC20Detailed(name, symbol, decimals) { 12 | _mint(msg.sender, 1000000 * (10**uint256(decimals))); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /contracts/test-helpers/MockWETH.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.5.16; 2 | 3 | import "openzeppelin-solidity-2.3.0/contracts/token/ERC20/ERC20.sol"; 4 | import "openzeppelin-solidity-2.3.0/contracts/token/ERC20/ERC20Detailed.sol"; 5 | 6 | // IWETH 7 | contract MockWETH is ERC20, ERC20Detailed { 8 | constructor() public ERC20Detailed("Wrapped Ether", "WETH", 18) { 9 | _mint(msg.sender, 1000000 * (10**18)); 10 | } 11 | 12 | function deposit() external { 13 | revert("Unimplemented for OVM"); 14 | } 15 | 16 | function withdraw(uint amount) external { 17 | amount; 18 | revert("Unimplemented for OVM"); 19 | } 20 | 21 | function mint(address account, uint256 amount) external { 22 | _mint(account, amount); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /contracts/test-helpers/MockWrapperFactory.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.5.16; 2 | 3 | import "../SafeDecimalMath.sol"; 4 | 5 | contract MockWrapperFactory { 6 | using SafeMath for uint; 7 | using SafeDecimalMath for uint; 8 | 9 | uint public totalIssuedSynths; 10 | 11 | constructor() public {} 12 | 13 | function setTotalIssuedSynths(uint value) external { 14 | totalIssuedSynths = value; 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /contracts/test-helpers/OneWeekSetup.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.5.16; 2 | 3 | import "../LimitedSetup.sol"; 4 | 5 | contract OneWeekSetup is LimitedSetup(1 weeks) { 6 | function testFunc() public view onlyDuringSetup returns (bool) { 7 | return true; 8 | } 9 | 10 | function publicSetupExpiryTime() public view returns (uint) { 11 | return setupExpiryTime; 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /contracts/test-helpers/PublicEST.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.5.16; 2 | 3 | import "../interfaces/IRewardEscrowV2.sol"; 4 | import "../ExternStateToken.sol"; 5 | 6 | contract PublicEST is ExternStateToken { 7 | uint8 public constant DECIMALS = 18; 8 | 9 | constructor( 10 | address payable _proxy, 11 | TokenState _tokenState, 12 | string memory _name, 13 | string memory _symbol, 14 | uint _totalSupply, 15 | address _owner 16 | ) public ExternStateToken(_proxy, _tokenState, _name, _symbol, _totalSupply, DECIMALS, _owner) {} 17 | 18 | function transfer(address to, uint value) external optionalProxy returns (bool) { 19 | return _transferByProxy(messageSender, to, value); 20 | } 21 | 22 | function transferFrom( 23 | address from, 24 | address to, 25 | uint value 26 | ) external optionalProxy returns (bool) { 27 | return _transferFromByProxy(messageSender, from, to, value); 28 | } 29 | 30 | // Index all parameters to make them easier to find in raw logs (as this will be emitted via a proxy and not decoded) 31 | event Received(address indexed sender, uint256 indexed inputA, bytes32 indexed inputB); 32 | 33 | function somethingToBeProxied(uint256 inputA, bytes32 inputB) external { 34 | emit Received(messageSender, inputA, inputB); 35 | } 36 | 37 | // SIP-252: allow to call revokeFrom on rewardsEscrow 38 | // this is needed here because SNX is both the required caller for this method, and needs to be an actual ERC20, 39 | // so using an EOA instead of it doesn't work 40 | function revokeFrom( 41 | address rewardEscrowV2, 42 | address account, 43 | address recipient, 44 | uint targetAmount, 45 | uint startIndex 46 | ) external { 47 | IRewardEscrowV2(rewardEscrowV2).revokeFrom(account, recipient, targetAmount, startIndex); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /contracts/test-helpers/PublicEST8Decimals.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.5.16; 2 | 3 | import "../ExternStateToken.sol"; 4 | 5 | contract PublicEST8Decimals is ExternStateToken { 6 | uint8 public constant DECIMALS = 8; 7 | 8 | constructor( 9 | address payable _proxy, 10 | TokenState _tokenState, 11 | string memory _name, 12 | string memory _symbol, 13 | uint _totalSupply, 14 | address _owner 15 | ) public ExternStateToken(_proxy, _tokenState, _name, _symbol, _totalSupply, DECIMALS, _owner) {} 16 | 17 | function transfer(address to, uint value) external optionalProxy returns (bool) { 18 | return _transferByProxy(messageSender, to, value); 19 | } 20 | 21 | function transferFrom( 22 | address from, 23 | address to, 24 | uint value 25 | ) external optionalProxy returns (bool) { 26 | return _transferFromByProxy(messageSender, from, to, value); 27 | } 28 | 29 | // Index all parameters to make them easier to find in raw logs (as this will be emitted via a proxy and not decoded) 30 | event Received(address indexed sender, uint256 indexed inputA, bytes32 indexed inputB); 31 | 32 | function somethingToBeProxied(uint256 inputA, bytes32 inputB) external { 33 | emit Received(messageSender, inputA, inputB); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /contracts/test-helpers/PublicMath.sol: -------------------------------------------------------------------------------- 1 | /* PublicMath.sol: expose the internal functions in Math library 2 | * for testing purposes. 3 | */ 4 | pragma solidity ^0.5.16; 5 | 6 | import "../Math.sol"; 7 | 8 | contract PublicMath { 9 | using Math for uint; 10 | 11 | function powerDecimal(uint x, uint y) public pure returns (uint) { 12 | return x.powDecimal(y); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /contracts/test-helpers/PublicSafeDecimalMath.sol: -------------------------------------------------------------------------------- 1 | /* PublicSafeDecimalMath.sol: expose the internal functions in SafeDecimalMath 2 | * for testing purposes. 3 | */ 4 | pragma solidity ^0.5.16; 5 | 6 | import "../SafeDecimalMath.sol"; 7 | 8 | contract PublicSafeDecimalMath { 9 | using SafeDecimalMath for uint; 10 | 11 | function unit() public pure returns (uint) { 12 | return SafeDecimalMath.unit(); 13 | } 14 | 15 | function preciseUnit() public pure returns (uint) { 16 | return SafeDecimalMath.preciseUnit(); 17 | } 18 | 19 | function multiplyDecimal(uint x, uint y) public pure returns (uint) { 20 | return x.multiplyDecimal(y); 21 | } 22 | 23 | function multiplyDecimalRound(uint x, uint y) public pure returns (uint) { 24 | return x.multiplyDecimalRound(y); 25 | } 26 | 27 | function multiplyDecimalRoundPrecise(uint x, uint y) public pure returns (uint) { 28 | return x.multiplyDecimalRoundPrecise(y); 29 | } 30 | 31 | function divideDecimal(uint x, uint y) public pure returns (uint) { 32 | return x.divideDecimal(y); 33 | } 34 | 35 | function divideDecimalRound(uint x, uint y) public pure returns (uint) { 36 | return x.divideDecimalRound(y); 37 | } 38 | 39 | function divideDecimalRoundPrecise(uint x, uint y) public pure returns (uint) { 40 | return x.divideDecimalRoundPrecise(y); 41 | } 42 | 43 | function decimalToPreciseDecimal(uint i) public pure returns (uint) { 44 | return i.decimalToPreciseDecimal(); 45 | } 46 | 47 | function preciseDecimalToDecimal(uint i) public pure returns (uint) { 48 | return i.preciseDecimalToDecimal(); 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /contracts/test-helpers/TestableAddressSet.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.5.16; 2 | 3 | import "../AddressSetLib.sol"; 4 | 5 | contract TestableAddressSet { 6 | using AddressSetLib for AddressSetLib.AddressSet; 7 | 8 | AddressSetLib.AddressSet internal set; 9 | 10 | function contains(address candidate) public view returns (bool) { 11 | return set.contains(candidate); 12 | } 13 | 14 | function getPage(uint index, uint pageSize) public view returns (address[] memory) { 15 | return set.getPage(index, pageSize); 16 | } 17 | 18 | function add(address element) public { 19 | set.add(element); 20 | } 21 | 22 | function remove(address element) public { 23 | set.remove(element); 24 | } 25 | 26 | function size() public view returns (uint) { 27 | return set.elements.length; 28 | } 29 | 30 | function element(uint index) public view returns (address) { 31 | return set.elements[index]; 32 | } 33 | 34 | function index(address element) public view returns (uint) { 35 | return set.indices[element]; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /contracts/test-helpers/TestableAddressSetProxyable.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.5.16; 2 | 3 | import "./TestableAddressSet.sol"; 4 | import "../Owned.sol"; 5 | import "../Proxyable.sol"; 6 | 7 | contract TestableAddressSetProxyable is Owned, Proxyable, TestableAddressSet { 8 | constructor(address payable _proxy, address _owner) public Owned(_owner) Proxyable(_proxy) {} 9 | } 10 | -------------------------------------------------------------------------------- /contracts/test-helpers/TestableBytes32Set.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.5.16; 2 | 3 | import "../Bytes32SetLib.sol"; 4 | 5 | contract TestableBytes32Set { 6 | using Bytes32SetLib for Bytes32SetLib.Bytes32Set; 7 | 8 | Bytes32SetLib.Bytes32Set internal set; 9 | 10 | function contains(bytes32 candidate) public view returns (bool) { 11 | return set.contains(candidate); 12 | } 13 | 14 | function getPage(uint index, uint pageSize) public view returns (bytes32[] memory) { 15 | return set.getPage(index, pageSize); 16 | } 17 | 18 | function add(bytes32 element) public { 19 | set.add(element); 20 | } 21 | 22 | function remove(bytes32 element) public { 23 | set.remove(element); 24 | } 25 | 26 | function size() public view returns (uint) { 27 | return set.elements.length; 28 | } 29 | 30 | function element(uint index) public view returns (bytes32) { 31 | return set.elements[index]; 32 | } 33 | 34 | function index(bytes32 element) public view returns (uint) { 35 | return set.indices[element]; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /contracts/test-helpers/TestableBytes32SetProxyable.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.5.16; 2 | 3 | import "./TestableBytes32Set.sol"; 4 | import "../Owned.sol"; 5 | import "../Proxyable.sol"; 6 | 7 | contract TestableBytes32SetProxyable is Owned, Proxyable, TestableBytes32Set { 8 | constructor(address payable _proxy, address _owner) public Owned(_owner) Proxyable(_proxy) {} 9 | } 10 | -------------------------------------------------------------------------------- /contracts/test-helpers/TestableDebtCache.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.5.16; 2 | 3 | // Inheritance 4 | import "../DebtCache.sol"; 5 | 6 | contract TestableDebtCache is DebtCache { 7 | constructor(address _owner, address _resolver) public DebtCache(_owner, _resolver) {} 8 | 9 | function setCachedSynthDebt(bytes32 currencyKey, uint debt) public { 10 | _cachedSynthDebt[currencyKey] = debt; 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /contracts/test-helpers/TestableDynamicFee.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.5.16; 2 | pragma experimental ABIEncoderV2; 3 | // Libraries 4 | import "../Exchanger.sol"; 5 | 6 | contract TestableDynamicFee is Exchanger { 7 | constructor(address _owner, address _resolver) public Exchanger(_owner, _resolver) {} 8 | 9 | function thresholdedAbsDeviationRatio( 10 | uint price, 11 | uint previousPrice, 12 | uint threshold 13 | ) external view returns (uint) { 14 | return _thresholdedAbsDeviationRatio(price, previousPrice, threshold); 15 | } 16 | 17 | function dynamicFeeCalculation( 18 | uint[] calldata prices, 19 | uint threshold, 20 | uint weightDecay 21 | ) external view returns (uint) { 22 | return _dynamicFeeCalculation(prices, threshold, weightDecay); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /contracts/test-helpers/TestableMinimalProxyFactory.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.5.16; 2 | 3 | import "../MinimalProxyFactory.sol"; 4 | 5 | contract TestableMinimalProxyFactory is MinimalProxyFactory { 6 | function cloneAsMinimalProxy(address _base, string calldata _revertMsg) external returns (address clone) { 7 | clone = _cloneAsMinimalProxy(_base, _revertMsg); 8 | emit CloneDeployed(clone, _base); 9 | 10 | return clone; 11 | } 12 | 13 | function generateMinimalProxyCreateData(address _base) external pure returns (bytes memory) { 14 | return _generateMinimalProxyCreateData(_base); 15 | } 16 | 17 | event CloneDeployed(address clone, address base); 18 | } 19 | -------------------------------------------------------------------------------- /contracts/test-helpers/TestableMixinResolver.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.5.16; 2 | 3 | import "../Owned.sol"; 4 | import "../MixinResolver.sol"; 5 | 6 | contract TestableMixinResolver is Owned, MixinResolver { 7 | bytes32 private constant CONTRACT_EXAMPLE_1 = "Example_1"; 8 | bytes32 private constant CONTRACT_EXAMPLE_2 = "Example_2"; 9 | bytes32 private constant CONTRACT_EXAMPLE_3 = "Example_3"; 10 | 11 | bytes32[24] private addressesToCache = [CONTRACT_EXAMPLE_1, CONTRACT_EXAMPLE_2, CONTRACT_EXAMPLE_3]; 12 | 13 | constructor(address _owner, address _resolver) public Owned(_owner) MixinResolver(_resolver) {} 14 | 15 | function resolverAddressesRequired() public view returns (bytes32[] memory addresses) { 16 | addresses = new bytes32[](3); 17 | addresses[0] = CONTRACT_EXAMPLE_1; 18 | addresses[1] = CONTRACT_EXAMPLE_2; 19 | addresses[2] = CONTRACT_EXAMPLE_3; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /contracts/test-helpers/TestablePausable.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.5.16; 2 | 3 | import "../Owned.sol"; 4 | import "../Pausable.sol"; 5 | 6 | /** 7 | * @title An implementation of Pausable. Used to test the features of the Pausable contract that can only be tested by an implementation. 8 | */ 9 | contract TestablePausable is Owned, Pausable { 10 | uint public someValue; 11 | 12 | constructor(address _owner) public Owned(_owner) Pausable() {} 13 | 14 | function setSomeValue(uint _value) external notPaused { 15 | someValue = _value; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /contracts/test-helpers/TestableProxyable.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.5.16; 2 | 3 | import "../Owned.sol"; 4 | import "../Proxyable.sol"; 5 | 6 | contract TestableProxyable is Owned, Proxyable { 7 | constructor(address payable _proxy, address _owner) public Owned(_owner) Proxyable(_proxy) {} 8 | 9 | event SomeEvent(uint); 10 | bytes32 internal constant SOMEEVENT_SIG = keccak256("SomeEvent(uint)"); 11 | 12 | function emitSomeEvent() external { 13 | proxy._emit(abi.encode(0), 1, SOMEEVENT_SIG, 0, 0, 0); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /contracts/test-helpers/TestableState.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.5.16; 2 | 3 | import "../Owned.sol"; 4 | import "../State.sol"; 5 | 6 | contract TestableState is Owned, State { 7 | constructor(address _owner, address _associatedContract) public Owned(_owner) State(_associatedContract) {} 8 | 9 | function testModifier() external onlyAssociatedContract {} 10 | } 11 | -------------------------------------------------------------------------------- /contracts/test-helpers/TestableStateShared.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.5.16; 2 | 3 | import "../Owned.sol"; 4 | import "../StateShared.sol"; 5 | 6 | contract TestableStateShared is Owned, StateShared { 7 | constructor(address _owner, address[] memory _associatedContracts) 8 | public 9 | Owned(_owner) 10 | StateShared(_associatedContracts) 11 | {} 12 | 13 | function testModifier() external onlyAssociatedContracts {} 14 | } 15 | -------------------------------------------------------------------------------- /contracts/test-helpers/TestableTempOwned.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.5.16; 2 | 3 | import "../TemporarilyOwned.sol"; 4 | 5 | contract TestableTempOwned is TemporarilyOwned { 6 | uint public testValue; 7 | 8 | constructor(address _temporaryOwner, uint _ownershipDuration) 9 | public 10 | TemporarilyOwned(_temporaryOwner, _ownershipDuration) 11 | {} 12 | 13 | function setTestValue(uint _testValue) external onlyTemporaryOwner { 14 | testValue = _testValue; 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /contracts/test-helpers/UsingReadProxy.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.5.16; 2 | 3 | import "../interfaces/IAddressResolver.sol"; 4 | import "../interfaces/IExchangeRates.sol"; 5 | 6 | contract UsingReadProxy { 7 | IAddressResolver public resolver; 8 | 9 | constructor(IAddressResolver _resolver) public { 10 | resolver = _resolver; 11 | } 12 | 13 | function run(bytes32 currencyKey) external view returns (uint) { 14 | IExchangeRates exRates = IExchangeRates(resolver.getAddress("ExchangeRates")); 15 | require(address(exRates) != address(0), "Missing ExchangeRates"); 16 | return exRates.rateForCurrency(currencyKey); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /examples/browser.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Example for browser envionments 5 | 6 | 7 | 8 |

9 | Open the console and check the window object. Run 10 | npm run pack first to generate browser.js 11 |

12 | 16 | 17 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /funding.json: -------------------------------------------------------------------------------- 1 | { 2 | "opRetro": { 3 | "projectId": "0xcf10a15439ef8c56e1b6c22641544012bfd032c7b584d1160a7d743cb770875b" 4 | } 5 | } -------------------------------------------------------------------------------- /hardhat/extensions/extension-log.js: -------------------------------------------------------------------------------- 1 | const { extendEnvironment } = require('hardhat/config'); 2 | const { gray } = require('chalk'); 3 | 4 | const log = (...text) => console.log(gray(...['└─> [DEBUG]'].concat(text))); 5 | 6 | extendEnvironment(hre => { 7 | hre.log = log; 8 | }); 9 | -------------------------------------------------------------------------------- /hardhat/index.js: -------------------------------------------------------------------------------- 1 | const fs = require('fs'); 2 | const path = require('path'); 3 | 4 | // now require all extensions and tasks 5 | ['extensions', 'tasks'].forEach(folder => 6 | fs 7 | .readdirSync(path.join(__dirname, folder)) 8 | .forEach(mod => require(path.join(__dirname, folder, mod))) 9 | ); 10 | -------------------------------------------------------------------------------- /hardhat/tasks/task-compile.js: -------------------------------------------------------------------------------- 1 | const { task } = require('hardhat/config'); 2 | const { yellow, red } = require('chalk'); 3 | 4 | const optimizeIfRequired = require('../util/optimizeIfRequired'); 5 | 6 | const { collectContractBytesCodes } = require('../util/collectContractBytecodes'); 7 | const { logContractSizes } = require('../../publish/src/contract-size'); 8 | 9 | task('compile') 10 | .addFlag('showsize', 'Show size of compiled contracts') 11 | .addFlag('optimizer', 'Compile with the optimizer') 12 | .addFlag('failOversize', 'Fail if any contract is oversize') 13 | .addFlag('native', 'Compile with the native solc compiler') 14 | .setAction(async (taskArguments, hre, runSuper) => { 15 | if (taskArguments.native) { 16 | hre.config.solc.native = true; 17 | } 18 | 19 | optimizeIfRequired({ hre, taskArguments }); 20 | 21 | await runSuper(taskArguments); 22 | 23 | if (taskArguments.showsize || taskArguments.failOversize) { 24 | const contractToObjectMap = collectContractBytesCodes(); 25 | const sizes = logContractSizes({ contractToObjectMap }); 26 | 27 | if (taskArguments.failOversize) { 28 | const offenders = sizes.filter(entry => +entry.pcent.split('%')[0] > 100); 29 | if (offenders.length > 0) { 30 | const names = offenders.map(o => o.file); 31 | console.log(red('Oversized contracts:'), yellow(`[${names}]`)); 32 | throw new Error( 33 | 'Compilation failed, because some contracts are too big to be deployed. See above.' 34 | ); 35 | } 36 | } 37 | } 38 | }); 39 | -------------------------------------------------------------------------------- /hardhat/tasks/task-describe.js: -------------------------------------------------------------------------------- 1 | const { task } = require('hardhat/config'); 2 | const { gray, green } = require('chalk'); 3 | 4 | const describeSources = require('../util/describeSources'); 5 | 6 | task('describe').setAction(async (taskArguments, hre) => { 7 | await hre.run('compile', taskArguments); 8 | 9 | console.log(gray('Processing Solidity sources and output ASTs...')); 10 | const descriptions = await describeSources({ hre }); 11 | console.log(green(`Done describing ${Object.keys(descriptions).length} sources 💯`)); 12 | }); 13 | -------------------------------------------------------------------------------- /hardhat/tasks/task-test.js: -------------------------------------------------------------------------------- 1 | const { task } = require('hardhat/config'); 2 | const { gray, yellow } = require('chalk'); 3 | const optimizeIfRequired = require('../util/optimizeIfRequired'); 4 | const isCI = require('is-ci'); 5 | 6 | let coverage = false; 7 | 8 | task('coverage').setAction(async (taskArguments, hre, runSuper) => { 9 | coverage = true; 10 | await runSuper(taskArguments); 11 | }); 12 | 13 | task('test') 14 | .addFlag('optimizer', 'Compile with the optimizer') 15 | .addFlag('gas', 'Compile gas usage') 16 | .addFlag('native', 'Compile with the native solc compiler') 17 | .addOptionalParam('gasOutputFile', 'Gas reporter output file') 18 | .setAction(async (taskArguments, hre, runSuper) => { 19 | const { gas, native, gasOutputFile } = taskArguments; 20 | 21 | if (native) { 22 | hre.config.solc.native = true; 23 | } 24 | 25 | optimizeIfRequired({ hre, taskArguments }); 26 | 27 | if (gas) { 28 | console.log(gray(`Enabling ${yellow('gas')} reports, tests will run slower`)); 29 | hre.config.gasReporter.enabled = true; 30 | } 31 | 32 | if (gasOutputFile) { 33 | hre.config.gasReporter.outputFile = gasOutputFile; 34 | } 35 | 36 | // When using CircleCI, output the test metadata 37 | // See https://circleci.com/docs/2.0/collect-test-data 38 | if (isCI && !coverage) { 39 | hre.config.mocha.reporter = 'mocha-junit-reporter'; 40 | hre.config.mocha.reporterOptions = { 41 | mochaFile: '/tmp/junit/test-results.[hash].xml', 42 | }; 43 | } 44 | 45 | await runSuper(taskArguments); 46 | }); 47 | -------------------------------------------------------------------------------- /hardhat/util/collectContractBytecodes.js: -------------------------------------------------------------------------------- 1 | const path = require('path'); 2 | const fs = require('fs'); 3 | const { 4 | constants: { BUILD_FOLDER }, 5 | } = require('../../index'); 6 | 7 | function collectContractBytesCodes() { 8 | // Where hardhat puts compiled contract artifacts 9 | // Should be synthetix/build/artifacts/contracts/ 10 | const builtContractsPath = path.resolve( 11 | __dirname, 12 | '../../', 13 | BUILD_FOLDER, 14 | 'artifacts', 15 | 'contracts' 16 | ); 17 | 18 | // Read all sub-folders within this folder 19 | // Discard folders that don't end with ".sol" 20 | // Eg: 21 | // artifacts/contracts/Synthetix.sol/ 22 | // artifacts/contracts/Exchanger.sol/ 23 | // ... 24 | 25 | const contractBytecodes = {}; 26 | 27 | function searchRecurse({ entryPath }) { 28 | const filesInDir = fs.readdirSync(entryPath); 29 | 30 | for (const contractFolder of filesInDir) { 31 | if (path.extname(contractFolder) === '.sol') { 32 | // Read json files within each folder, 33 | // and collect them in a combined object. 34 | // Eg: 35 | // artifacts/contracts/Synthetix.sol/Synthetix.json 36 | // artifacts/contracts/Exchanger.sol/Exchanger.json 37 | // ... 38 | const contractName = path.basename(contractFolder, '.sol'); 39 | 40 | const jsonFileName = `${contractName}.json`; 41 | const jsonfilePath = path.resolve(entryPath, contractFolder, jsonFileName); 42 | const jsonFileContents = fs.readFileSync(jsonfilePath); 43 | const artifacts = JSON.parse(jsonFileContents); 44 | 45 | contractBytecodes[contractName] = artifacts.deployedBytecode; 46 | } else { 47 | searchRecurse({ entryPath: path.join(entryPath, contractFolder) }); 48 | } 49 | } 50 | } 51 | 52 | searchRecurse({ entryPath: builtContractsPath }); 53 | 54 | return contractBytecodes; 55 | } 56 | 57 | module.exports = { 58 | collectContractBytesCodes, 59 | }; 60 | -------------------------------------------------------------------------------- /hardhat/util/optimizeIfRequired.js: -------------------------------------------------------------------------------- 1 | const { gray, yellow } = require('chalk'); 2 | const { 3 | DEFAULTS: { optimizerRuns }, 4 | } = require('../../publish/src/commands/build'); 5 | 6 | module.exports = ({ hre, taskArguments: { optimizer } }) => { 7 | if (optimizer || hre.optimizer) { 8 | // only show message once if re-run 9 | if (hre.optimizer === undefined) { 10 | console.log(gray('Adding optimizer, runs', yellow(optimizerRuns))); 11 | } 12 | // Use optimizer (slower) but simulates real contract size limits and gas usage 13 | // Note: does not consider actual deployed optimization runs from 14 | // publish/src/contract-overrides.js 15 | for (const compiler of hre.config.solidity.compilers) { 16 | compiler.settings.optimizer = { enabled: true, runs: optimizerRuns }; 17 | } 18 | hre.config.networks.hardhat.allowUnlimitedContractSize = false; 19 | } else { 20 | if (hre.optimizer === undefined) { 21 | console.log(gray('Optimizer disabled. Unlimited contract sizes allowed.')); 22 | } 23 | for (const compiler of hre.config.solidity.compilers) { 24 | compiler.settings.optimizer = { enabled: false }; 25 | } 26 | hre.config.networks.hardhat.allowUnlimitedContractSize = true; 27 | } 28 | 29 | // flag here so that if invoked via "hardhat test" the argument will persist to the compile stage 30 | hre.optimizer = !!optimizer; 31 | }; 32 | -------------------------------------------------------------------------------- /hooks/lint: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # Detect changes in js and sol files 4 | jsChangedFiles=$(git diff --name-only --diff-filter ACMRT --exit-code --staged -- '***.js') 5 | solChangedFiles=$(git diff --name-only --diff-filter ACMRT --exit-code --staged -- '***.sol' ':!contracts/interfaces/*.sol') 6 | isolChangedFiles=$(git diff --name-only --diff-filter ACMRT --exit-code --staged -- 'contracts/interfaces/*.sol') 7 | 8 | # Lint Javascript, only on changed files 9 | if [[ ! -z $jsChangedFiles ]]; then 10 | echo "Javascript changed files [$jsChangedFiles]" 11 | stderrOutput=$(npx eslint $jsChangedFiles --ignore-pattern '!.*' 2>&1) 12 | if [[ ! -z $stderrOutput ]]; then 13 | echo "Javascript lint failed with: $stderrOutput" 14 | exit 1 15 | fi 16 | fi 17 | 18 | # Lint Solidity, only on changed files 19 | if [[ ! -z $solChangedFiles ]]; then 20 | echo "Solidity changed files [$solChangedFiles]" 21 | stderrOutput=$(npx solhint $solChangedFiles 2>&1) 22 | if [[ ! -z $stderrOutput ]]; then 23 | echo "Solidity lint failed with: $stderrOutput" 24 | exit 1 25 | fi 26 | fi 27 | if [[ ! -z $isolChangedFiles ]]; then 28 | echo "Solidity interface files changed [$isolChangedFiles]" 29 | stderrOutput=$(npx solhint $isolChangedFiles --config contracts/interfaces/.solhint.json 2>&1) # Capture stderr 30 | if [[ ! -z $stderrOutput ]]; then 31 | echo "Solidity interface lint failed with: $stderrOutput" 32 | exit 1 33 | fi 34 | fi 35 | -------------------------------------------------------------------------------- /output.txt: -------------------------------------------------------------------------------- 1 | Loading default deployment for network 2 | Using ProxyiETH address of 0xA9859874e1743A32409f75bB11549892138BBA1E 3 | StakingRewardsiETH 4 | Using StakingRewardsiETH address of 0x3f27c540ADaE3a9E8c875C61e3B970b559d7F65d 5 | Loading rewards for synth iETH on network mainnet 6 | Staking rewards StakingRewardsiETH deployed at block 11781285 7 | iETH current price is 774 8 | Exchange fee of sUSD is 0.003 9 | Querying all transfers into the staking contract to find candidate stakers. 10 | 11 | Staking Contract: 0x3f27c540ADaE3a9E8c875C61e3B970b559d7F65d 12 | Synth: 0xA9859874e1743A32409f75bB11549892138BBA1E 13 | Starting Block: 11781285 (853677 blocks ago at 2021/1/3 5:0:31 UTC) 14 | 15 | 138 candidate holders found. Querying their balances. 16 | 17 | |██████████████████████████████████████████████████| - 138 / 138 (100%) 18 | 19 | 9 active stakers found. 20 | 21 | Computing owed sUSD balances for accounts using parameters: 22 | Price: 774 23 | Exchange Fee: 0.3% 24 | 25 | 10.791025799025218434 staked in total. 26 | 8327.197206540182510709 total sUSD owed. 27 | 28 | Saving results to owedBalances.csv... -------------------------------------------------------------------------------- /output_new.txt: -------------------------------------------------------------------------------- 1 | Loading default deployment for network 2 | Using ProxyiETH address of 0xA9859874e1743A32409f75bB11549892138BBA1E 3 | Using StakingRewardsiETH address of 0x3f27c540ADaE3a9E8c875C61e3B970b559d7F65d 4 | Loading rewards for synth iETH on network mainnet 5 | Staking rewards StakingRewardsiETH deployed at block 11781285 6 | iETH current price is 774.0 7 | Exchange fee of sUSD is 0.003 8 | Querying all transfers into the staking contract to find candidate stakers. 9 | 10 | Staking Contract: 0x3f27c540ADaE3a9E8c875C61e3B970b559d7F65d 11 | Synth: 0xA9859874e1743A32409f75bB11549892138BBA1E 12 | Starting Block: 11781285 (855481 blocks ago at 2021/1/3 5:0:31 UTC) 13 | 14 | 138 candidate holders found. Querying their balances. 15 | 16 | |██████████████████████████████████████████████████| - 138 / 138 (100%) 17 | 18 | 9 active stakers found. 19 | 20 | Computing owed sUSD balances for accounts using parameters: 21 | Price: 774.0 22 | Exchange Fee: 0.3% 23 | 24 | 10.791025799025218434 staked in total. 25 | 8327.197206540182510709 total sUSD owed. 26 | 27 | Saving results to owedBalances.csv... -------------------------------------------------------------------------------- /publish/deployed/local-ovm/.gitignore: -------------------------------------------------------------------------------- 1 | # these files are irrelevant outside of a single developer's machine, 2 | # so no need to persist them in source control 3 | owner-actions.json -------------------------------------------------------------------------------- /publish/deployed/local-ovm/.npmignore: -------------------------------------------------------------------------------- 1 | !deployment.json -------------------------------------------------------------------------------- /publish/deployed/local-ovm/deployment.json: -------------------------------------------------------------------------------- 1 | { 2 | "targets": {} 3 | } 4 | -------------------------------------------------------------------------------- /publish/deployed/local-ovm/feeds.json: -------------------------------------------------------------------------------- 1 | { 2 | "SNX": { "asset": "SNX", "feed": "0x0" } 3 | } 4 | -------------------------------------------------------------------------------- /publish/deployed/local-ovm/futures-markets.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "marketKey": "sBTC", 4 | "asset": "sBTC", 5 | "takerFee": "0.003", 6 | "makerFee": "0.002", 7 | "takerFeeNextPrice": "0.001", 8 | "makerFeeNextPrice": "0.0", 9 | "nextPriceConfirmWindow": "2", 10 | "maxLeverage": "10", 11 | "maxMarketValueUSD": "20000000", 12 | "maxFundingRate": "0.1", 13 | "skewScaleUSD": "300000000" 14 | }, 15 | { 16 | "marketKey": "sETH", 17 | "asset": "sETH", 18 | "takerFee": "0.003", 19 | "makerFee": "0.002", 20 | "takerFeeNextPrice": "0.001", 21 | "makerFeeNextPrice": "0.0", 22 | "nextPriceConfirmWindow": "2", 23 | "maxLeverage": "10", 24 | "maxMarketValueUSD": "20000000", 25 | "maxFundingRate": "0.1", 26 | "skewScaleUSD": "300000000" 27 | } 28 | ] 29 | -------------------------------------------------------------------------------- /publish/deployed/local-ovm/index.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | deployment: require('./deployment.json'), 3 | synths: require('./synths.json'), 4 | rewards: require('./rewards.json'), 5 | feeds: require('./feeds.json'), 6 | offchainFeeds: require('./offchain-feeds.json'), 7 | futuresMarkets: require('./futures-markets.json'), 8 | perpsv2Markets: require('./perpsv2-markets.json'), 9 | }; 10 | -------------------------------------------------------------------------------- /publish/deployed/local-ovm/offchain-feeds.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "kind": "pyth", 4 | "oracle": "0xff1a0f4744e8582DF1aE09D5611b887B6a12925C", 5 | "asset": "sETH", 6 | "feedId": "0xca80ba6dc32e08d06f1aa886011eed1d77c77be9eb761cc10d72b7d0a2fd57a6" 7 | }, 8 | { 9 | "kind": "pyth", 10 | "oracle": "0xff1a0f4744e8582DF1aE09D5611b887B6a12925C", 11 | "asset": "sBTC", 12 | "feedId": "0xf9c0172ba10dfa4d19088d94f5bf61d3b54d5bd7483a322a982e1373ee8ea31b" 13 | } 14 | ] 15 | -------------------------------------------------------------------------------- /publish/deployed/local-ovm/params.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "name": "INITIAL_ISSUANCE", 4 | "value": "0" 5 | }, 6 | { 7 | "name": "WAITING_PERIOD_SECS", 8 | "value": "0" 9 | }, 10 | { 11 | "name": "RATE_STALE_PERIOD", 12 | "value": "4200" 13 | }, 14 | { 15 | "name": "COLLATERAL_MANAGER", 16 | "value": { 17 | "SYNTHS": ["sUSD", "sBTC", "sETH"], 18 | "SHORTS": ["sBTC", "sETH"], 19 | "MAX_DEBT": "75000000000000000000000000", 20 | "MAX_SKEW_RATE": "200000000000000000", 21 | "BASE_BORROW_RATE": "950662938", 22 | "BASE_SHORT_RATE": "158443823" 23 | } 24 | }, 25 | { 26 | "name": "COLLATERAL_SHORT", 27 | "value": { 28 | "SYNTHS": ["sBTC", "sETH"], 29 | "MIN_CRATIO": "1200000000000000000", 30 | "MIN_COLLATERAL": "100000000000000000000", 31 | "ISSUE_FEE_RATE": "4000000000000000", 32 | "INTERACTION_DELAY": "0", 33 | "COLLAPSE_FEE_RATE": "0" 34 | } 35 | }, 36 | { 37 | "name": "COLLATERAL_ETH", 38 | "value": { 39 | "SYNTHS": ["sUSD"], 40 | "MIN_CRATIO": "1200000000000000000", 41 | "MIN_COLLATERAL": "100000000000000000", 42 | "ISSUE_FEE_RATE": "0" 43 | } 44 | } 45 | ] 46 | -------------------------------------------------------------------------------- /publish/deployed/local-ovm/perpsv2-markets.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "marketKey": "sBTCPERP", 4 | "asset": "sBTC", 5 | "takerFee": "0.003", 6 | "makerFee": "0.002", 7 | 8 | "takerFeeDelayedOrder": "0.001", 9 | "makerFeeDelayedOrder": "0.0", 10 | "takerFeeOffchainDelayedOrder": "0.0001", 11 | "makerFeeOffchainDelayedOrder": "0.0", 12 | "nextPriceConfirmWindow": "2", 13 | "delayedOrderConfirmWindow": "60", 14 | "minDelayTimeDelta": "30", 15 | "maxDelayTimeDelta": "120", 16 | "offchainDelayedOrderMinAge": "15", 17 | "offchainDelayedOrderMaxAge": "60", 18 | "maxLeverage": "10", 19 | "maxMarketValue": "1500", 20 | "maxFundingVelocity": "0.1", 21 | "skewScale": "50000", 22 | "offchainPriceDivergence": "0.05", 23 | "liquidationPremiumMultiplier": "1", 24 | "offchainMarketKey": "ocBTCPERP", 25 | "maxLiquidationDelta": "0.05", 26 | "maxPD": "0.05", 27 | "liquidationBufferRatio": "0.0025", 28 | "paused": false, 29 | "offchainPaused": false 30 | }, 31 | { 32 | "marketKey": "sETHPERP", 33 | "asset": "sETH", 34 | "takerFee": "0.003", 35 | "makerFee": "0.002", 36 | 37 | "takerFeeDelayedOrder": "0.001", 38 | "makerFeeDelayedOrder": "0.0", 39 | "takerFeeOffchainDelayedOrder": "0.0001", 40 | "makerFeeOffchainDelayedOrder": "0.0", 41 | "nextPriceConfirmWindow": "2", 42 | "delayedOrderConfirmWindow": "60", 43 | "minDelayTimeDelta": "30", 44 | "maxDelayTimeDelta": "120", 45 | "offchainDelayedOrderMinAge": "15", 46 | "offchainDelayedOrderMaxAge": "60", 47 | "maxLeverage": "10", 48 | "maxMarketValue": "20000", 49 | "maxFundingVelocity": "0.1", 50 | "skewScale": "1000000", 51 | "offchainPriceDivergence": "0.05", 52 | "liquidationPremiumMultiplier": "1", 53 | "offchainMarketKey": "ocETHPERP", 54 | "maxLiquidationDelta": "0.05", 55 | "maxPD": "0.05", 56 | "liquidationBufferRatio": "0.0025", 57 | "paused": false, 58 | "offchainPaused": false 59 | } 60 | ] 61 | -------------------------------------------------------------------------------- /publish/deployed/local-ovm/rewards.json: -------------------------------------------------------------------------------- 1 | [] 2 | -------------------------------------------------------------------------------- /publish/deployed/local-ovm/shorting-rewards.json: -------------------------------------------------------------------------------- 1 | [] 2 | -------------------------------------------------------------------------------- /publish/deployed/local-ovm/synths.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "asset": "USD", 4 | "category": "forex", 5 | "sign": "$", 6 | "description": "US Dollars", 7 | "name": "sUSD", 8 | "subclass": "MultiCollateralSynth" 9 | }, 10 | { 11 | "asset": "ETH", 12 | "category": "crypto", 13 | "sign": "Ξ", 14 | "description": "Ether", 15 | "name": "sETH", 16 | "subclass": "MultiCollateralSynth" 17 | }, 18 | { 19 | "asset": "BTC", 20 | "category": "crypto", 21 | "sign": "₿", 22 | "description": "Bitcoin", 23 | "name": "sBTC", 24 | "subclass": "MultiCollateralSynth" 25 | }, 26 | { 27 | "asset": "LINK", 28 | "category": "crypto", 29 | "sign": "", 30 | "description": "Chainlink", 31 | "name": "sLINK", 32 | "subclass": "MultiCollateralSynth" 33 | }, 34 | { 35 | "feed": "0x0", 36 | "asset": "ETHBTC", 37 | "category": "crypto", 38 | "sign": "", 39 | "description": "ETHBTC Ratio", 40 | "name": "sETHBTC", 41 | "subclass": "MultiCollateralSynth" 42 | } 43 | ] 44 | -------------------------------------------------------------------------------- /publish/deployed/local/.gitignore: -------------------------------------------------------------------------------- 1 | # these files are irrelevant outside of a single developer's machine, 2 | # so no need to persist them in source control 3 | deployment.json 4 | owner-actions.json 5 | -------------------------------------------------------------------------------- /publish/deployed/local/deployment.json: -------------------------------------------------------------------------------- 1 | { 2 | "targets": {} 3 | } 4 | -------------------------------------------------------------------------------- /publish/deployed/local/feeds.json: -------------------------------------------------------------------------------- 1 | { 2 | "SNX": { 3 | "asset": "SNX", 4 | "feed": "0x0" 5 | }, 6 | "ETH": { 7 | "asset": "ETH", 8 | "feed": "0x0" 9 | }, 10 | "BTC": { 11 | "asset": "BTC", 12 | "feed": "0x0" 13 | }, 14 | "LINK": { 15 | "asset": "LINK", 16 | "feed": "0x0" 17 | }, 18 | "ETHBTC": { 19 | "asset": "ETHBTC", 20 | "feed": "0x0" 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /publish/deployed/local/futures-markets.json: -------------------------------------------------------------------------------- 1 | [] 2 | -------------------------------------------------------------------------------- /publish/deployed/local/index.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | deployment: require('./deployment.json'), 3 | synths: require('./synths.json'), 4 | rewards: require('./rewards.json'), 5 | feeds: require('./feeds.json'), 6 | offchainFeeds: require('./offchain-feeds.json'), 7 | futuresMarkets: require('./futures-markets.json'), 8 | perpsv2Markets: require('./perpsv2-markets.json'), 9 | }; 10 | -------------------------------------------------------------------------------- /publish/deployed/local/offchain-feeds.json: -------------------------------------------------------------------------------- 1 | [] 2 | -------------------------------------------------------------------------------- /publish/deployed/local/params.json: -------------------------------------------------------------------------------- 1 | [] 2 | -------------------------------------------------------------------------------- /publish/deployed/local/perpsv2-markets.json: -------------------------------------------------------------------------------- 1 | [] 2 | -------------------------------------------------------------------------------- /publish/deployed/local/rewards.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "name": "sETHUniswapV1", 4 | "stakingToken": "0xe9cf7887b93150d4f2da7dfc6d502b216438f244", 5 | "rewardsToken": "Synthetix" 6 | }, 7 | { 8 | "name": "sXAUUniswapV2", 9 | "stakingToken": "0x34a0216C5057bC18e5d34D4405284564eFd759b2", 10 | "rewardsToken": "Synthetix" 11 | }, 12 | { 13 | "name": "sUSDCurve", 14 | "stakingToken": "0xc25a3a3b969415c80451098fa907ec722572917f", 15 | "rewardsToken": "Synthetix" 16 | }, 17 | { 18 | "name": "SNXBalancer", 19 | "stakingToken": "0x815f8ef4863451f4faf34fbc860034812e7377d9", 20 | "rewardsToken": "Synthetix" 21 | } 22 | ] 23 | -------------------------------------------------------------------------------- /publish/deployed/local/shorting-rewards.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "name": "sETH", 4 | "rewardsToken": "Synthetix" 5 | }, 6 | { 7 | "name": "sBTC", 8 | "rewardsToken": "Synthetix" 9 | } 10 | ] 11 | -------------------------------------------------------------------------------- /publish/deployed/local/synths.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "asset": "USD", 4 | "category": "forex", 5 | "sign": "$", 6 | "description": "US Dollars", 7 | "name": "sUSD", 8 | "subclass": "MultiCollateralSynth" 9 | }, 10 | { 11 | "feed": "0x0", 12 | "asset": "BTC", 13 | "category": "crypto", 14 | "sign": "₿", 15 | "description": "Bitcoin", 16 | "name": "sBTC", 17 | "subclass": "MultiCollateralSynth" 18 | }, 19 | { 20 | "feed": "0x0", 21 | "asset": "ETH", 22 | "category": "crypto", 23 | "sign": "Ξ", 24 | "description": "Ether", 25 | "name": "sETH", 26 | "subclass": "MultiCollateralSynth" 27 | }, 28 | { 29 | "feed": "0x0", 30 | "asset": "LINK", 31 | "category": "crypto", 32 | "sign": "", 33 | "description": "Chainlink", 34 | "name": "sLINK", 35 | "subclass": "MultiCollateralSynth" 36 | }, 37 | { 38 | "feed": "0x0", 39 | "asset": "ETHBTC", 40 | "category": "crypto", 41 | "sign": "", 42 | "description": "ETHBTC Ratio", 43 | "name": "sETHBTC", 44 | "subclass": "MultiCollateralSynth" 45 | } 46 | ] 47 | -------------------------------------------------------------------------------- /publish/deployed/mainnet-ovm/index.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | deployment: require('./deployment.json'), 3 | versions: require('./versions.json'), 4 | synths: require('./synths.json'), 5 | rewards: require('./rewards.json'), 6 | feeds: require('./feeds.json'), 7 | offchainFeeds: require('./offchain-feeds.json'), 8 | futuresMarkets: require('./futures-markets.json'), 9 | perpsv2Markets: require('./perpsv2-markets.json'), 10 | }; 11 | -------------------------------------------------------------------------------- /publish/deployed/mainnet-ovm/owner-actions.json: -------------------------------------------------------------------------------- 1 | {} 2 | -------------------------------------------------------------------------------- /publish/deployed/mainnet-ovm/params.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "name": "INITIAL_ISSUANCE", 4 | "value": "0" 5 | }, 6 | { 7 | "name": "WAITING_PERIOD_SECS", 8 | "value": "0" 9 | }, 10 | { 11 | "name": "RATE_STALE_PERIOD", 12 | "value": "4200" 13 | }, 14 | { 15 | "name": "LIQUIDATION_DELAY", 16 | "value": "43200" 17 | }, 18 | { 19 | "name": "LIQUIDATION_RATIO", 20 | "value": "666666666666666666" 21 | }, 22 | { 23 | "name": "FLAG_REWARD", 24 | "value": "1000000000000000000" 25 | }, 26 | { 27 | "name": "LIQUIDATE_REWARD", 28 | "value": "2000000000000000000" 29 | }, 30 | { 31 | "name": "FUTURES_LIQUIDATION_BUFFER_RATIO", 32 | "value": "10000000000000000" 33 | }, 34 | { 35 | "name": "COLLATERAL_MANAGER", 36 | "value": { 37 | "SYNTHS": [ 38 | "sUSD", 39 | "sBTC", 40 | "sETH", 41 | "sLINK", 42 | "sSOL", 43 | "sAVAX", 44 | "sMATIC", 45 | "sEUR" 46 | ], 47 | "SHORTS": ["sBTC", "sETH", "sLINK", "sSOL", "sAVAX", "sMATIC", "sEUR"], 48 | "MAX_DEBT": "75000000000000000000000000", 49 | "MAX_SKEW_RATE": "200000000000000000", 50 | "BASE_BORROW_RATE": "950662938", 51 | "BASE_SHORT_RATE": "158443823" 52 | } 53 | }, 54 | { 55 | "name": "COLLATERAL_SHORT", 56 | "value": { 57 | "SYNTHS": [ 58 | "sBTC", 59 | "sETH", 60 | "sLINK", 61 | "sSOL", 62 | "sAVAX", 63 | "sMATIC", 64 | "sUNI", 65 | "sAAVE" 66 | ], 67 | "MIN_CRATIO": "1200000000000000000", 68 | "MIN_COLLATERAL": "100000000000000000000", 69 | "ISSUE_FEE_RATE": "4000000000000000", 70 | "INTERACTION_DELAY": "0", 71 | "COLLAPSE_FEE_RATE": "0" 72 | } 73 | }, 74 | { 75 | "name": "COLLATERAL_ETH", 76 | "value": { 77 | "SYNTHS": ["sUSD", "sETH"], 78 | "ISSUE_FEE_RATE": "0" 79 | } 80 | }, 81 | { 82 | "name": "FUTURES_MIN_KEEPER_FEE", 83 | "value": "4000000000000000000" 84 | }, 85 | { 86 | "name": "FUTURES_MAX_KEEPER_FEE", 87 | "value": "100000000000000000000" 88 | }, 89 | { 90 | "name": "FUTURES_LIQUIDATION_FEE_RATIO", 91 | "value": "200000000000000" 92 | } 93 | ] 94 | -------------------------------------------------------------------------------- /publish/deployed/mainnet-ovm/rewards.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "name": "sUSDDAIUniswapV3", 4 | "stakingToken": "0x88ccdbba89e073c5dc08b9c84dfc1fdc152c0dac", 5 | "rewardsToken": "ProxyERC20" 6 | }, 7 | { 8 | "name": "SNXWETHUniswapV3", 9 | "stakingToken": "0x83beefb4ca39af649d03969b442c0e9f4e1732d8", 10 | "rewardsToken": "ProxyERC20" 11 | } 12 | ] 13 | -------------------------------------------------------------------------------- /publish/deployed/mainnet-ovm/synths.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "name": "sUSD", 4 | "asset": "USD", 5 | "subclass": "MultiCollateralSynth" 6 | }, 7 | { 8 | "name": "sETH", 9 | "asset": "ETH", 10 | "subclass": "MultiCollateralSynth" 11 | }, 12 | { 13 | "name": "sBTC", 14 | "asset": "BTC", 15 | "subclass": "MultiCollateralSynth" 16 | }, 17 | { 18 | "name": "sEUR", 19 | "asset": "EUR", 20 | "subclass": "MultiCollateralSynth" 21 | } 22 | ] 23 | -------------------------------------------------------------------------------- /publish/deployed/mainnet/feeds.json: -------------------------------------------------------------------------------- 1 | { 2 | "SNX": { 3 | "asset": "SNX", 4 | "feed": "0xDC3EA94CD0AC27d9A86C180091e7f78C683d3699" 5 | }, 6 | "ETH": { 7 | "asset": "ETH", 8 | "feed": "0x5f4eC3Df9cbd43714FE2740f5E3616155c5b8419" 9 | }, 10 | "BTC": { 11 | "asset": "BTC", 12 | "feed": "0xF4030086522a5bEEa4988F8cA5B36dbC97BeE88c" 13 | }, 14 | "ETHBTC": { 15 | "asset": "ETHBTC", 16 | "feed": "0xAc559F25B1619171CbC396a50854A3240b6A4e99" 17 | }, 18 | "EUR": { 19 | "asset": "EUR", 20 | "feed": "0xb49f677943BC038e9857d61E7d053CaA2C1734C1" 21 | }, 22 | "JPY": { 23 | "asset": "JPY", 24 | "feed": "0xBcE206caE7f0ec07b545EddE332A47C2F75bbeb3" 25 | }, 26 | "AUD": { 27 | "asset": "AUD", 28 | "feed": "0x77F9710E7d0A19669A13c055F62cd80d313dF022" 29 | }, 30 | "GBP": { 31 | "asset": "GBP", 32 | "feed": "0x5c0Ab2d9b5a7ed9f470386e82BB36A3613cDd4b5" 33 | }, 34 | "CHF": { 35 | "asset": "CHF", 36 | "feed": "0x449d117117838fFA61263B61dA6301AA2a88B13A" 37 | }, 38 | "KRW": { 39 | "asset": "KRW", 40 | "feed": "0x01435677FB11763550905594A16B645847C1d0F3" 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /publish/deployed/mainnet/futures-markets.json: -------------------------------------------------------------------------------- 1 | [] 2 | -------------------------------------------------------------------------------- /publish/deployed/mainnet/index.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | deployment: require('./deployment.json'), 3 | versions: require('./versions.json'), 4 | synths: require('./synths.json'), 5 | rewards: require('./rewards.json'), 6 | feeds: require('./feeds.json'), 7 | offchainFeeds: require('./offchain-feeds.json'), 8 | futuresMarkets: require('./futures-markets.json'), 9 | perpsv2Markets: require('./perpsv2-markets.json'), 10 | }; 11 | -------------------------------------------------------------------------------- /publish/deployed/mainnet/offchain-feeds.json: -------------------------------------------------------------------------------- 1 | [] 2 | -------------------------------------------------------------------------------- /publish/deployed/mainnet/owner-actions.json: -------------------------------------------------------------------------------- 1 | {} 2 | -------------------------------------------------------------------------------- /publish/deployed/mainnet/params.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "name": "EXCHANGE_DYNAMIC_FEE_ROUNDS", 4 | "value": "0" 5 | }, 6 | { 7 | "name": "DEX_PRICE_AGGREGATOR", 8 | "value": "0x228bCc970003Ca7588337604AFD9Fc5d92bF1C8B" 9 | }, 10 | { 11 | "name": "ATOMIC_EQUIVALENTS_ON_DEX", 12 | "value": { 13 | "sUSD": { 14 | "currencyKey": "sUSD", 15 | "equivalent": "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48", 16 | "token": "USDC" 17 | }, 18 | "sETH": { 19 | "currencyKey": "sETH", 20 | "equivalent": "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2", 21 | "token": "WETH" 22 | }, 23 | "sBTC": { 24 | "currencyKey": "sBTC", 25 | "equivalent": "0x2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599", 26 | "token": "WBTC" 27 | } 28 | } 29 | }, 30 | { 31 | "name": "ATOMIC_EXCHANGE_FEE_RATES", 32 | "value": { 33 | "sETH": "3000000000000000", 34 | "sBTC": "3000000000000000", 35 | "sUSD": "3000000000000000" 36 | } 37 | }, 38 | { 39 | "name": "ATOMIC_VOLATILITY_CONSIDERATION_WINDOW", 40 | "value": { 41 | "sETH": "600", 42 | "sBTC": "600" 43 | } 44 | }, 45 | { 46 | "name": "ATOMIC_VOLATILITY_UPDATE_THRESHOLD", 47 | "value": { 48 | "sETH": "3", 49 | "sBTC": "3" 50 | } 51 | }, 52 | { 53 | "name": "LIQUIDATION_DELAY", 54 | "value": "43200" 55 | }, 56 | { 57 | "name": "LIQUIDATION_RATIO", 58 | "value": "666666666666666666" 59 | }, 60 | { 61 | "name": "COLLATERAL_ETH", 62 | "value": { 63 | "SYNTHS": ["sUSD", "sETH"], 64 | "ISSUE_FEE_RATE": "0", 65 | "MIN_CRATIO": "1300000000000000000", 66 | "MIN_COLLATERAL": "2000000000000000000" 67 | } 68 | }, 69 | { 70 | "name": "ETHER_WRAPPER_MAX_ETH", 71 | "value": "0" 72 | } 73 | ] 74 | -------------------------------------------------------------------------------- /publish/deployed/mainnet/perpsv2-markets.json: -------------------------------------------------------------------------------- 1 | [] 2 | -------------------------------------------------------------------------------- /publish/deployed/mainnet/shorting-rewards.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "name": "sETH", 4 | "rewardsToken": "ProxyERC20" 5 | }, 6 | { 7 | "name": "sBTC", 8 | "rewardsToken": "ProxyERC20" 9 | } 10 | ] 11 | -------------------------------------------------------------------------------- /publish/deployed/mainnet/synths.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "name": "sUSD", 4 | "asset": "USD", 5 | "subclass": "MultiCollateralSynth" 6 | }, 7 | { 8 | "name": "sEUR", 9 | "asset": "EUR", 10 | "subclass": "MultiCollateralSynth" 11 | }, 12 | { 13 | "name": "sJPY", 14 | "asset": "JPY", 15 | "subclass": "MultiCollateralSynth" 16 | }, 17 | { 18 | "name": "sAUD", 19 | "asset": "AUD", 20 | "subclass": "MultiCollateralSynth" 21 | }, 22 | { 23 | "name": "sGBP", 24 | "asset": "GBP", 25 | "subclass": "MultiCollateralSynth" 26 | }, 27 | { 28 | "name": "sCHF", 29 | "asset": "CHF", 30 | "subclass": "MultiCollateralSynth" 31 | }, 32 | { 33 | "name": "sKRW", 34 | "asset": "KRW", 35 | "subclass": "MultiCollateralSynth" 36 | }, 37 | { 38 | "name": "sBTC", 39 | "asset": "BTC", 40 | "subclass": "MultiCollateralSynth" 41 | }, 42 | { 43 | "name": "sETH", 44 | "asset": "ETH", 45 | "subclass": "MultiCollateralSynth" 46 | }, 47 | { 48 | "name": "sETHBTC", 49 | "asset": "ETHBTC", 50 | "subclass": "MultiCollateralSynth" 51 | } 52 | ] 53 | -------------------------------------------------------------------------------- /publish/deployed/sepolia-ovm/futures-markets.json: -------------------------------------------------------------------------------- 1 | [] 2 | -------------------------------------------------------------------------------- /publish/deployed/sepolia-ovm/index.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | deployment: require('./deployment.json'), 3 | versions: require('./versions.json'), 4 | synths: require('./synths.json'), 5 | rewards: require('./rewards.json'), 6 | feeds: require('./feeds.json'), 7 | offchainFeeds: require('./offchain-feeds.json'), 8 | futuresMarkets: require('./futures-markets.json'), 9 | perpsv2Markets: require('./perpsv2-markets.json'), 10 | }; 11 | -------------------------------------------------------------------------------- /publish/deployed/sepolia-ovm/owner-actions.json: -------------------------------------------------------------------------------- 1 | {} 2 | -------------------------------------------------------------------------------- /publish/deployed/sepolia-ovm/params.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "name": "INITIAL_ISSUANCE", 4 | "value": "0" 5 | }, 6 | { 7 | "name": "WAITING_PERIOD_SECS", 8 | "value": "0" 9 | }, 10 | { 11 | "name": "RATE_STALE_PERIOD", 12 | "value": "4200" 13 | }, 14 | { 15 | "name": "LIQUIDATION_DELAY", 16 | "value": "43200" 17 | }, 18 | { 19 | "name": "LIQUIDATION_RATIO", 20 | "value": "666666666666666666" 21 | }, 22 | { 23 | "name": "FLAG_REWARD", 24 | "value": "1000000000000000000" 25 | }, 26 | { 27 | "name": "LIQUIDATE_REWARD", 28 | "value": "2000000000000000000" 29 | }, 30 | { 31 | "name": "FUTURES_LIQUIDATION_BUFFER_RATIO", 32 | "value": "10000000000000000" 33 | }, 34 | { 35 | "name": "COLLATERAL_MANAGER", 36 | "value": { 37 | "SYNTHS": ["sUSD", "sBTC", "sETH"], 38 | "SHORTS": ["sBTC", "sETH"], 39 | "MAX_DEBT": "75000000000000000000000000", 40 | "MAX_SKEW_RATE": "200000000000000000", 41 | "BASE_BORROW_RATE": "950662938", 42 | "BASE_SHORT_RATE": "158443823" 43 | } 44 | }, 45 | { 46 | "name": "COLLATERAL_SHORT", 47 | "value": { 48 | "SYNTHS": ["sBTC", "sETH"], 49 | "MIN_CRATIO": "1200000000000000000", 50 | "MIN_COLLATERAL": "100000000000000000000", 51 | "ISSUE_FEE_RATE": "4000000000000000", 52 | "INTERACTION_DELAY": "0", 53 | "COLLAPSE_FEE_RATE": "0" 54 | } 55 | }, 56 | { 57 | "name": "COLLATERAL_ETH", 58 | "value": { 59 | "SYNTHS": ["sUSD", "sETH"], 60 | "ISSUE_FEE_RATE": "0" 61 | } 62 | } 63 | ] 64 | -------------------------------------------------------------------------------- /publish/deployed/sepolia-ovm/rewards.json: -------------------------------------------------------------------------------- 1 | [] 2 | -------------------------------------------------------------------------------- /publish/deployed/sepolia-ovm/shorting-rewards.json: -------------------------------------------------------------------------------- 1 | [] 2 | -------------------------------------------------------------------------------- /publish/deployed/sepolia-ovm/synths.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "name": "sUSD", 4 | "asset": "USD", 5 | "subclass": "MultiCollateralSynth" 6 | }, 7 | { 8 | "name": "sETH", 9 | "asset": "ETH", 10 | "subclass": "MultiCollateralSynth" 11 | }, 12 | { 13 | "name": "sBTC", 14 | "asset": "BTC", 15 | "subclass": "MultiCollateralSynth" 16 | } 17 | ] 18 | -------------------------------------------------------------------------------- /publish/deployed/sepolia/feeds.json: -------------------------------------------------------------------------------- 1 | { 2 | "SNX": { 3 | "asset": "SNX", 4 | "feed": "0xc0F82A46033b8BdBA4Bb0B0e28Bc2006F64355bC" 5 | }, 6 | "ETH": { 7 | "asset": "ETH", 8 | "feed": "0x694AA1769357215DE4FAC081bf1f309aDC325306" 9 | }, 10 | "BTC": { 11 | "asset": "BTC", 12 | "feed": "0x1b44F3514812d835EB1BDB0acB33d3fA3351Ee43" 13 | }, 14 | "LINK": { 15 | "asset": "LINK", 16 | "feed": "0xc59E3633BAAC79493d908e63626716e204A45EdF" 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /publish/deployed/sepolia/futures-markets.json: -------------------------------------------------------------------------------- 1 | [] 2 | -------------------------------------------------------------------------------- /publish/deployed/sepolia/index.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | deployment: require('./deployment.json'), 3 | versions: require('./versions.json'), 4 | synths: require('./synths.json'), 5 | rewards: require('./rewards.json'), 6 | feeds: require('./feeds.json'), 7 | offchainFeeds: require('./offchain-feeds.json'), 8 | futuresMarkets: require('./futures-markets.json'), 9 | perpsv2Markets: require('./perpsv2-markets.json'), 10 | }; 11 | -------------------------------------------------------------------------------- /publish/deployed/sepolia/offchain-feeds.json: -------------------------------------------------------------------------------- 1 | [] 2 | -------------------------------------------------------------------------------- /publish/deployed/sepolia/owner-actions.json: -------------------------------------------------------------------------------- 1 | {} 2 | -------------------------------------------------------------------------------- /publish/deployed/sepolia/params.json: -------------------------------------------------------------------------------- 1 | [] 2 | -------------------------------------------------------------------------------- /publish/deployed/sepolia/perpsv2-markets.json: -------------------------------------------------------------------------------- 1 | [] 2 | -------------------------------------------------------------------------------- /publish/deployed/sepolia/rewards.json: -------------------------------------------------------------------------------- 1 | [] 2 | -------------------------------------------------------------------------------- /publish/deployed/sepolia/shorting-rewards.json: -------------------------------------------------------------------------------- 1 | [] 2 | -------------------------------------------------------------------------------- /publish/deployed/sepolia/synths.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "name": "sUSD", 4 | "asset": "USD", 5 | "subclass": "MultiCollateralSynth" 6 | }, 7 | { 8 | "name": "sETH", 9 | "asset": "ETH", 10 | "subclass": "MultiCollateralSynth" 11 | }, 12 | { 13 | "name": "sBTC", 14 | "asset": "BTC", 15 | "subclass": "MultiCollateralSynth" 16 | } 17 | ] 18 | -------------------------------------------------------------------------------- /publish/index.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const program = require('commander'); 4 | 5 | require('pretty-error').start(); 6 | require('dotenv').config(); 7 | 8 | require('./src/commands/build').cmd(program); 9 | require('./src/commands/connect-bridge').cmd(program); 10 | require('./src/commands/deploy-migration').cmd(program); 11 | require('./src/commands/deploy-shorting-rewards').cmd(program); 12 | require('./src/commands/deploy-staking-rewards').cmd(program); 13 | require('./src/commands/deploy').cmd(program); 14 | require('./src/commands/extract-staking-balances').cmd(program); 15 | require('./src/commands/finalize-release').cmd(program); 16 | require('./src/commands/migrate-debt-shares').cmd(program); 17 | require('./src/commands/check-settlement-owing').cmd(program); 18 | require('./src/commands/initiate-liquidator-rewards').cmd(program); 19 | require('./src/commands/liquidator-rewards-restitution').cmd(program); 20 | require('./src/commands/nominate').cmd(program); 21 | require('./src/commands/owner').cmd(program); 22 | require('./src/commands/persist-tokens').cmd(program); 23 | require('./src/commands/prepare-deploy-detect-diff').cmd(program); 24 | require('./src/commands/prepare-deploy').cmd(program); 25 | require('./src/commands/purge-synths').cmd(program); 26 | require('./src/commands/release').cmd(program); 27 | require('./src/commands/remove-synths').cmd(program); 28 | require('./src/commands/replace-synths').cmd(program); 29 | require('./src/commands/settle').cmd(program); 30 | require('./src/commands/verify').cmd(program); 31 | require('./src/commands/versions-history').cmd(program); 32 | require('./src/commands/versions-update').cmd(program); 33 | 34 | program.parse(process.argv); 35 | -------------------------------------------------------------------------------- /publish/non-upgradeable.json: -------------------------------------------------------------------------------- 1 | [ 2 | "Depot", 3 | "EternalStorage", 4 | "ExchangeState", 5 | "FeePoolEternalStorage", 6 | "FeePoolState", 7 | "Proxy", 8 | "ProxyERC20", 9 | "RewardEscrow$", 10 | "RewardEscrowV2Frozen", 11 | "RewardEscrowV2Storage", 12 | "RewardsDistribution", 13 | "SafeDecimalMath", 14 | "SynthetixEscrow", 15 | "SynthetixState", 16 | "TokenState", 17 | "ReadProxyAddressResolver", 18 | "PerpsV2ProxyETHPERP", 19 | "PerpsV2MarketStateETHPERP", 20 | "PerpsV2ProxyBTCPERP", 21 | "PerpsV2MarketStateBTCPERP", 22 | "PerpsV2ProxyLINKPERP", 23 | "PerpsV2MarketStateLINKPERP", 24 | "PerpsV2ProxySOLPERP", 25 | "PerpsV2MarketStateSOLPERP", 26 | "PerpsV2ProxyAVAXPERP", 27 | "PerpsV2MarketStateAVAXPERP", 28 | "PerpsV2ProxyAAVEPERP", 29 | "PerpsV2MarketStateAAVEPERP", 30 | "PerpsV2ProxyUNIPERP", 31 | "PerpsV2MarketStateUNIPERP", 32 | "PerpsV2ProxyMATICPERP", 33 | "PerpsV2MarketStateMATICPERP", 34 | "PerpsV2ProxyAPEPERP", 35 | "PerpsV2MarketStateAPEPERP", 36 | "PerpsV2ProxyDYDXPERP", 37 | "PerpsV2MarketStateDYDXPERP", 38 | "PerpsV2ProxyBNBPERP", 39 | "PerpsV2MarketStateBNBPERP", 40 | "PerpsV2ProxyOPPERP", 41 | "PerpsV2MarketStateOPPERP", 42 | "PerpsV2ProxyDOGEPERP", 43 | "PerpsV2MarketStateDOGEPERP", 44 | "PerpsV2ProxyXAUPERP", 45 | "PerpsV2MarketStateXAUPERP", 46 | "PerpsV2ProxyXAGPERP", 47 | "PerpsV2MarketStateXAGPERP", 48 | "PerpsV2ProxyEURPERP", 49 | "PerpsV2MarketStateEURPERP", 50 | "PerpsV2ProxyATOMPERP", 51 | "PerpsV2MarketStateATOMPERP", 52 | "PerpsV2ProxyAXSPERP", 53 | "PerpsV2MarketStateAXSPERP", 54 | "PerpsV2ProxyFLOWPERP", 55 | "PerpsV2MarketStateFLOWPERP", 56 | "PerpsV2ProxyFTMPERP", 57 | "PerpsV2MarketStateFTMPERP", 58 | "PerpsV2ProxyNEARPERP", 59 | "PerpsV2MarketStateNEARPERP", 60 | "PerpsV2ProxyAUDPERP", 61 | "PerpsV2MarketStateAUDPERP", 62 | "PerpsV2ProxyGBPPERP", 63 | "PerpsV2MarketStateGBPPERP" 64 | ] 65 | -------------------------------------------------------------------------------- /publish/src/NonceManager.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const { gray } = require('chalk'); 4 | 5 | class NonceManager { 6 | constructor({ provider, account }) { 7 | this.provider = provider; 8 | this.account = account; 9 | this.storedNonces = {}; 10 | } 11 | 12 | async getNonce() { 13 | if (!this.storedNonces[this.account]) { 14 | this.storedNonces[this.account] = parseInt( 15 | (await this.provider.getTransactionCount(this.account)).toString(), 16 | 10 17 | ); 18 | } 19 | 20 | const nonce = this.storedNonces[this.account]; 21 | console.log(gray(` > Providing custom nonce: ${nonce}`)); 22 | 23 | return nonce; 24 | } 25 | 26 | incrementNonce() { 27 | this.storedNonces[this.account] += 1; 28 | } 29 | } 30 | 31 | module.exports = NonceManager; 32 | -------------------------------------------------------------------------------- /publish/src/command-utils/contract.js: -------------------------------------------------------------------------------- 1 | const fs = require('fs'); 2 | const path = require('path'); 3 | 4 | const ethers = require('ethers'); 5 | 6 | const { getSource, getTarget } = require('../../..'); 7 | 8 | const getContract = ({ 9 | contract, 10 | source, 11 | network = 'mainnet', 12 | useOvm = false, 13 | deploymentPath = undefined, 14 | wallet, 15 | provider, 16 | }) => { 17 | const target = getTarget({ path, fs, contract, network, useOvm, deploymentPath }); 18 | const sourceData = getSource({ 19 | path, 20 | fs, 21 | contract: source || target.source, 22 | network, 23 | useOvm, 24 | deploymentPath, 25 | }); 26 | 27 | return new ethers.Contract(target.address, sourceData.abi, wallet || provider); 28 | }; 29 | 30 | module.exports = { 31 | getContract, 32 | }; 33 | -------------------------------------------------------------------------------- /publish/src/command-utils/safe-initializer.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const { gray, yellow } = require('chalk'); 4 | 5 | const SafeBatchSubmitter = require('../SafeBatchSubmitter'); 6 | 7 | const safeInitializer = async ({ network, signer, safeAddress }) => { 8 | const safeBatchSubmitter = new SafeBatchSubmitter({ network, signer, safeAddress }); 9 | try { 10 | // attempt to initialize a gnosis safe from the new owner 11 | const { currentNonce, pendingTxns } = await safeBatchSubmitter.init(); 12 | console.log( 13 | gray( 14 | 'Loaded safe at address', 15 | yellow(safeAddress), 16 | 'nonce', 17 | yellow(currentNonce), 18 | 'with', 19 | yellow(pendingTxns.count), 20 | 'transactions pending signing' 21 | ) 22 | ); 23 | 24 | return safeBatchSubmitter; 25 | } catch (err) { 26 | if ( 27 | !/Safe Proxy contract is not deployed in the current network/.test(err.message) && 28 | !/Safe contracts not found in the current network/.test(err.message) 29 | ) { 30 | // TODO: In the future we should throw here and get Gnosis to help fix these errors. 31 | console.error(err.message); 32 | } 33 | } 34 | }; 35 | 36 | module.exports = { 37 | safeInitializer, 38 | }; 39 | -------------------------------------------------------------------------------- /publish/src/commands/.gitignore: -------------------------------------------------------------------------------- 1 | recent-feePeriods-*.json 2 | exchanges-*.json 3 | -------------------------------------------------------------------------------- /publish/src/commands/deploy/add-synths-to-protocol.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const { gray } = require('chalk'); 4 | 5 | module.exports = async ({ addressOf, deployer, runStep, synthsToAdd }) => { 6 | console.log(gray(`\n------ ADD SYNTHS TO ISSUER ------\n`)); 7 | 8 | const { Issuer } = deployer.deployedContracts; 9 | 10 | // Set up the connection to the Issuer for each Synth (requires FlexibleStorage to have been configured) 11 | 12 | // First filter out all those synths which are already properly imported 13 | console.log(gray('Filtering synths to add to the issuer.')); 14 | const filteredSynths = []; 15 | const seen = new Set(); 16 | for (const synth of synthsToAdd) { 17 | const issuerSynthAddress = await Issuer.synths(synth.currencyKeyInBytes); 18 | const currentSynthAddress = addressOf(synth.synth); 19 | if (issuerSynthAddress === currentSynthAddress) { 20 | console.log(gray(`${currentSynthAddress} requires no action`)); 21 | } else if (!seen.has(synth.currencyKeyInBytes)) { 22 | console.log(gray(`${currentSynthAddress} will be added to the issuer.`)); 23 | filteredSynths.push(synth); 24 | } 25 | seen.add(synth.currencyKeyInBytes); 26 | } 27 | 28 | const synthChunkSize = 15; 29 | let batchCounter = 1; 30 | for (let i = 0; i < filteredSynths.length; i += synthChunkSize) { 31 | const chunk = filteredSynths.slice(i, i + synthChunkSize); 32 | await runStep({ 33 | contract: 'Issuer', 34 | target: Issuer, 35 | read: 'getSynths', 36 | readArg: [chunk.map(synth => synth.currencyKeyInBytes)], 37 | expected: input => 38 | input.length === chunk.length && 39 | input.every((cur, idx) => cur === addressOf(chunk[idx].synth)), 40 | write: 'addSynths', 41 | writeArg: [chunk.map(synth => addressOf(synth.synth))], 42 | gasLimit: 1e5 * synthChunkSize, 43 | comment: `Add synths to the Issuer contract - batch ${batchCounter++}`, 44 | }); 45 | } 46 | }; 47 | -------------------------------------------------------------------------------- /publish/src/commands/deploy/configure-offchain-price-feeds.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const { gray } = require('chalk'); 4 | const { toBytes32 } = require('../../../..'); 5 | 6 | module.exports = async ({ deployer, runStep, offchainFeeds, useOvm }) => { 7 | console.log(gray(`\n------ CONFIGURE OFFCHAIN FEEDS ------\n`)); 8 | 9 | console.log(gray(`\n------ CONFIGURE OFFCHAIN FEEDS (PYTH) ------\n`)); 10 | 11 | // Setup remaining price feeds (that aren't synths) 12 | const { PerpsV2ExchangeRate } = deployer.deployedContracts; 13 | 14 | const pythFeeds = offchainFeeds.filter(p => p.kind === 'pyth'); 15 | if (pythFeeds.length === 0) { 16 | // No feeds to configure 17 | return; 18 | } 19 | 20 | if (new Set(pythFeeds.map(p => p.oracle)).size > 1) { 21 | throw Error('Pyth Off-chain feeds contains more than one oracle address'); 22 | } 23 | 24 | const oracleAddress = pythFeeds[0].oracle; 25 | 26 | await runStep({ 27 | contract: `PerpsV2ExchangeRate`, 28 | target: PerpsV2ExchangeRate, 29 | read: 'offchainOracle', 30 | expected: input => input === oracleAddress, 31 | write: 'setOffchainOracle', 32 | writeArg: [oracleAddress], 33 | comment: `Ensure the PerpsV2ExchangeRate has the oracle address configured to ${oracleAddress}`, 34 | }); 35 | 36 | for (const feed of pythFeeds) { 37 | const key = feed.asset; 38 | await runStep({ 39 | contract: `PerpsV2ExchangeRate`, 40 | target: PerpsV2ExchangeRate, 41 | read: 'offchainPriceFeedId', 42 | readArg: [toBytes32(key)], 43 | expected: input => input === feed.feedId, 44 | write: 'setOffchainPriceFeedId', 45 | writeArg: [toBytes32(key), feed.feedId], 46 | comment: `Ensure the PerpsV2ExchangeRate contract has the off-chain feed Id for ${key}`, 47 | }); 48 | } 49 | }; 50 | -------------------------------------------------------------------------------- /publish/src/commands/deploy/configure-standalone-price-feeds.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const { gray } = require('chalk'); 4 | const { 5 | utils: { isAddress }, 6 | } = require('ethers'); 7 | const { toBytes32 } = require('../../../..'); 8 | 9 | module.exports = async ({ deployer, runStep, feeds, useOvm }) => { 10 | console.log(gray(`\n------ CONFIGURE STANDALONE FEEDS ------\n`)); 11 | 12 | // Setup remaining price feeds (that aren't synths) 13 | const { ExchangeRates } = deployer.deployedContracts; 14 | 15 | for (const { asset, feed } of Object.values(feeds)) { 16 | const key = asset; 17 | if (isAddress(feed) && ExchangeRates) { 18 | await runStep({ 19 | contract: `ExchangeRates`, 20 | target: ExchangeRates, 21 | read: 'aggregators', 22 | readArg: toBytes32(key), 23 | expected: input => input === feed, 24 | write: 'addAggregator', 25 | writeArg: [toBytes32(key), feed], 26 | comment: `Ensure the ExchangeRates contract has the standalone feed for ${key}`, 27 | }); 28 | } 29 | } 30 | }; 31 | -------------------------------------------------------------------------------- /publish/src/commands/deploy/deploy-dapp-utils.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const { gray } = require('chalk'); 4 | 5 | module.exports = async ({ account, addressOf, deployer }) => { 6 | console.log(gray(`\n------ DEPLOY DAPP UTILITIES ------\n`)); 7 | 8 | const { ReadProxyAddressResolver } = deployer.deployedContracts; 9 | 10 | await deployer.deployContract({ 11 | name: 'SynthUtil', 12 | deps: ['ReadProxyAddressResolver'], 13 | args: [addressOf(ReadProxyAddressResolver)], 14 | }); 15 | 16 | await deployer.deployContract({ 17 | name: 'DappMaintenance', 18 | args: [account], 19 | }); 20 | }; 21 | -------------------------------------------------------------------------------- /publish/src/commands/deploy/get-deploy-parameter-factory.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const { yellow } = require('chalk'); 4 | 5 | const { defaults } = require('../../../..'); 6 | 7 | module.exports = ({ params, ignoreCustomParameters }) => async name => { 8 | const defaultParam = defaults[name]; 9 | if (ignoreCustomParameters) { 10 | return defaultParam; 11 | } 12 | 13 | let effectiveValue = defaultParam; 14 | 15 | const param = (params || []).find(p => p.name === name); 16 | 17 | if (param) { 18 | effectiveValue = param.value; 19 | } 20 | 21 | if (effectiveValue !== defaultParam) { 22 | console.log( 23 | yellow( 24 | `PARAMETER OVERRIDE: Overriding default ${name} with ${JSON.stringify( 25 | effectiveValue 26 | )}, specified in params.json.` 27 | ) 28 | ); 29 | } 30 | 31 | return effectiveValue; 32 | }; 33 | -------------------------------------------------------------------------------- /publish/src/contract-overrides.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | module.exports = { 4 | 'ExchangeRates.sol': { 5 | runs: 20000, 6 | }, 7 | 'FeePool.sol': { 8 | runs: 1500, 9 | }, 10 | }; 11 | -------------------------------------------------------------------------------- /slither.config.json: -------------------------------------------------------------------------------- 1 | { 2 | "buidler_cache_directory": "build/cache", 3 | "hardhat_artifacts_directory": "build/artifacts", 4 | "detectors_to_exclude": "reentrancy-events" 5 | } 6 | -------------------------------------------------------------------------------- /test/etherscan/index.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const path = require('path'); 4 | const Mocha = require('mocha'); 5 | 6 | const commander = require('commander'); 7 | const program = new commander.Command(); 8 | 9 | program 10 | .option('-n, --network ', 'The network to run off.', x => x.toLowerCase(), 'mainnet') 11 | .option('-g, --grep ', 'Any grep string') 12 | .action(async ({ network, grep }) => { 13 | // setup the network as an env variable 14 | process.env.ETH_NETWORK = network; 15 | 16 | const mocha = new Mocha({ 17 | timeout: 10e3, // 10 secs 18 | grep, 19 | }); 20 | 21 | // Add each .js file to the mocha instance 22 | mocha.addFile(path.join(__dirname, 'spec.js')); 23 | 24 | // Run the tests, this way we can pass CLI args in as env variables 25 | mocha.run(failures => { 26 | process.exitCode = failures ? 1 : 0; // exit with non-zero status if there were failures 27 | }); 28 | }); 29 | 30 | if (require.main === module) { 31 | program.parse(process.argv); 32 | } 33 | -------------------------------------------------------------------------------- /test/integration/l1/Liquidations.l1.integrations.js: -------------------------------------------------------------------------------- 1 | const { bootstrapL1 } = require('../utils/bootstrap'); 2 | const { itCanLiquidate } = require('../behaviors/liquidations.behavior'); 3 | 4 | describe('Liquidations (L1)', () => { 5 | const ctx = this; 6 | bootstrapL1({ ctx }); 7 | 8 | itCanLiquidate({ ctx }); 9 | }); 10 | -------------------------------------------------------------------------------- /test/integration/l1/Redemption.Dynamic.l1.integration.js: -------------------------------------------------------------------------------- 1 | const { bootstrapL1 } = require('../utils/bootstrap'); 2 | const { itCanRedeem } = require('../behaviors/redeem.dynamic.behavior'); 3 | 4 | describe('Redemption.dynamic integration tests (L1)', () => { 5 | const ctx = this; 6 | bootstrapL1({ ctx }); 7 | itCanRedeem({ ctx }); 8 | }); 9 | -------------------------------------------------------------------------------- /test/integration/l1/Redemption.l1.integration.js: -------------------------------------------------------------------------------- 1 | const { bootstrapL1 } = require('../utils/bootstrap'); 2 | const { itCanRedeem } = require('../behaviors/redeem.behavior'); 3 | 4 | describe('Redemption integration tests (L1)', () => { 5 | const ctx = this; 6 | bootstrapL1({ ctx }); 7 | 8 | before('check fork', async function() { 9 | if (ctx.fork) { 10 | // this will fail on a fork since sBTC or sETH can't be removed because 11 | // the debt may be too large for removeSynth to not underflow during debt update 12 | this.skip(); 13 | } 14 | }); 15 | 16 | itCanRedeem({ ctx }); 17 | }); 18 | -------------------------------------------------------------------------------- /test/integration/l1/RewardEscrow.l1.integration.js: -------------------------------------------------------------------------------- 1 | const { bootstrapL1 } = require('../utils/bootstrap'); 2 | const { itDoesRewardEscrow } = require('../behaviors/rewardEscrow.behavior'); 3 | 4 | describe('RewardEscrow integration tests (L1)', () => { 5 | const ctx = this; 6 | bootstrapL1({ ctx }); 7 | 8 | itDoesRewardEscrow({ ctx }); 9 | }); 10 | -------------------------------------------------------------------------------- /test/integration/l1/Shorts.l1.integration.js: -------------------------------------------------------------------------------- 1 | const { bootstrapL1 } = require('../utils/bootstrap'); 2 | const { itCanOpenAndCloseShort } = require('../behaviors/short.behavior'); 3 | 4 | describe('Shorts integration tests (L1)', () => { 5 | const ctx = this; 6 | bootstrapL1({ ctx }); 7 | 8 | itCanOpenAndCloseShort({ ctx }); 9 | }); 10 | -------------------------------------------------------------------------------- /test/integration/l1/Synthetix.l1.integration.js: -------------------------------------------------------------------------------- 1 | const { bootstrapL1 } = require('../utils/bootstrap'); 2 | const { itCanExchange } = require('../behaviors/exchange.behavior'); 3 | const { itCanStake } = require('../behaviors/stake.behavior'); 4 | const { itBehavesLikeAnERC20 } = require('../behaviors/erc20.behavior'); 5 | 6 | describe('Synthetix integration tests (L1)', () => { 7 | const ctx = this; 8 | bootstrapL1({ ctx }); 9 | 10 | itCanExchange({ ctx }); 11 | itCanStake({ ctx }); 12 | itBehavesLikeAnERC20({ ctx }); 13 | }); 14 | -------------------------------------------------------------------------------- /test/integration/l1/SynthsUSD.l1.integration.js: -------------------------------------------------------------------------------- 1 | const { bootstrapL1 } = require('../utils/bootstrap'); 2 | const { itBehavesLikeAnERC20 } = require('../behaviors/erc20.behavior'); 3 | 4 | describe('SynthsUSD integration tests (L1)', () => { 5 | const ctx = this; 6 | bootstrapL1({ ctx }); 7 | 8 | itBehavesLikeAnERC20({ ctx, contract: 'SynthsUSD' }); 9 | }); 10 | -------------------------------------------------------------------------------- /test/integration/l1/WrapperFactory.l1.integration.js: -------------------------------------------------------------------------------- 1 | // const { artifacts } = require('hardhat'); 2 | const { bootstrapL1 } = require('../utils/bootstrap'); 3 | const { itCanWrapETH } = require('../behaviors/wrap.behavior'); 4 | 5 | describe('WrapperFactory integration tests (L1)', () => { 6 | const ctx = this; 7 | bootstrapL1({ ctx }); 8 | 9 | itCanWrapETH({ ctx }); 10 | }); 11 | -------------------------------------------------------------------------------- /test/integration/l2/Futures.l2.integration.js: -------------------------------------------------------------------------------- 1 | const { bootstrapL2 } = require('../utils/bootstrap'); 2 | const { itCanTrade } = require('../behaviors/futures.behavior'); 3 | 4 | describe('Futures integration tests (L2)', () => { 5 | const ctx = this; 6 | bootstrapL2({ ctx }); 7 | itCanTrade({ ctx }); 8 | }); 9 | -------------------------------------------------------------------------------- /test/integration/l2/Liquidations.l2.integration.js: -------------------------------------------------------------------------------- 1 | const { bootstrapL2 } = require('../utils/bootstrap'); 2 | const { itCanLiquidate } = require('../behaviors/liquidations.behavior'); 3 | 4 | describe('Liquidations (L2)', () => { 5 | const ctx = this; 6 | bootstrapL2({ ctx }); 7 | 8 | itCanLiquidate({ ctx }); 9 | }); 10 | -------------------------------------------------------------------------------- /test/integration/l2/PerpsV2.l2.integration.js: -------------------------------------------------------------------------------- 1 | const { bootstrapL2 } = require('../utils/bootstrap'); 2 | const { itCanTrade } = require('../behaviors/perpsV2.behavior'); 3 | 4 | describe('PerpsV2 integration tests (L2)', () => { 5 | const ctx = this; 6 | bootstrapL2({ ctx }); 7 | itCanTrade({ ctx }); 8 | }); 9 | -------------------------------------------------------------------------------- /test/integration/l2/Redemption.Dynamic.l2.integration.js: -------------------------------------------------------------------------------- 1 | const { bootstrapL2 } = require('../utils/bootstrap'); 2 | const { itCanRedeem } = require('../behaviors/redeem.dynamic.behavior'); 3 | 4 | describe('Redemption.dynamic integration tests (L2)', () => { 5 | const ctx = this; 6 | bootstrapL2({ ctx }); 7 | itCanRedeem({ ctx }); 8 | }); 9 | -------------------------------------------------------------------------------- /test/integration/l2/Redemption.l2.integration.js: -------------------------------------------------------------------------------- 1 | const { bootstrapL2 } = require('../utils/bootstrap'); 2 | const { itCanRedeem } = require('../behaviors/redeem.behavior'); 3 | 4 | describe('Redemption integration tests (L2)', () => { 5 | const ctx = this; 6 | bootstrapL2({ ctx }); 7 | 8 | before('check fork', async function() { 9 | if (ctx.fork) { 10 | // this will fail on a fork since sBTC or sETH can't be removed because 11 | // the debt may be too large for removeSynth to not underflow during debt update 12 | this.skip(); 13 | } 14 | }); 15 | 16 | itCanRedeem({ ctx }); 17 | }); 18 | -------------------------------------------------------------------------------- /test/integration/l2/RewardEscrow.l2.integration.js: -------------------------------------------------------------------------------- 1 | const { bootstrapL2 } = require('../utils/bootstrap'); 2 | const { itDoesRewardEscrow } = require('../behaviors/rewardEscrow.behavior'); 3 | 4 | describe('RewardEscrow integration tests (L2)', () => { 5 | const ctx = this; 6 | bootstrapL2({ ctx }); 7 | 8 | itDoesRewardEscrow({ ctx }); 9 | }); 10 | -------------------------------------------------------------------------------- /test/integration/l2/Shorts.l2.integration.js: -------------------------------------------------------------------------------- 1 | const { bootstrapL2 } = require('../utils/bootstrap'); 2 | const { itCanOpenAndCloseShort } = require('../behaviors/short.behavior'); 3 | 4 | describe('Shorts integration tests (L2)', () => { 5 | const ctx = this; 6 | bootstrapL2({ ctx }); 7 | 8 | itCanOpenAndCloseShort({ ctx }); 9 | }); 10 | -------------------------------------------------------------------------------- /test/integration/l2/Synthetix.l2.integration.js: -------------------------------------------------------------------------------- 1 | const { bootstrapL2 } = require('../utils/bootstrap'); 2 | const { itCanExchange } = require('../behaviors/exchange.behavior'); 3 | const { itCanStake } = require('../behaviors/stake.behavior'); 4 | const { itBehavesLikeAnERC20 } = require('../behaviors/erc20.behavior'); 5 | 6 | describe('Synthetix integration tests (L2)', () => { 7 | const ctx = this; 8 | bootstrapL2({ ctx }); 9 | 10 | itCanExchange({ ctx }); 11 | itCanStake({ ctx }); 12 | itBehavesLikeAnERC20({ ctx }); 13 | }); 14 | -------------------------------------------------------------------------------- /test/integration/l2/SynthsUSD.l2.integration.js: -------------------------------------------------------------------------------- 1 | const { bootstrapL2 } = require('../utils/bootstrap'); 2 | const { itBehavesLikeAnERC20 } = require('../behaviors/erc20.behavior'); 3 | 4 | describe('SynthsUSD integration tests (L2)', () => { 5 | const ctx = this; 6 | bootstrapL2({ ctx }); 7 | 8 | itBehavesLikeAnERC20({ ctx, contract: 'SynthsUSD' }); 9 | }); 10 | -------------------------------------------------------------------------------- /test/integration/l2/WrapperFactory.l2.integration.js: -------------------------------------------------------------------------------- 1 | // const { artifacts } = require('hardhat'); 2 | const { bootstrapL2 } = require('../utils/bootstrap'); 3 | const { itCanWrapETH } = require('../behaviors/wrap.behavior'); 4 | 5 | describe('WrapperFactory integration tests (L2)', () => { 6 | const ctx = this; 7 | bootstrapL2({ ctx }); 8 | 9 | itCanWrapETH({ ctx }); 10 | }); 11 | -------------------------------------------------------------------------------- /test/integration/utils/approve.js: -------------------------------------------------------------------------------- 1 | async function approveIfNeeded({ token, owner, beneficiary, amount }) { 2 | const allowance = await token.allowance(owner.address, beneficiary.address); 3 | 4 | if (allowance.lt(amount)) { 5 | token = token.connect(owner); 6 | 7 | const tx = await token.approve(beneficiary.address, amount); 8 | await tx.wait(); 9 | } 10 | } 11 | 12 | module.exports = { 13 | approveIfNeeded, 14 | }; 15 | -------------------------------------------------------------------------------- /test/integration/utils/contracts.js: -------------------------------------------------------------------------------- 1 | const fs = require('fs'); 2 | const path = require('path'); 3 | const ethers = require('ethers'); 4 | const { getSource, getTarget } = require('../../..'); 5 | 6 | function connectContracts({ ctx }) { 7 | const { useOvm } = ctx; 8 | const network = ctx.fork ? 'mainnet' : 'local'; 9 | 10 | const allTargets = getTarget({ fs, path, network, useOvm }); 11 | 12 | ctx.contracts = {}; 13 | Object.entries(allTargets).map(([name, target]) => { 14 | ctx.contracts[name] = new ethers.Contract( 15 | getTarget({ fs, path, network, useOvm, contract: name }).address, 16 | getSource({ fs, path, network, useOvm, contract: target.source }).abi, 17 | ctx.provider 18 | ); 19 | }); 20 | 21 | _ensureWETH({ ctx }); 22 | } 23 | 24 | function _ensureWETH({ ctx }) { 25 | if (!ctx.contracts.WETH) { 26 | if (ctx.useOvm) { 27 | ctx.contracts.WETH = new ethers.Contract( 28 | '0x4200000000000000000000000000000000000006', 29 | _loadCustomAbi({ name: 'WETH' }), 30 | ctx.provider 31 | ); 32 | } else if (ctx.fork) { 33 | ctx.contracts.WETH = new ethers.Contract( 34 | '0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2', // WETH on mainnet L1 35 | _loadCustomAbi({ name: 'WETH' }), 36 | ctx.provider 37 | ); 38 | } 39 | } 40 | } 41 | 42 | function _loadCustomAbi({ name }) { 43 | return JSON.parse(fs.readFileSync(path.resolve(__dirname, '../abis/WETH.json'), 'utf8')); 44 | } 45 | 46 | module.exports = { 47 | connectContracts, 48 | }; 49 | -------------------------------------------------------------------------------- /test/integration/utils/exchanging.js: -------------------------------------------------------------------------------- 1 | const ethers = require('ethers'); 2 | const { ensureBalance } = require('./balances'); 3 | const { toBytes32 } = require('../../../index'); 4 | const { updateCache } = require('../utils/rates'); 5 | const { skipWaitingPeriod } = require('../utils/skip'); 6 | 7 | async function exchangeSomething({ ctx }) { 8 | let { Synthetix } = ctx.contracts; 9 | Synthetix = Synthetix.connect(ctx.users.owner); 10 | 11 | const sUSDAmount = ethers.utils.parseEther('10'); 12 | await ensureBalance({ ctx, symbol: 'sUSD', user: ctx.users.owner, balance: sUSDAmount }); 13 | 14 | await updateCache({ ctx }); 15 | 16 | const tx = await Synthetix.exchange(toBytes32('sUSD'), sUSDAmount, toBytes32('sETH')); 17 | await tx.wait(); 18 | } 19 | 20 | async function exchangeSynths({ ctx, src, dest, amount, user }) { 21 | let { Synthetix, CircuitBreaker } = ctx.contracts; 22 | const { ExchangeRates } = ctx.contracts; 23 | Synthetix = Synthetix.connect(user); 24 | CircuitBreaker = CircuitBreaker.connect(ctx.users.owner); 25 | 26 | await ensureBalance({ ctx, symbol: src, user, balance: amount }); 27 | 28 | // ensure that circuit breaker wont get in he way 29 | const oracles = [ 30 | await ExchangeRates.aggregators(toBytes32(src)), 31 | await ExchangeRates.aggregators(toBytes32(dest)), 32 | ].filter(o => o !== ethers.constants.AddressZero); 33 | let tx = await CircuitBreaker.resetLastValue( 34 | oracles, 35 | oracles.map(() => 0) 36 | ); 37 | 38 | tx = await Synthetix.exchange(toBytes32(src), amount, toBytes32(dest)); 39 | await tx.wait(); 40 | 41 | await skipWaitingPeriod({ ctx }); 42 | 43 | tx = await Synthetix.settle(toBytes32(dest)); 44 | await tx.wait(); 45 | } 46 | 47 | module.exports = { 48 | exchangeSomething, 49 | exchangeSynths, 50 | }; 51 | -------------------------------------------------------------------------------- /test/integration/utils/gas.js: -------------------------------------------------------------------------------- 1 | const chalk = require('chalk'); 2 | 3 | async function runTxAndLogGasUsed(ctx, tx) { 4 | const receipt = await tx.wait(); 5 | const gasUsed = receipt.gasUsed.toString(); 6 | 7 | // Append to running test title. 8 | ctx._runnable.title = `${ctx._runnable.title} (${chalk.green(gasUsed)}${chalk.gray(' gas)')}`; 9 | } 10 | 11 | module.exports = { 12 | runTxAndLogGasUsed, 13 | }; 14 | -------------------------------------------------------------------------------- /test/integration/utils/issuance.js: -------------------------------------------------------------------------------- 1 | const ethers = require('ethers'); 2 | const { resumeIssuance } = require('./status'); 3 | const { setSystemSetting } = require('./settings'); 4 | 5 | async function ensureIssuance({ ctx }) { 6 | if (ctx.fork) { 7 | // Ensure issuance is not suspended for any reason 8 | await resumeIssuance({ ctx }); 9 | // Note: if issuance has been suspended for some time, the circuit breaker could kick in for issuance, 10 | // so up the ratio here 11 | await setSystemSetting({ 12 | ctx, 13 | settingName: 'priceDeviationThresholdFactor', 14 | newValue: ethers.utils.parseEther('10'), 15 | }); 16 | } 17 | } 18 | 19 | module.exports = { 20 | ensureIssuance, 21 | }; 22 | -------------------------------------------------------------------------------- /test/integration/utils/l2.js: -------------------------------------------------------------------------------- 1 | const chalk = require('chalk'); 2 | 3 | function skipIfL2({ ctx, reason }) { 4 | before('skip if running on :2', async function() { 5 | if (!ctx.useOvm) { 6 | return; 7 | } 8 | 9 | if (!reason) { 10 | throw new Error('Please specify a reason when skipping L2 tests.'); 11 | } 12 | console.log(chalk.yellow(`>> Skipping L2 tests because ${reason}`)); 13 | 14 | this.skip(); 15 | }); 16 | } 17 | 18 | module.exports = { 19 | skipIfL2, 20 | }; 21 | -------------------------------------------------------------------------------- /test/integration/utils/loans.js: -------------------------------------------------------------------------------- 1 | async function getLoan({ ctx, id, user }) { 2 | const { CollateralShort, CollateralStateShort } = ctx.contracts; 3 | 4 | let loan; 5 | if (!CollateralStateShort) { 6 | loan = await CollateralShort.loans(id); 7 | } else { 8 | loan = await CollateralStateShort.getLoan(user.address, id); 9 | } 10 | return loan; 11 | } 12 | 13 | async function getShortInteractionDelay({ ctx }) { 14 | const { CollateralShort, CollateralStateShort, SystemSettings } = ctx.contracts; 15 | 16 | let interactionDelay; 17 | if (!CollateralStateShort) { 18 | interactionDelay = await SystemSettings.interactionDelay(CollateralShort.address); 19 | } else { 20 | interactionDelay = await CollateralShort.interactionDelay(); 21 | } 22 | 23 | return interactionDelay; 24 | } 25 | 26 | async function setShortInteractionDelay({ ctx, delay }) { 27 | const { CollateralShort, CollateralStateShort, SystemSettings } = ctx.contracts; 28 | 29 | if (!CollateralStateShort) { 30 | const SystemSettingsAsOwner = SystemSettings.connect(ctx.users.owner); 31 | await SystemSettingsAsOwner.setInteractionDelay(CollateralShort.address, delay); 32 | } else { 33 | const CollateralShortAsOwner = CollateralShort.connect(ctx.users.owner); 34 | await CollateralShortAsOwner.setInteractionDelay(delay); 35 | } 36 | } 37 | 38 | module.exports = { 39 | getLoan, 40 | getShortInteractionDelay, 41 | setShortInteractionDelay, 42 | }; 43 | -------------------------------------------------------------------------------- /test/integration/utils/rpc.js: -------------------------------------------------------------------------------- 1 | async function sendDummyTx({ ctx }) { 2 | const tx = await ctx.owner.sendTransaction({ 3 | to: '0x0000000000000000000000000000000000000001', 4 | value: 0, 5 | }); 6 | 7 | await tx.wait(); 8 | } 9 | 10 | async function wait({ seconds }) { 11 | return new Promise(resolve => { 12 | setTimeout(() => { 13 | resolve(); 14 | }, seconds * 1000); 15 | }); 16 | } 17 | 18 | module.exports = { 19 | sendDummyTx, 20 | wait, 21 | }; 22 | -------------------------------------------------------------------------------- /test/integration/utils/settings.js: -------------------------------------------------------------------------------- 1 | const { toBytes32 } = require('../../..'); 2 | 3 | async function getSystemSetting({ ctx, settingName }) { 4 | const { SystemSettings } = ctx.contracts; 5 | 6 | return SystemSettings[settingName](); 7 | } 8 | 9 | async function setSystemSetting({ ctx, settingName, newValue }) { 10 | let { SystemSettings } = ctx.contracts; 11 | SystemSettings = SystemSettings.connect(ctx.users.owner); 12 | 13 | const tx = await SystemSettings[ 14 | `set${settingName.charAt(0).toUpperCase()}${settingName.slice(1)}` 15 | ](newValue); 16 | await tx.wait(); 17 | } 18 | 19 | async function forceSetSystemSetting({ ctx, settingName, newValue }) { 20 | const { SystemSettings } = ctx.contracts; 21 | let { AddressResolver, FlexibleStorage } = ctx.contracts; 22 | 23 | const owner = ctx.users.owner; 24 | AddressResolver = AddressResolver.connect(owner); 25 | FlexibleStorage = FlexibleStorage.connect(owner); 26 | 27 | let tx; 28 | 29 | const settingsName = toBytes32('SystemSettings'); 30 | const settingsAddress = await AddressResolver.getAddress(settingsName); 31 | 32 | tx = await AddressResolver.importAddresses([settingsName], [owner.address]); 33 | await tx.wait(); 34 | tx = await AddressResolver.rebuildCaches([SystemSettings.address]); 35 | await tx.wait(); 36 | 37 | tx = await FlexibleStorage.setUIntValue(settingsName, toBytes32(settingName), newValue); 38 | await tx.wait(); 39 | 40 | tx = await AddressResolver.importAddresses([settingsName], [settingsAddress]); 41 | await tx.wait(); 42 | tx = await AddressResolver.rebuildCaches([SystemSettings.address]); 43 | await tx.wait(); 44 | } 45 | 46 | module.exports = { 47 | getSystemSetting, 48 | setSystemSetting, 49 | forceSetSystemSetting, 50 | }; 51 | -------------------------------------------------------------------------------- /test/integration/utils/skip.js: -------------------------------------------------------------------------------- 1 | const { fastForward } = require('../../test-utils/rpc'); 2 | const { wait } = require('../../test-utils/wait'); 3 | const { getSystemSetting } = require('./settings'); 4 | const { increaseStalePeriodAndCheckRatesAndCache } = require('./rates'); 5 | 6 | async function skipWaitingPeriod({ ctx }) { 7 | await _dualFastForward({ 8 | ctx, 9 | seconds: await getSystemSetting({ ctx, settingName: 'waitingPeriodSecs' }), 10 | }); 11 | } 12 | 13 | async function skipFeePeriod({ ctx }) { 14 | await _dualFastForward({ 15 | ctx, 16 | seconds: await getSystemSetting({ ctx, settingName: 'feePeriodDuration' }), 17 | }); 18 | } 19 | 20 | async function skipMinimumStakeTime({ ctx }) { 21 | await _dualFastForward({ 22 | ctx, 23 | seconds: await getSystemSetting({ ctx, settingName: 'minimumStakeTime' }), 24 | }); 25 | } 26 | 27 | async function skipLiquidationDelay({ ctx }) { 28 | await _dualFastForward({ 29 | ctx, 30 | seconds: await getSystemSetting({ ctx, settingName: 'liquidationDelay' }), 31 | }); 32 | } 33 | 34 | /* 35 | * Fast forwards the L1 chain and waits for the 36 | * L2 chain to sync to the new timestamp. 37 | * The delay is chosen because this is the default time granularity 38 | * of the ops tool, which is 5s. 39 | * */ 40 | async function _dualFastForward({ ctx, seconds }) { 41 | const l1Ctx = ctx.l1mock || ctx; 42 | 43 | await fastForward({ seconds: parseInt(seconds), provider: l1Ctx.provider }); 44 | 45 | // this is needed for some reason, not sure why 46 | await wait({ seconds: 1 }); 47 | 48 | await increaseStalePeriodAndCheckRatesAndCache({ ctx }); 49 | } 50 | 51 | module.exports = { 52 | skipWaitingPeriod, 53 | skipFeePeriod, 54 | skipMinimumStakeTime, 55 | skipLiquidationDelay, 56 | }; 57 | -------------------------------------------------------------------------------- /test/integration/utils/staking.js: -------------------------------------------------------------------------------- 1 | function ignoreMinimumStakeTime({ ctx }) { 2 | before('record and reduce minimumStakeTime', async () => { 3 | let { SystemSettings } = ctx.contracts; 4 | SystemSettings = SystemSettings.connect(ctx.users.owner); 5 | 6 | ctx.minimumStakeTime = await SystemSettings.minimumStakeTime(); 7 | 8 | const tx = await SystemSettings.setMinimumStakeTime(0); 9 | await tx.wait(); 10 | }); 11 | 12 | after('restore minimum stake time', async () => { 13 | let { SystemSettings } = ctx.contracts; 14 | SystemSettings = SystemSettings.connect(ctx.users.owner); 15 | 16 | const tx = await SystemSettings.setMinimumStakeTime(ctx.minimumStakeTime); 17 | await tx.wait(); 18 | }); 19 | } 20 | 21 | module.exports = { 22 | ignoreMinimumStakeTime, 23 | }; 24 | -------------------------------------------------------------------------------- /test/integration/utils/status.js: -------------------------------------------------------------------------------- 1 | async function resumeIssuance({ ctx }) { 2 | let { SystemStatus } = ctx.contracts; 3 | 4 | const owner = ctx.users.owner; 5 | SystemStatus = SystemStatus.connect(owner); 6 | const tx = await SystemStatus.resumeIssuance(); 7 | await tx.wait(); 8 | } 9 | 10 | module.exports = { 11 | resumeIssuance, 12 | }; 13 | -------------------------------------------------------------------------------- /test/integration/utils/wait.js: -------------------------------------------------------------------------------- 1 | async function wait({ seconds }) { 2 | return new Promise(resolve => { 3 | setTimeout(() => { 4 | resolve(); 5 | }, seconds * 1000); 6 | }); 7 | } 8 | 9 | module.exports = { 10 | wait, 11 | }; 12 | -------------------------------------------------------------------------------- /test/publish/test.log: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Synthetixio/synthetix/1609d156708eb77025478cbcd92b98de51faf1e3/test/publish/test.log -------------------------------------------------------------------------------- /test/test-utils/rpc.js: -------------------------------------------------------------------------------- 1 | async function fastForward({ seconds, provider }) { 2 | await provider.send('evm_increaseTime', [seconds]); 3 | 4 | // anvil has a slightly different format for `evm_mine` annoyingly, so 5 | // we have to fallback here 6 | try { 7 | await provider.send('evm_mine', [{}]); 8 | } catch (err) { 9 | // backup 10 | await provider.send('evm_mine', []); 11 | } 12 | } 13 | 14 | async function dummyTx({ wallet, gasPrice = 0, gasLimit = 8000000 }) { 15 | const tx = await wallet.sendTransaction({ 16 | to: '0x' + '1234'.repeat(10), 17 | gasPrice, 18 | gasLimit, 19 | data: '0x', 20 | value: 0, 21 | }); 22 | await tx.wait(); 23 | } 24 | 25 | module.exports = { 26 | fastForward, 27 | dummyTx, 28 | }; 29 | -------------------------------------------------------------------------------- /test/test-utils/wait.js: -------------------------------------------------------------------------------- 1 | async function wait({ seconds }) { 2 | return new Promise(resolve => { 3 | setTimeout(() => { 4 | resolve(); 5 | }, seconds * 1000); 6 | }); 7 | } 8 | 9 | module.exports = { 10 | wait, 11 | }; 12 | -------------------------------------------------------------------------------- /test/test-utils/wallets.js: -------------------------------------------------------------------------------- 1 | const ethers = require('ethers'); 2 | 3 | function loadLocalWallets({ provider }) { 4 | const wallets = []; 5 | 6 | for (let i = 0; i < 10; i++) { 7 | const privateKey = getLocalPrivateKey({ index: i }); 8 | const wallet = new ethers.Wallet(privateKey, provider); 9 | wallet.pk = privateKey; 10 | wallets.push(wallet); 11 | } 12 | 13 | return wallets; 14 | } 15 | 16 | function getLocalPrivateKey({ index }) { 17 | return _getLocalMasterNode().derivePath(`m/44'/60'/0'/0/${index}`).privateKey; 18 | } 19 | 20 | function _getLocalMasterNode() { 21 | return ethers.utils.HDNode.fromMnemonic( 22 | 'test test test test test test test test test test test junk' // Default hardhat mnemonic 23 | ); 24 | } 25 | 26 | module.exports = { 27 | loadLocalWallets, 28 | getLocalPrivateKey, 29 | }; 30 | -------------------------------------------------------------------------------- /webpack.config.js: -------------------------------------------------------------------------------- 1 | const path = require('path'); 2 | 3 | module.exports = { 4 | entry: './index.js', 5 | output: { 6 | filename: 'browser.js', 7 | path: path.resolve(__dirname), 8 | library: 'synthetix', 9 | libraryTarget: 'umd', 10 | }, 11 | resolve: { 12 | fallback: { assert: false, stream: false }, 13 | }, 14 | }; 15 | --------------------------------------------------------------------------------