Skip to content

Commit

Permalink
Add lots of JS from Nantucket and pair contract
Browse files Browse the repository at this point in the history
  • Loading branch information
haydenshively committed Oct 25, 2020
1 parent 069fd98 commit 0d9aea9
Show file tree
Hide file tree
Showing 20 changed files with 1,623 additions and 11 deletions.
14 changes: 14 additions & 0 deletions .openzeppelin/mainnet.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{
"contracts": {},
"solidityLibs": {},
"proxies": {
"CafeChi/CafeChi": [
{
"address": "0x9dB0987bAAC8EAA684Ff54F836a2368109f1761C",
"kind": "NonProxy",
"bytecodeHash": "5c8aa614716e91c24afbbe430b6654219ce01bb2da808322eac37cd6348cbf6b"
}
]
},
"manifestVersion": "2.2"
}
23 changes: 18 additions & 5 deletions networks.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,25 @@
const HDWalletProvider = require("@truffle/hdwallet-provider");
require("dotenv").config();

module.exports = {
networks: {
development: {
protocol: 'http',
host: 'localhost',
ganache: {
protocol: "http",
host: "localhost",
port: 8545,
gas: 6000000,
gasPrice: 45e9,
networkId: '*',
networkId: "*"
},
},
production: {
provider: () =>
new HDWalletProvider(
process.env.ACCOUNT_SECRET,
"https://mainnet.infura.io/v3/" + process.env.PROVIDER_INFURA_ID
),
gas: 4000000,
gasPrice: 26e9,
networkId: "*"
}
}
};
5 changes: 5 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,17 @@
"@openzeppelin/cli": "^2.8.2",
"@openzeppelin/contracts": "^3.2.0",
"@truffle/hdwallet-provider": "^1.1.1",
"@uniswap/v2-core": "^1.0.1",
"big.js": "^6.0.1",
"dotenv": "^8.2.0",
"ethereumjs-tx": "^2.1.2",
"ganache-cli": "^6.12.0",
"mocha": "^8.2.0",
"node-fetch": "^2.6.1",
"web3": "^1.3.0",
"winston": "^3.3.3"
},
"scripts": {
"test": "mocha --file './tests/setup.js' 'tests/**/*.test.js' --recursive"
}
}
43 changes: 43 additions & 0 deletions src/logging/slackhook.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
const nfetch = require("node-fetch");
const Transport = require("winston-transport");

class SlackHook extends Transport {
constructor(opts) {
super(opts);

opts = opts || {};

this.webhookUrl = opts.webhookUrl;
this.formatter = opts.formatter || undefined;
this.mrkdwn = opts.mrkdwn || false;
}

log(info, callback) {
let payload = {
mrkdwn: this.mrkdwn
};

if (this.formatter && typeof this.formatter === "function") {
let layout = this.formatter(info);

// Note: Supplying `text` when `blocks` is also supplied will cause `text`
// to be used as a fallback for clients/surfaces that don't support blocks
payload.text = layout.text || undefined;
payload.blocks = layout.blocks || undefined;
payload.attachments = layout.attachments || undefined;
} else {
payload.text = `${info.message}`;
}

const params = {
method: "POST",
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify(payload)
};
nfetch(this.webhookUrl, params).then(callback());
}
}

module.exports = SlackHook;
13 changes: 13 additions & 0 deletions src/network/web/fetchable.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
class Fetchable {
constructor() {
if (new.target === Fetchable) {
throw new TypeError(
"Fetchable is abstract. Please subclass to construct."
);
}
}

async fetch(withConfig) {}
}

module.exports = Fetchable;
21 changes: 21 additions & 0 deletions src/network/web/gasprice.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
const nfetch = require("node-fetch");

const Fetchable = require("./fetchable");

class GasPrice extends Fetchable {
async fetch() {
const res = await nfetch(process.env.GAS_STATION_ENDPOINT, {
method: "GET"
});
const json = await res.json();

return {
fastest: json.fastest ? Number(json.fastest) * 1e8 : null,
fast: json.fast ? Number(json.fast) * 1e8 : null,
average: json.average ? Number(json.average) * 1e8 : null,
safeLow: json.safeLow ? Number(json.safeLow) * 1e8 : null
};
}
}

module.exports = GasPrice;
41 changes: 41 additions & 0 deletions src/network/webthree/abis/goldenage/cafechi.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
[
{
"inputs": [],
"name": "arb",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "sender",
"type": "address"
},
{
"internalType": "uint256",
"name": "amount0",
"type": "uint256"
},
{
"internalType": "uint256",
"name": "amount1",
"type": "uint256"
},
{
"internalType": "bytes",
"name": "data",
"type": "bytes"
}
],
"name": "uniswapV2Call",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"stateMutability": "payable",
"type": "receive"
}
]
153 changes: 153 additions & 0 deletions src/network/webthree/goldenage/cafechi.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,153 @@
const Big = require("big.js");
Big.DP = 40;
Big.RM = 0;

const Web3Utils = require("web3-utils");

const SmartContract = require("../smartcontract");

class CafeChi extends SmartContract {
arb() {
return this._txFor(this._inner.methods.arb());
}


liquidateSNWithPrice(
messages,
signatures,
symbols,
borrowers,
repayCTokens,
seizeCTokens,
gasPrice,
chi = false
) {
const cTokens = this._combineTokens(repayCTokens, seizeCTokens);
let method = chi
? this._inner.methods.liquidateSNWithPriceChi
: this._inner.methods.liquidateSNWithPrice;
method = method(messages, signatures, symbols, borrowers, cTokens);
// TODO we cheat here by just estimating gas for first candidate since
// that's all that TxManager cares about at the moment.
const gasLimit = this._estimateGas(repayCTokens[0], seizeCTokens[0], true);
return this._txFor(method, gasLimit, gasPrice);
}

/**
* Performs liquidation on multiple accounts (SEND -- uses gas)
*
* @param {Array<String>} borrowers addresses of users with negative liquidity
* @param {Array<String>} repayCTokens address of token to repay
* @param {Array<String>} seizeCTokens address of token to seize
* @param {Number} gasPrice the gas price to use, in gwei
* @return {Object} the transaction object
*/
liquidateSN(borrowers, repayCTokens, seizeCTokens, gasPrice, chi = false) {
const cTokens = this._combineTokens(repayCTokens, seizeCTokens);
let method = chi
? this._inner.methods.liquidateSNChi
: this._inner.methods.liquidateSN;
method = method(borrowers, cTokens);
// TODO we cheat here by just estimating gas for first candidate since
// that's all that TxManager cares about at the moment.
const gasLimit = this._estimateGas(repayCTokens[0], seizeCTokens[0]);
return this._txFor(method, gasLimit, gasPrice);
}

liquidateSWithPrice(
messages,
signatures,
symbols,
borrower,
repayCToken,
seizeCToken,
gasPrice,
chi = false
) {
let method = chi
? this._inner.methods.liquidateSWithPriceChi
: this._inner.methods.liquidateSWithPrice;
method = method(
messages,
signatures,
symbols,
borrower,
repayCToken,
seizeCToken
);
const gasLimit = this._estimateGas(repayCToken, seizeCToken, true);
return this._txFor(method, gasLimit, gasPrice);
}

liquidateS(borrower, repayCToken, seizeCToken, gasPrice, chi = false) {
let method = chi
? this._inner.methods.liquidateSChi
: this._inner.methods.liquidateS;
method = method(borrower, repayCToken, seizeCToken);
const gasLimit = this._estimateGas(repayCToken, seizeCToken);
return this._txFor(method, gasLimit, gasPrice);
}

/**
* Performs liquidation (SEND -- uses gas)
*
* @param {string} borrower address of any user with negative liquidity
* @param {string} repayCToken address of token to repay
* @param {string} seizeCToken address of token to seize
* @param {Big} amount debt to repay, in units of the ordinary asset
* @param {Number} gasPrice the gas price to use, in gwei
* @return {Promise<Object>} the transaction object
*/
liquidate(borrower, repayCToken, seizeCToken, amount, gasPrice) {
const hexAmount = Web3Utils.toHex(amount.toFixed(0));
const method = this._inner.methods.liquidate(
borrower,
repayCToken,
seizeCToken,
hexAmount
);
const gasLimit = this._estimateGas(repayCToken, seizeCToken, false, false);
return this.txFor(method, gasLimit, gasPrice);
}

_combineTokens(repayList, seizeList) {
let cTokens = [];
for (let i = 0; i < repayList.length; i++)
cTokens.push(repayList[i], seizeList[i]);
return cTokens;
}

_estimateGas(
repayCToken,
seizeCToken,
postPrices = false,
solveAmount = true
) {
let gas = Big(GAS_CUSHION);

// NOTE: we assume everything is lowercase when comparing addresses
if (repayCToken === CETH) gas = gas.plus(GAS_ETH2TOKEN);
else if (seizeCToken === CETH) gas = gas.plus(GAS_TOKEN2ETH);
// TODO The following conditional should really have an `or` clause to account
// for cases where Uniswap has sufficient liquidity to go straight from repay
// to seize without using Eth as an intermediate, but that's difficult to compute
else if (repayCToken === seizeCToken) gas = gas.plus(GAS_TOKEN2TOKEN);
else gas = gas.plus(GAS_TOKEN2TOKEN2ETH);

if (V2S.includes(repayCToken) || V2S.includes(seizeCToken))
gas = gas.plus(GAS_V2_PENALTY);
if (postPrices) gas = gas.plus(GAS_ORACLE);
if (solveAmount) gas = gas.plus(GAS_COMPUTE_AMOUNT);

return gas;
}
}

const addresses = {
mainnet: "0x9dB0987bAAC8EAA684Ff54F836a2368109f1761C"
};

const abi = require("../abis/goldenage/cafechi.json");
for (let net in addresses) {
exports[net] = new CafeChi(addresses[net], abi);
}
Loading

0 comments on commit 0d9aea9

Please sign in to comment.