Skip to content
This repository has been archived by the owner on Sep 27, 2022. It is now read-only.

Commit

Permalink
add Maker Price Oracle
Browse files Browse the repository at this point in the history
  • Loading branch information
Brendan Chou committed Mar 30, 2020
1 parent 935a206 commit 4c5dd42
Show file tree
Hide file tree
Showing 14 changed files with 376 additions and 8 deletions.
41 changes: 41 additions & 0 deletions contracts/external/maker/I_MakerOracle.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
/*
Copyright 2020 dYdX Trading Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

pragma solidity 0.5.16;
pragma experimental ABIEncoderV2;


/**
* @title I_MakerOracle
* @author dYdX
*
* Interface for the price oracles run by MakerDao
*/
interface I_MakerOracle {
// returns the current value (ETH/USD * 10**18) as a bytes32
function peek()
external
view
returns (bytes32, bool);

// requires a fresh price and then returns the current value
function read()
external
view
returns (bytes32);
}
2 changes: 1 addition & 1 deletion contracts/protocol/lib/TypedSignature.sol
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/*
Copyright 2019 dYdX Trading Inc.
Copyright 2020 dYdX Trading Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
Expand Down
69 changes: 69 additions & 0 deletions contracts/protocol/v1/oracles/P1MakerOracle.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
/*
Copyright 2020 dYdX Trading Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

pragma solidity 0.5.16;
pragma experimental ABIEncoderV2;

import { I_MakerOracle } from "../../../external/maker/I_MakerOracle.sol";
import { I_P1Oracle } from "../intf/I_P1Oracle.sol";


/**
* @title P1MakerOracle
* @author dYdX
*
* P1Oracle that reads the price directly from a Maker V2 Oracle.
*/
contract P1MakerOracle is
I_P1Oracle
{
// ============ Storage ============

address public _ORACLE_ADDRESS_;

address public _PERPETUAL_V1_;

// ============ Constructor ============

constructor(
address perpetualV1,
address oracleAddress
)
public
{
_PERPETUAL_V1_ = perpetualV1;
_ORACLE_ADDRESS_ = oracleAddress;
}

// ============ Public Functions ============

/**
* Returns the price of the underlying asset relative to the margin token.
*/
function getPrice()
external
view
returns (uint256)
{
require(
msg.sender == _PERPETUAL_V1_,
"msg.sender must be PerpetualV1"
);
return uint256(I_MakerOracle(_ORACLE_ADDRESS_).read());
}
}
77 changes: 77 additions & 0 deletions contracts/test/external/Test_MakerOracle.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
/*
Copyright 2020 dYdX Trading Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

pragma solidity 0.5.16;
pragma experimental ABIEncoderV2;

import { I_MakerOracle } from "../../external/maker/I_MakerOracle.sol";


/**
* @title Test_MakerOracle
* @author dYdX
*
* MakerOracle for testing
*/
/* solium-disable-next-line camelcase */
contract Test_MakerOracle is
I_MakerOracle
{
uint256 public _PRICE_ = 0;
bool public _VALID_ = true;

// ============ Set Functions ============

function setPrice(
uint256 newPrice
)
external
{
_PRICE_ = newPrice;
}

function setValidity(
bool valid
)
external
{
_VALID_ = valid;
}

// ============ Get Functions ============

function read()
external
view
returns (bytes32)
{
require(
_VALID_,
"Median/invalid-price-feed"
);
return bytes32(_PRICE_);
}

function peek()
external
view
returns (bytes32, bool)
{
return (bytes32(_PRICE_), _VALID_);
}
}
25 changes: 19 additions & 6 deletions migrations/2_deploy.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
const {
getChainId,
isDevNetwork,
getMakerPriceOracleAddress,
} = require('./helpers');

// ============ Contracts ============
Expand All @@ -35,13 +36,17 @@ const P1Orders = artifacts.require('P1Orders');
const P1Deleveraging = artifacts.require('P1Deleveraging');
const P1Liquidation = artifacts.require('P1Liquidation');

// Price Oracles
const P1MakerOracle = artifacts.require('P1MakerOracle');

// Test Contracts
const TestLib = artifacts.require('Test_Lib');
const TestP1Funder = artifacts.require('Test_P1Funder');
const TestP1Monolith = artifacts.require('Test_P1Monolith');
const TestP1Oracle = artifacts.require('Test_P1Oracle');
const TestP1Trader = artifacts.require('Test_P1Trader');
const TestToken = artifacts.require('Test_Token');
const TestMakerOracle = artifacts.require('Test_MakerOracle');

// ============ Main Migration ============

Expand All @@ -51,8 +56,8 @@ const migration = async (deployer, network, accounts) => {
deployProtocol(deployer, network, accounts),
]);

await deployOracles(deployer, network, accounts);
await deployTraders(deployer, network, accounts);
await deployOracles(deployer, network);
await deployTraders(deployer, network);
};

module.exports = migration;
Expand All @@ -68,6 +73,7 @@ async function deployTestContracts(deployer, network) {
deployer.deploy(TestP1Oracle),
deployer.deploy(TestP1Trader),
deployer.deploy(TestToken),
deployer.deploy(TestMakerOracle),
]);
}
}
Expand All @@ -82,10 +88,17 @@ async function deployProtocol(deployer, network, accounts) {
);
}

async function deployOracles(deployer) {
await deployer.deploy(
P1FundingOracle,
);
async function deployOracles(deployer, network) {
await Promise.all([
deployer.deploy(
P1FundingOracle,
),
deployer.deploy(
P1MakerOracle,
PerpetualProxy.address,
getMakerPriceOracleAddress(network, TestMakerOracle.address),
),
]);
}

async function deployTraders(deployer, network) {
Expand Down
1 change: 1 addition & 0 deletions migrations/deployed.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{}
22 changes: 22 additions & 0 deletions migrations/helpers.js
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,29 @@ function verifyNetwork(network) {
}
}

function getPartiallyDelayedMultisigAddress(network) {
if (isMainnet(network)) {
return '0xba2906b18B069b40C6D2CAFd392E76ad479B1B53';
}
if (isKovan(network)) {
return '0x3d62d8b3ef034e0fde7de8fec4f557a3e6e4efa1';
}
throw new Error('Cannot find Admin Multisig');
}

function getMakerPriceOracleAddress(network, devAddress) {
if (isMainnet(network)) {
return '0x064409168198A7E9108036D072eF59F923dEDC9A';
}
if (isDevNetwork(network)) {
return devAddress;
}
throw new Error('Cannot find MakerPriceOracle');
}

module.exports = {
getChainId,
isDevNetwork,
getPartiallyDelayedMultisigAddress,
getMakerPriceOracleAddress,
};
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,11 @@
"lint:sol": "solium -d contracts/",
"lint:dydx": "python util/lintcontracts.py",
"docker_node": "ganache-cli -i 1313 -d -k=istanbul -p 8545 -h 0.0.0.0 --db=/home/.ganache",
"deploy": "truffle migrate --network=$NETWORK --reset",
"deploy": "truffle migrate --network=$NETWORK --reset && npm run save_deployed_addresses",
"deploy_test": "npm run reset_test_evm && NETWORK=test npm run deploy && npm run snapshot_test_evm",
"migrate": "truffle migrate",
"reset_test_evm": "node scripts/reset-test-evm.js",
"save_deployed_addresses": "ts-node ./scripts/SaveDeployedAddresses.ts",
"snapshot_test_evm": "node scripts/snapshot-test-evm.js"
},
"repository": {
Expand Down
3 changes: 3 additions & 0 deletions src/Perpetual.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ import { Admin } from './modules/Admin';
import { Deleveraging } from './modules/Deleveraging';
import { FinalSettlement } from './modules/FinalSettlement';
import { FundingOracle } from './modules/FundingOracle';
import { PriceOracle } from './modules/PriceOracle';
import { Liquidation } from './modules/Liquidation';
import { Getters } from './modules/Getters';
import { Margin } from './modules/Margin';
Expand All @@ -47,6 +48,7 @@ export class Perpetual {
public deleveraging: Deleveraging;
public finalSettlement: FinalSettlement;
public fundingOracle: FundingOracle;
public priceOracle: PriceOracle;
public liquidation: Liquidation;
public getters: Getters;
public logs: Logs;
Expand All @@ -67,6 +69,7 @@ export class Perpetual {
this.deleveraging = new Deleveraging(this.contracts);
this.finalSettlement = new FinalSettlement(this.contracts);
this.fundingOracle = new FundingOracle(this.contracts);
this.priceOracle = new PriceOracle(this.contracts);
this.liquidation = new Liquidation(this.contracts);
this.getters = new Getters(this.contracts);
this.logs = new Logs(this.contracts, this.web3);
Expand Down
6 changes: 6 additions & 0 deletions src/modules/Contracts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ const jsonFolder = `../../${process.env.COVERAGE ? '.coverage_artifacts' : 'buil
const perpetualProxyJson = require(`${jsonFolder}PerpetualProxy.json`);
const perpetualV1Json = require(`${jsonFolder}PerpetualV1.json`);
const p1FundingOracleJson = require(`${jsonFolder}P1FundingOracle.json`);
const p1MakerOracleJson = require(`${jsonFolder}P1MakerOracle.json`);
const p1OrdersJson = require(`${jsonFolder}P1Orders.json`);
const p1DeleveragingJson = require(`${jsonFolder}P1Deleveraging.json`);
const p1LiquidationJson = require(`${jsonFolder}P1Liquidation.json`);
Expand All @@ -43,6 +44,7 @@ const testP1MonolithJson = require(`${jsonFolder}Test_P1Monolith.json`);
const testP1OracleJson = require(`${jsonFolder}Test_P1Oracle.json`);
const testP1TraderJson = require(`${jsonFolder}Test_P1Trader.json`);
const testTokenJson = require(`${jsonFolder}Test_Token.json`);
const testMakerOracleJson = require(`${jsonFolder}Test_MakerOracle.json`);

import {
address,
Expand Down Expand Up @@ -73,6 +75,7 @@ export class Contracts {
public perpetualProxy: Contract;
public perpetualV1: Contract;
public p1FundingOracle: Contract;
public p1MakerOracle: Contract;
public p1Orders: Contract;
public p1Deleveraging: Contract;
public p1Liquidation: Contract;
Expand All @@ -84,6 +87,7 @@ export class Contracts {
public testP1Oracle: Contract;
public testP1Trader: Contract;
public testToken: Contract;
public testMakerOracle: Contract;

constructor(
provider: Provider,
Expand All @@ -106,6 +110,7 @@ export class Contracts {
this.perpetualProxy = this.addMainContract(perpetualProxyJson);
this.perpetualV1 = this.addMainContract(perpetualV1Json);
this.p1FundingOracle = this.addMainContract(p1FundingOracleJson);
this.p1MakerOracle = this.addMainContract(p1MakerOracleJson);
this.p1Orders = this.addMainContract(p1OrdersJson);
this.p1Deleveraging = this.addMainContract(p1DeleveragingJson);
this.p1Liquidation = this.addMainContract(p1LiquidationJson);
Expand All @@ -117,6 +122,7 @@ export class Contracts {
this.testP1Oracle = this.addTestContract(testP1OracleJson);
this.testP1Trader = this.addTestContract(testP1TraderJson);
this.testToken = this.addTestContract(testTokenJson);
this.testMakerOracle = this.addTestContract(testMakerOracleJson);

this.setProvider(provider, networkId);
this.setDefaultAccount(this.web3.eth.defaultAccount);
Expand Down
Loading

0 comments on commit 4c5dd42

Please sign in to comment.