Skip to content

Commit

Permalink
M-02 [Oval] Attempts to Push Price to the CoinbaseOracle Will Always …
Browse files Browse the repository at this point in the history
…Fail (#18)

Signed-off-by: Pablo Maldonado <pablo@umaproject.org>
  • Loading branch information
md0x authored Jun 18, 2024
1 parent 6f53172 commit ff31b1b
Show file tree
Hide file tree
Showing 13 changed files with 917 additions and 76 deletions.
3 changes: 3 additions & 0 deletions scripts/.env.example
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,6 @@
TENDERLY_USER=
TENDERLY_PROJECT=
TENDERLY_ACCESS_KEY=
COINBASE_API_KEY=
COINBASE_API_SECRET=
COINBASE_API_PASSPHRASE=
40 changes: 40 additions & 0 deletions scripts/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,3 +36,43 @@ The script will create Tenderly forks that have Note starting with `Generated: 0
identify the forks that it had created and delete them when creating the same type of simulation. If you are sharing
Tenderly forks with other people, it is better to remove the `Generated: 0x...` Note from the fork through Tenderly
UI.


# Coinbase API Price Scripts

The following describes the Coinbase API Price Scripts to fetch cryptocurrency prices from the Coinbase API and logs related messages and signatures.

## Prerequisites

Before running the scripts you need to create an .env file in the scripts directory of the project and add the following environment variables:

```
COINBASE_API_KEY=your_api_key
COINBASE_API_SECRET=your_api_secret
COINBASE_API_PASSPHRASE=your_api_passphrase
```

## Installation

To set up the project, you need to install the necessary dependencies. You can do this by running the following command in your terminal:

```
yarn install
```

## Running the Scripts

Once the installation is complete, you can start the scripts with the following command:

Fetch data from the Coinbase API and save it to a file:
```
node ./src/fetchData.js
```
Read data from the file and send it to stdout:
```
node ./src/readData.js
```

## Integrating Signatures and Messages

test/unit/CoinbaseOracle.sol uses the out `fetchData.js` and `readData.js` scripts to fetch data from the Coinbase API and push it the CoinbaseOracle smart contract. Make sure the .env file is set up correctly before running the forge test.
12 changes: 7 additions & 5 deletions scripts/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,16 @@
"clean": "rm -rf contract-types && rm -rf dist && rm -rf node_modules"
},
"devDependencies": {
"@redstone-finance/protocol": "^0.5.1",
"@redstone-finance/sdk": "^0.5.1",
"@typechain/ethers-v5": "^11.1.2",
"@types/node": "^20.8.6",
"typechain": "^8.3.2",
"typescript": "^5.2.2",
"axios": "^1.5.1",
"dotenv": "^16.3.1",
"dotenv": "^16.4.5",
"ethers": "^5.7.2",
"@redstone-finance/protocol": "^0.5.1",
"@redstone-finance/sdk": "^0.5.1"
"typechain": "^8.3.2",
"typescript": "^5.2.2",
"node-fetch": "^3.3.2",
"web3": "^4.9.0"
}
}
54 changes: 54 additions & 0 deletions scripts/src/coinbase/data.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
{
"BTC": {
"message": "0x000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000667021bc00000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000f527b32780000000000000000000000000000000000000000000000000000000000000006707269636573000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000034254430000000000000000000000000000000000000000000000000000000000",
"signature": "0xfe72fff2d36008b1ad1c2f4bedd2457922ead78ba27b2cbdce6759a2bd833420966064a6df58df6a2d38c5283c7247abd68bff21cf3d237006e5bd0216bc76bc000000000000000000000000000000000000000000000000000000000000001c"
},
"ETH": {
"message": "0x000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000667021bc00000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000d22e27000000000000000000000000000000000000000000000000000000000000000006707269636573000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000034554480000000000000000000000000000000000000000000000000000000000",
"signature": "0xec8905696b28efa8e0b1715d0066d90ec6488915a8db5dc134d94bb11af5ec9ea95755f82e3b38f7a133b8629156ab4f71f1816c475db72554d6001ec1ec4b96000000000000000000000000000000000000000000000000000000000000001b"
},
"XTZ": {
"message": "0x0000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000006670218000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000bc7a000000000000000000000000000000000000000000000000000000000000000067072696365730000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000358545a0000000000000000000000000000000000000000000000000000000000",
"signature": "0x8d86bf14f9e635caab4300780a7e830a372fee09ea61223793910b9533a0e7eb695ac2e43c36aa32ac26d501a272849ea800e1b13294fe26a10746f0be46542c000000000000000000000000000000000000000000000000000000000000001c"
},
"DAI": {
"message": "0x00000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000062cedf1c00000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000f41780000000000000000000000000000000000000000000000000000000000000006707269636573000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000034441490000000000000000000000000000000000000000000000000000000000",
"signature": "0xad99f6564beb896c16f31145b5b3f176c7ac9ac1bba315d42ef252c460b7a0a9cd75d5e25e7d05d0616d4341a1f93c46168c487addf04414d7ab1d7b44ea4887000000000000000000000000000000000000000000000000000000000000001c"
},
"REP": {
"message": "0x0000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000006424597800000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000000788b600000000000000000000000000000000000000000000000000000000000000006707269636573000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000035245500000000000000000000000000000000000000000000000000000000000",
"signature": "0x3df12304d9ac17111ac80a7237ec2fa994e1fc7b56547f12e4a66f30b4e60ff6f3adc3cc845993832855c4796b44e09b82770c7d888684eb5ae0695548e41dd8000000000000000000000000000000000000000000000000000000000000001b"
},
"ZRX": {
"message": "0x0000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000006670218000000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000005d7330000000000000000000000000000000000000000000000000000000000000006707269636573000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000035a52580000000000000000000000000000000000000000000000000000000000",
"signature": "0x2268a2c9c7939008468c5456906f8d2abba88e91b498782b17e53607c8512c2ff85c6f89ee9d7b2d559cb6e4b36d82d7858f866c73edb82f3b6a6e2695cd29cb000000000000000000000000000000000000000000000000000000000000001c"
},
"BAT": {
"message": "0x00000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000062cf049c00000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000005a7b20000000000000000000000000000000000000000000000000000000000000006707269636573000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000034241540000000000000000000000000000000000000000000000000000000000",
"signature": "0x882bc7b0c91e58ca72e5689789463fad2772de1cd4b58c3e3cde43c4a3519fb3dd4e15256dffa71504048afa784bd288570aa98a7a660c54ef147256b302281e000000000000000000000000000000000000000000000000000000000000001c"
},
"KNC": {
"message": "0x0000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000006670210800000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000009d2100000000000000000000000000000000000000000000000000000000000000006707269636573000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000034b4e430000000000000000000000000000000000000000000000000000000000",
"signature": "0x51bdd17d0094d50a53b7d4e87bc85e7135c958945203016aebefccf40dc5f7b3c16f2b163bf3f8c40b4ace3336146614d7a7433a121be14934fb0f11407886bc000000000000000000000000000000000000000000000000000000000000001b"
},
"LINK": {
"message": "0x000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000667021bc00000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000000da7f8c0000000000000000000000000000000000000000000000000000000000000006707269636573000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000044c494e4b00000000000000000000000000000000000000000000000000000000",
"signature": "0xb26581f2666663e06e715e4ce71f7deb4c96ff767bba5b5d998c572ece609685e8f8e9fb4f7dd7017d5ca4c8eba5335e45da4ad4e00b6fb3fad7b0912e54457a000000000000000000000000000000000000000000000000000000000000001b"
},
"COMP": {
"message": "0x0000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000006670218000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000031640b0000000000000000000000000000000000000000000000000000000000000000670726963657300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004434f4d5000000000000000000000000000000000000000000000000000000000",
"signature": "0x0d26681fb760c2b8cfa540d94b2d829e3711c4ee86cfbc9c9c044e75bffa39339293af1b40b5dbe878bf2bd98d4a3c3e83afd79a16ca591fc51847fe8cebac19000000000000000000000000000000000000000000000000000000000000001b"
},
"UNI": {
"message": "0x000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000667021bc00000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000000a63e98000000000000000000000000000000000000000000000000000000000000000670726963657300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003554e490000000000000000000000000000000000000000000000000000000000",
"signature": "0x5b6d356b3d4c6b9dadfd4807e45e434cbecd6cab3e741191a1c6ef830b4aa0a52cceba6adfece1e0dbdeed1d4c9322d6b4a82e4bdc7e9e7f3ab25d6a5289f019000000000000000000000000000000000000000000000000000000000000001c"
},
"GRT": {
"message": "0x000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000667021bc00000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000000034db40000000000000000000000000000000000000000000000000000000000000006707269636573000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000034752540000000000000000000000000000000000000000000000000000000000",
"signature": "0x94bc918d38446f273ca07d91d9f1fff8bb0f2fcb31eb726ef26a32464e74ab07824edd51d32d9c343fef801c60d8731f4be8c6b287b956975d9b8998d56be7a6000000000000000000000000000000000000000000000000000000000000001b"
},
"SNX": {
"message": "0x00000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000066701fdc00000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000001f5964000000000000000000000000000000000000000000000000000000000000000670726963657300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003534e580000000000000000000000000000000000000000000000000000000000",
"signature": "0xe4e42dccf098cff55a1ef70bd97e0c2f3808e3a47b12b1187d9a3da65f2f3410e50edb6937210671f3a85168a95a44b031e113132cd281d40f4506862d31c72f000000000000000000000000000000000000000000000000000000000000001b"
}
}
67 changes: 67 additions & 0 deletions scripts/src/coinbase/fetchData.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
require("dotenv").config(); // Add dotenv package to load environment variables
const fs = require("fs");
const path = require("path");
const crypto = require("crypto");
const web3 = require("web3");

const { COINBASE_API_KEY, COINBASE_API_SECRET, COINBASE_API_PASSPHRASE } =
process.env;
if (!COINBASE_API_KEY || !COINBASE_API_SECRET || !COINBASE_API_PASSPHRASE) {
console.log(
"error: missing one or more of COINBASE_API_KEY, COINBASE_API_SECRET, COINBASE_API_PASSPHRASE environment variables"
);
process.exit(1);
}

const API_URL = "https://api.exchange.coinbase.com";

async function main() {
const timestamp = (new Date().getTime() / 1000).toString();
const message = timestamp + "GET" + "/oracle";
const hmac = crypto
.createHmac("sha256", Buffer.from(COINBASE_API_SECRET, "base64"))
.update(message);
const signature = hmac.digest("base64");

const headers = {
"CB-ACCESS-SIGN": signature,
"CB-ACCESS-TIMESTAMP": timestamp,
"CB-ACCESS-KEY": COINBASE_API_KEY,
"CB-ACCESS-PASSPHRASE": COINBASE_API_PASSPHRASE,
};

const res = await fetch(API_URL + "/oracle", { method: "GET", headers });

const { messages, signatures } = await res.json();

const output = {};
for (let i = 0; i < messages.length; ++i) {
const record = Object.values(
web3.eth.abi.decodeParameters(
["string", "uint", "string", "uint"],
messages[i]
)
).slice(0, -1);

const adr = web3.eth.accounts.recover(
web3.utils.keccak256(messages[i]),
signatures[i]
);

if (adr !== "0xfCEAdAFab14d46e20144F48824d0C09B1a03F2BC")
throw new Error("Invalid signature");

output[record[2]] = {
message: messages[i],
signature: signatures[i],
};
}

const filePath = path.join(__dirname, "data.json");

fs.mkdirSync(path.dirname(filePath), { recursive: true });

fs.writeFileSync(filePath, JSON.stringify(output, null, 2));
}

main();
37 changes: 37 additions & 0 deletions scripts/src/coinbase/readData.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
require("dotenv").config(); // Load environment variables from .env file
const web3 = require("web3");
const fs = require("fs");
const path = require("path");

async function main(symbol) {
try {
if (!symbol) {
console.error("Error: No symbol argument provided");
process.exit(1);
}

const filePath = path.join(__dirname, "data.json");

const file = fs.readFileSync(filePath);
const data = JSON.parse(file);
const tickerData = data[symbol];

if (!tickerData) {
console.error("Error: Symbol not found");
process.exit(1);
}

const encodedData = web3.eth.abi.encodeParameters(
["bytes", "bytes"],
[tickerData.message, tickerData.signature]
);

process.stdout.write(encodedData);
} catch (error) {
console.error("An error occurred:", error.message);
process.exit(1);
}
}

const symbolArg = process.argv[2];
main(symbolArg);
Loading

0 comments on commit ff31b1b

Please sign in to comment.