Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

merge 2.34.0 release into develop #940

Merged
merged 21 commits into from
Dec 1, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 1 addition & 1 deletion .circleci/config.yml
Expand Up @@ -10,7 +10,7 @@ commands:
default: false
steps:
- run:
command: node publish fork --network << parameters.network >> <<# parameters.reset >> --reset <</ parameters.reset >> --unlock-accounts 0xbe0eb53f46cd790cd13851d5eff43d12404d33e8
command: node publish fork --network << parameters.network >> <<# parameters.reset >> --reset <</ parameters.reset >> --unlock-accounts 0xF977814e90dA44bFA03b6295A0616a897441aceC
background: true
- cmd-wait-for-rpc
cmd-local-start:
Expand Down
2 changes: 1 addition & 1 deletion .circleci/src/commands/cmd-fork-start.yml
Expand Up @@ -8,6 +8,6 @@ parameters:
default: false
steps:
- run:
command: node publish fork --network << parameters.network >> <<# parameters.reset >> --reset <</ parameters.reset >> --unlock-accounts 0xbe0eb53f46cd790cd13851d5eff43d12404d33e8
command: node publish fork --network << parameters.network >> <<# parameters.reset >> --reset <</ parameters.reset >> --unlock-accounts 0xF977814e90dA44bFA03b6295A0616a897441aceC
background: true
- cmd-wait-for-rpc
27 changes: 22 additions & 5 deletions contracts/Exchanger.sol
Expand Up @@ -808,11 +808,28 @@ contract Exchanger is Owned, MixinResolver, MixinSystemSettings, IExchanger {
exchangeFeeRate = _feeRateForExchange(sourceCurrencyKey, destinationCurrencyKey);
}

function _feeRateForExchange(
bytes32, // API for source in case pricing model evolves to include source rate /* sourceCurrencyKey */
bytes32 destinationCurrencyKey
) internal view returns (uint exchangeFeeRate) {
return getExchangeFeeRate(destinationCurrencyKey);
function _feeRateForExchange(bytes32 sourceCurrencyKey, bytes32 destinationCurrencyKey)
internal
view
returns (uint exchangeFeeRate)
{
// Get the exchange fee rate as per destination currencyKey
exchangeFeeRate = getExchangeFeeRate(destinationCurrencyKey);

if (sourceCurrencyKey == sUSD || destinationCurrencyKey == sUSD) {
return exchangeFeeRate;
}

// Is this a swing trade? long to short or short to long skipping sUSD.
if (
(sourceCurrencyKey[0] == 0x73 && destinationCurrencyKey[0] == 0x69) ||
(sourceCurrencyKey[0] == 0x69 && destinationCurrencyKey[0] == 0x73)
) {
// Double the exchange fee
exchangeFeeRate = exchangeFeeRate.mul(2);
}

return exchangeFeeRate;
}

function getAmountsForExchange(
Expand Down
4 changes: 2 additions & 2 deletions index.js
Expand Up @@ -465,7 +465,7 @@ const decode = ({ network = 'mainnet', fs, path, data, target, useOvm = false }
return { method: abiDecoder.decodeMethod(data), contract };
};

const wrap = ({ network, fs, path, useOvm = false }) =>
const wrap = ({ network, deploymentPath, fs, path, useOvm = false }) =>
[
'decode',
'getAST',
Expand All @@ -480,7 +480,7 @@ const wrap = ({ network, fs, path, useOvm = false }) =>
'getVersions',
].reduce((memo, fnc) => {
memo[fnc] = (prop = {}) =>
module.exports[fnc](Object.assign({ network, useOvm, fs, path }, prop));
module.exports[fnc](Object.assign({ network, deploymentPath, fs, path, useOvm }, prop));
return memo;
}, {});

Expand Down
2 changes: 1 addition & 1 deletion package.json
@@ -1,6 +1,6 @@
{
"name": "synthetix",
"version": "2.33.2",
"version": "2.34.0",
"license": "MIT",
"author": "Synthetix",
"description": "The smart contracts which make up the Synthetix system. (synthetix.io)",
Expand Down
22 changes: 11 additions & 11 deletions publish/deployed/kovan/deployment.json

Large diffs are not rendered by default.

18 changes: 17 additions & 1 deletion publish/deployed/kovan/versions.json
Expand Up @@ -5853,8 +5853,24 @@
},
"Exchanger": {
"address": "0x189B2f2F23cC264518129a61c556490E1b8FF7A0",
"status": "replaced",
"keccak256": "0xee1b7e9552a2b8e7da01a7932c36340a6a1e667b8b37f6eefd7a59ef6bbc5361",
"replaced_in": "v2.33.0"
}
}
},
"v2.33.0": {
"tag": "v2.33.0",
"fulltag": "v2.33.0",
"release": "Adhara",
"network": "kovan",
"date": "2020-12-01T13:12:01+11:00",
"commit": "0de54808af511e54cd54d267bb65e9145b01ef88",
"contracts": {
"Exchanger": {
"address": "0x8EfAB91EAd9C4A89A83A7BB6E9f278aa916Eb4E1",
"status": "current",
"keccak256": "0xee1b7e9552a2b8e7da01a7932c36340a6a1e667b8b37f6eefd7a59ef6bbc5361"
"keccak256": "0x09fa1faaf859aae12a0424acc41b0e80c285f1af4b495a4659ac2b140afd8bdf"
}
}
}
Expand Down
52 changes: 41 additions & 11 deletions publish/deployed/mainnet/deployment.json

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion publish/deployed/mainnet/synths.json
Expand Up @@ -381,7 +381,7 @@
"subclass": "PurgeableSynth",
"inverted": {
"entryPoint": 45.087,
"upperLimit": 67.630,
"upperLimit": 67.63,
"lowerLimit": 22.543
}
}
Expand Down
22 changes: 19 additions & 3 deletions publish/deployed/mainnet/versions.json
Expand Up @@ -2394,15 +2394,16 @@
},
"Exchanger": {
"address": "0xd3970a9D35d2Be3aaf62D2b5B2be3Ee303aC4228",
"status": "current",
"keccak256": "0xee1b7e9552a2b8e7da01a7932c36340a6a1e667b8b37f6eefd7a59ef6bbc5361"
"status": "replaced",
"keccak256": "0xee1b7e9552a2b8e7da01a7932c36340a6a1e667b8b37f6eefd7a59ef6bbc5361",
"replaced_in": "v2.34.0"
}
}
},
"v2.33.1": {
"tag": "v2.33.1",
"fulltag": "v2.33.1",
"release": "regulus",
"release": "Regulus",
"network": "mainnet",
"date": "2020-11-24T12:48:26+11:00",
"commit": "1925c97723ce0b4871ac4864f1e63f5f12990c5a",
Expand All @@ -2412,5 +2413,20 @@
"status": "current"
}
}
},
"v2.34.0": {
"tag": "v2.34.0",
"fulltag": "v2.34.0",
"release": "Adhara",
"network": "mainnet",
"date": "2020-12-01T03:01:54+00:00",
"commit": "12576807a21a7efa6b2cbb47c5a9082a956edc64",
"contracts": {
"Exchanger": {
"address": "0x93b434b2e21d0F4E3ed1e9efa3Aa254A6D863B2A",
"status": "current",
"keccak256": "0x09fa1faaf859aae12a0424acc41b0e80c285f1af4b495a4659ac2b140afd8bdf"
}
}
}
}
9 changes: 9 additions & 0 deletions publish/releases.json
Expand Up @@ -65,5 +65,14 @@
},
"sources": ["Exchanger", "Synthetix"],
"sips": [94]
},
{
"name": "Adhara",
"version": {
"major": 2,
"minor": 34
},
"sources": ["Exchanger"],
"sips": [98, 99]
}
]
78 changes: 61 additions & 17 deletions test/contracts/Exchanger.spec.js
Expand Up @@ -23,6 +23,8 @@ const {
defaults: { WAITING_PERIOD_SECS, PRICE_DEVIATION_THRESHOLD_FACTOR },
} = require('../..');

const BN = require('bn.js');

const bnCloseVariance = '30';

const MockAggregator = artifacts.require('MockAggregatorV2V3');
Expand Down Expand Up @@ -390,15 +392,31 @@ contract('Exchanger (spec tests)', async accounts => {
actualFeeRate = await exchanger.feeRateForExchange(sUSD, iBTC);
assert.bnEqual(actualFeeRate, exchangeFeeRate, 'Rate must be the exchange fee rate');
});
it('for an inverse synth and a long synth, returns regular exchange fee', async () => {
it('for an inverse synth and a long synth, returns double the regular exchange fee', async () => {
let actualFeeRate = await exchanger.feeRateForExchange(iBTC, sEUR);
assert.bnEqual(actualFeeRate, exchangeFeeRate, 'Rate must be the exchange fee rate');
assert.bnEqual(
actualFeeRate,
exchangeFeeRate.mul(new BN(2)),
'Rate must be the exchange fee rate'
);
actualFeeRate = await exchanger.feeRateForExchange(sEUR, iBTC);
assert.bnEqual(actualFeeRate, exchangeFeeRate, 'Rate must be the exchange fee rate');
assert.bnEqual(
actualFeeRate,
exchangeFeeRate.mul(new BN(2)),
'Rate must be the exchange fee rate'
);
actualFeeRate = await exchanger.feeRateForExchange(sBTC, iBTC);
assert.bnEqual(actualFeeRate, exchangeFeeRate, 'Rate must be the exchange fee rate');
assert.bnEqual(
actualFeeRate,
exchangeFeeRate.mul(new BN(2)),
'Rate must be the exchange fee rate'
);
actualFeeRate = await exchanger.feeRateForExchange(iBTC, sBTC);
assert.bnEqual(actualFeeRate, exchangeFeeRate, 'Rate must be the exchange fee rate');
assert.bnEqual(
actualFeeRate,
exchangeFeeRate.mul(new BN(2)),
'Rate must be the exchange fee rate'
);
});
});

Expand Down Expand Up @@ -2091,19 +2109,14 @@ contract('Exchanger (spec tests)', async accounts => {
const assertExchangeSucceeded = async ({
amountExchanged,
txn,
exchangeFeeRateMultiplier = 1,
from = sUSD,
to = iBTC,
toContract = iBTCContract,
prevBalance,
}) => {
// Note: this presumes balance was empty before the exchange - won't work when
// exchanging into sUSD as there is an existing sUSD balance from minting
const exchangeFeeRate = await exchanger.feeRateForExchange(sUSD, iBTC);
const actualExchangeFee = multiplyDecimal(
exchangeFeeRate,
toUnit(exchangeFeeRateMultiplier)
);
const actualExchangeFee = await exchanger.feeRateForExchange(from, to);
const balance = await toContract.balanceOf(account1);
const effectiveValue = await exchangeRates.effectiveValue(
from,
Expand Down Expand Up @@ -2234,11 +2247,17 @@ contract('Exchanger (spec tests)', async accounts => {
from: account1,
});
});
it('then it exchanges correctly from iBTC to sBTC, not doubling the fee', async () => {
it('then it exchanges correctly from iBTC to sBTC, doubling the fee based on the destination Synth', async () => {
// get exchange fee for sUSD to sBTC (Base rate for destination synth)
const baseExchangeRate = await exchanger.feeRateForExchange(sUSD, sBTC);
const expectedExchangeRate = await exchanger.feeRateForExchange(iBTC, sBTC);

// swing trade should be double the base exchange fee
assert.bnEqual(expectedExchangeRate, baseExchangeRate.mul(new BN(2)));

await assertExchangeSucceeded({
amountExchanged: iBTCexchangeAmount,
txn,
exchangeFeeRateMultiplier: 1,
from: iBTC,
to: sBTC,
toContract: sBTCContract,
Expand All @@ -2252,11 +2271,20 @@ contract('Exchanger (spec tests)', async accounts => {
from: account1,
});
});
it('then it exchanges correctly from iBTC to sEUR, not doubling the fee', async () => {
it('then it exchanges correctly from iBTC to sEUR, doubling the fee', async () => {
// get exchange fee for sUSD to sEUR (Base rate for destination synth)
const baseExchangeRate = await exchanger.feeRateForExchange(sUSD, sEUR);
const expectedExchangeRate = await exchanger.feeRateForExchange(
iBTC,
sEUR
);

// swing trade should be double the base exchange fee
assert.bnEqual(expectedExchangeRate, baseExchangeRate.mul(new BN(2)));

await assertExchangeSucceeded({
amountExchanged: iBTCexchangeAmount,
txn,
exchangeFeeRateMultiplier: 1,
from: iBTC,
to: sEUR,
toContract: sEURContract,
Expand All @@ -2273,11 +2301,20 @@ contract('Exchanger (spec tests)', async accounts => {
from: account1,
});
});
it('then it exchanges correctly from sEUR to iBTC, not doubling the fee', async () => {
it('then it exchanges correctly from sEUR to iBTC, doubling the fee', async () => {
// get exchange fee for sUSD to iBTC (Base rate for destination synth)
const baseExchangeRate = await exchanger.feeRateForExchange(sUSD, iBTC);
const expectedExchangeRate = await exchanger.feeRateForExchange(
sEUR,
iBTC
);

// swing trade should be double the base exchange fee
assert.bnEqual(expectedExchangeRate, baseExchangeRate.mul(new BN(2)));

await assertExchangeSucceeded({
amountExchanged: sEURExchangeAmount,
txn,
exchangeFeeRateMultiplier: 1,
from: sEUR,
to: iBTC,
toContract: iBTCContract,
Expand All @@ -2299,6 +2336,13 @@ contract('Exchanger (spec tests)', async accounts => {
});
});
it('then it exchanges correctly out of iBTC, with the regular fee', async () => {
// get exchange fee for sETH to sUSD (Base rate for destination synth into sUSD)
const baseExchangeRate = await exchanger.feeRateForExchange(sETH, sUSD);
const expectedExchangeRate = await exchanger.feeRateForExchange(iBTC, sUSD);

// exchange fee should be the same base exchange fee
assert.bnEqual(expectedExchangeRate, baseExchangeRate);

await assertExchangeSucceeded({
amountExchanged: iBTCexchangeAmount,
txn,
Expand Down
4 changes: 2 additions & 2 deletions test/prod/EtherCollateral.prod.js
Expand Up @@ -88,7 +88,7 @@ contract('EtherCollateral (prod tests)', accounts => {
});

describe('opening a loan', () => {
const amount = toUnit('5');
const amount = toUnit('1');

let ethBalance, sEthBalance;
let tx;
Expand All @@ -113,7 +113,7 @@ contract('EtherCollateral (prod tests)', accounts => {
describe('closing a loan', () => {
before(async () => {
if (network === 'local') {
const amount = toUnit('100');
const amount = toUnit('1000');

const balance = await SynthsUSD.balanceOf(Depot.address);
if (balance.lt(amount)) {
Expand Down
7 changes: 6 additions & 1 deletion test/prod/ExchangeRates.prod.js
Expand Up @@ -86,7 +86,11 @@ contract('ExchangeRates (prod tests)', accounts => {

describe('when an exchange is made', () => {
let waitingPeriod;
before(async () => {
before(async function() {
if (config.useOvm) {
this.skip();
}

await exchangeSynths({
network,
deploymentPath,
Expand All @@ -97,6 +101,7 @@ contract('ExchangeRates (prod tests)', accounts => {
});
waitingPeriod = Number(await SystemSettings.waitingPeriodSecs());
});

it('should settle', async () => {
await fastForward(waitingPeriod);
await Exchanger.settle(user, toBytes32('sETH'), { from: user });
Expand Down
9 changes: 8 additions & 1 deletion test/prod/Synthetix.prod.js
Expand Up @@ -6,6 +6,7 @@ const { assert, addSnapshotBeforeRestoreAfter } = require('../contracts/common')
const { toUnit, fromUnit } = require('../utils')();
const { wrap, toBytes32 } = require('../..');
const {
knownMainnetWallet,
detectNetworkName,
connectContracts,
connectContract,
Expand Down Expand Up @@ -172,6 +173,12 @@ contract('Synthetix (prod tests)', accounts => {
});

describe('exchanging', () => {
before('skip if there is no exchanging implementation', async function() {
if (config.useOvm) {
this.skip();
}
});

addSnapshotBeforeRestoreAfter();

it('can exchange sUSD to sETH', async () => {
Expand Down Expand Up @@ -346,7 +353,7 @@ contract('Synthetix (prod tests)', accounts => {
});

describe('with virtual tokens and a custom swap contract', () => {
const usdcHolder = '0xbe0eb53f46cd790cd13851d5eff43d12404d33e8';
const usdcHolder = knownMainnetWallet;
const usdc = '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48';
const wbtc = '0x2260fac5e5542a773aa44fbcfedf7c193bc2c599';

Expand Down