forked from justlend/justlend-protocol
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit 1fadc93
Showing
85 changed files
with
16,613 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
name: Tests | ||
|
||
on: | ||
push: | ||
branches: | ||
- main | ||
pull_request: | ||
|
||
jobs: | ||
unit-tests: | ||
name: Unit Tests | ||
runs-on: ubuntu-latest | ||
|
||
steps: | ||
- uses: actions/checkout@v1 | ||
- uses: actions/setup-node@v1 | ||
with: | ||
node-version: 12.x | ||
|
||
- id: yarn-cache | ||
run: echo "::set-output name=dir::$(yarn cache dir)" | ||
|
||
- uses: actions/cache@v1 | ||
with: | ||
path: ${{ steps.yarn-cache.outputs.dir }} | ||
key: yarn-${{ hashFiles('**/yarn.lock') }} | ||
restore-keys: | | ||
yarn- | ||
- name: Install dependencies | ||
run: npm i | ||
|
||
|
||
#- name: Run unit tests | ||
# run: yarn test |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
.env | ||
node_modules | ||
build | ||
package-lock.json | ||
.DS_store |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,144 @@ | ||
JustLend Protocol | ||
================= | ||
|
||
JustLend Protocol is an TRON smart contract protocol for supplying or borrowing assets. Through the jToken contracts, accounts on the TRON blockchain <b>supply</b> capital (TRX or TRC20 tokens) to receive jTokens or <b>borrow</b> assets from the protocol (holding other assets as collateral). The JustLend jToken contracts track these balances and algorithmically set interest rates for borrowers. | ||
|
||
Before getting started with this repo, please read: | ||
|
||
* The [Justlend Whitepaper](https://www.justlend.link/docs/justlend_whitepaper_en.pdf) | ||
* The [Justlend Terms Of Use](https://www.justlend.link/docs/JustLend_Terms_of_Use_en.pdf) | ||
|
||
For questions about interacting with JustLend, please visit [our Telegram Group](https://t.me/officialjustlend). | ||
|
||
|
||
Contracts | ||
========= | ||
|
||
We detail a few of the core contracts in the Justlend protocol. | ||
|
||
<dl> | ||
<dt>CToken, CErc20 and CEther</dt> | ||
<dd>The Justlend jTokens which are self-contained borrowing and lending contracts, are deployed from the code of CToken and CEther contracts. CToken contains the core logic and CErc20 and CEther add public interfaces for TRC20 tokens and TRX, respectively. Each jToken is assigned an interest rate and risk model (see InterestRateModel and Comptroller parts), and allows accounts to <b>mint</b> (supply capital), <b>redeem</b> (withdraw capital), <b>borrow</b> and <b>repay a borrow</b>. Each jToken is an TRC20 compliant token where balances represent ownership of the market.</dd> | ||
</dl> | ||
|
||
<dl> | ||
<dt>Comptroller</dt> | ||
<dd>The risk model contract, which validates permissible user actions and disallows actions if they do not fit certain risk parameters. For instance, the Comptroller enforces that each borrowing user must maintain a sufficient collateral balance across all cTokens.</dd> | ||
</dl> | ||
|
||
<dl> | ||
<dt>GovernorAlpha</dt> | ||
<dd>The administrator of the Justlend timelock contract. Holders of JST token may create and vote on proposals which will be queued into the Justlend timelock and then have effects on Justlend jToken and Comptroller contracts. This contract may be replaced in the future with a beta version.</dd> | ||
</dl> | ||
|
||
<dl> | ||
<dt>InterestRateModel</dt> | ||
<dd>Contracts which define interest rate models. These models algorithmically determine interest rates based on the current utilization of a given market (that is, how much of the supplied assets are liquid versus borrowed).</dd> | ||
</dl> | ||
|
||
<dl> | ||
<dt>ErrorReporter</dt> | ||
<dd>Library for tracking error codes and failure conditions.</dd> | ||
</dl> | ||
|
||
<dl> | ||
<dt>Exponential</dt> | ||
<dd>Library for handling fixed-point decimal numbers.</dd> | ||
</dl> | ||
|
||
|
||
<dl> | ||
<dt>WhitePaperInterestRateModel</dt> | ||
<dd>Initial interest rate model, as defined in the Whitepaper. This contract accepts a base rate and slope parameter in its constructor.</dd> | ||
</dl> | ||
|
||
|
||
<dl> | ||
<dt>Careful Math</dt> | ||
<dd>Library for safe math operations.</dd> | ||
</dl> | ||
|
||
<dl> | ||
<dt>SafeToken</dt> | ||
<dd>Library for safely handling Trc20 interaction.</dd> | ||
</dl> | ||
|
||
Deployment | ||
---------- | ||
TronBox is being used in this project. Before getting started with the deployment script, please read: | ||
|
||
* [Tronbox Tutorial](https://developers.tron.network/v3.7/docs/tron-box-user-guide) | ||
|
||
|
||
## Compile and Deployment | ||
|
||
To get started, first create and initialize a [NodeJS 8.0+ environment](https://github.com/nodejs/node). Next, clone the repo and install the developer dependencies: | ||
|
||
### Setup | ||
``` | ||
npm i | ||
``` | ||
|
||
### OS requirement | ||
* Linux | ||
* Mac OS X | ||
|
||
### Compile The Contract | ||
|
||
Run this by using tronbox embedded solc: | ||
```shell | ||
tronbox compile | ||
``` | ||
|
||
Or you may want to use external compilers. You can get the compiler from [here](https://github.com/tronprotocol/solidity/releases/tag/tv_0.5.12) | ||
|
||
And rename the compiler executable file to `solc512`, then compile the contracts with these commands. | ||
|
||
```shell | ||
./solc512 --allow-paths $YOUR_PATH/justlend-protocol/, --bin --abi --optimize $YOUR_PATH/justlend-protocol/Unitroller.sol | ||
./solc512 --allow-paths $YOUR_PATH/justlend-protocol/, --bin --abi --optimize $YOUR_PATH/justlend-protocol/Comptroller.sol | ||
./solc512 --allow-paths $YOUR_PATH/justlend-protocol/, --bin --abi --optimize $YOUR_PATH/justlend-protocol/Governance/WJST.sol | ||
./solc512 --allow-paths $YOUR_PATH/justlend-protocol/, --bin --abi --optimize $YOUR_PATH/justlend-protocol/Governance/GovernorBravoDelegator.sol | ||
./solc512 --allow-paths $YOUR_PATH/justlend-protocol/, --bin --abi --optimize $YOUR_PATH/justlend-protocol/Timelock.sol | ||
./solc512 --allow-paths $YOUR_PATH/justlend-protocol/, --bin --abi --optimize $YOUR_PATH/justlend-protocol/JumpRateModelV2.sol | ||
./solc512 --allow-paths $YOUR_PATH/justlend-protocol/, --bin --abi --optimize $YOUR_PATH/justlend-protocol/WhitePaperInterestRateModel.sol | ||
./solc512 --allow-paths $YOUR_PATH/justlend-protocol/, --bin --abi --optimize $YOUR_PATH/justlend-protocol/CEther.sol | ||
./solc512 --allow-paths $YOUR_PATH/justlend-protocol/, --bin --abi --optimize $YOUR_PATH/justlend-protocol/CErc20Delegate.sol | ||
./solc512 --allow-paths $YOUR_PATH/justlend-protocol/, --bin --abi --optimize $YOUR_PATH/justlend-protocol/CErc20Delegator.sol | ||
./solc512 --allow-paths $YOUR_PATH/justlend-protocol/, --bin --abi --optimize $YOUR_PATH/justlend-protocol/PriceOracle/PriceOracle.sol | ||
./solc512 --allow-paths $YOUR_PATH/justlend-protocol/, --bin --abi --optimize $YOUR_PATH/justlend-protocol/PriceOracleProxy.sol | ||
./solc512 --allow-paths $YOUR_PATH/justlend-protocol/, --bin --abi --optimize $YOUR_PATH/justlend-protocol/PriceOracle/PriceOracle.sol | ||
./solc512 --allow-paths $YOUR_PATH/justlend-protocol/, --bin --abi --optimize $YOUR_PATH/justlend-protocol/PriceOracleProxy.sol | ||
./solc512 --allow-paths $YOUR_PATH/justlend-protocol/, --bin --abi --optimize $YOUR_PATH/justlend-protocol/Lens/CompoundLens.sol | ||
``` | ||
|
||
### Deploy on Nile TestNet | ||
Before use, `sample-env` should be renamed to `.env` with the added network config: | ||
``` | ||
PRIVATE_KEY_NILE=YOUR_PRIVATE_KEY | ||
RESERVER_ADMIN=YOUR_RESERVE_ADMIN_ADMIN_ADDRESS | ||
ADMIN=YOUR_ADMIN_ADDRESS | ||
``` | ||
|
||
Assuming all contracts haven't been deployed, the user must deploy the script one by one individually by replacing `xx` with the correct number of the file and then record the contract addresses and data to `../data/test-xxx.json`. Please feel free to modify the `migrations` and contract data. | ||
|
||
``` | ||
tronbox migrate --network nile -f xx --to xx | ||
``` | ||
|
||
For example, if you want to run `3_deploy_comptroller.js`, the command will be `tronbox migrate --network nile -f 3 --to 3`. | ||
|
||
Due to the limitation of Tronbox, `Governor.setTimelock()` is unable to be invoked among the migration script. Therefore, the related script is inside `script/2_setTimelock.js`. Please run it for setting up the timelock address from Governor. | ||
|
||
## Contract Callers | ||
|
||
The sample of contract invokers is inside the `script` folder. | ||
|
||
Discussion | ||
---------- | ||
|
||
For any concerns with the protocol, open an issue or visit us on [Telegram](https://t.me/officialjustlend) to discuss. | ||
|
||
For security concerns, please email [[email protected]](mailto:[email protected]). | ||
|
||
_© Copyright 2022 JustLend DAO |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,137 @@ | ||
pragma solidity ^0.5.12; | ||
|
||
import "./SafeMath.sol"; | ||
|
||
/** | ||
* @title Logic for Compound's JumpRateModel Contract V2. | ||
* @author Compound (modified by Dharma Labs, refactored by Arr00) | ||
* @notice Version 2 modifies Version 1 by enabling updateable parameters. | ||
*/ | ||
contract BaseJumpRateModelV2 { | ||
using SafeMath for uint; | ||
|
||
event NewInterestParams(uint baseRatePerBlock, uint multiplierPerBlock, uint jumpMultiplierPerBlock, uint kink); | ||
|
||
/** | ||
* @notice The address of the owner, i.e. the Timelock contract, which can update parameters directly | ||
*/ | ||
address public owner; | ||
|
||
/** | ||
* @notice The approximate number of blocks per year that is assumed by the interest rate model | ||
*/ | ||
uint public constant blocksPerYear = 10_512_000; | ||
|
||
/** | ||
* @notice The multiplier of utilization rate that gives the slope of the interest rate | ||
*/ | ||
uint public multiplierPerBlock; | ||
|
||
/** | ||
* @notice The base interest rate which is the y-intercept when utilization rate is 0 | ||
*/ | ||
uint public baseRatePerBlock; | ||
|
||
/** | ||
* @notice The multiplierPerBlock after hitting a specified utilization point | ||
*/ | ||
uint public jumpMultiplierPerBlock; | ||
|
||
/** | ||
* @notice The utilization point at which the jump multiplier is applied | ||
*/ | ||
uint public kink; | ||
|
||
/** | ||
* @notice Construct an interest rate model | ||
* @param baseRatePerYear The approximate target base APR, as a mantissa (scaled by 1e18) | ||
* @param multiplierPerYear The rate of increase in interest rate wrt utilization (scaled by 1e18) | ||
* @param jumpMultiplierPerYear The multiplierPerBlock after hitting a specified utilization point | ||
* @param kink_ The utilization point at which the jump multiplier is applied | ||
* @param owner_ The address of the owner, i.e. the Timelock contract (which has the ability to update parameters directly) | ||
*/ | ||
constructor(uint baseRatePerYear, uint multiplierPerYear, uint jumpMultiplierPerYear, uint kink_, address owner_) internal { | ||
owner = owner_; | ||
|
||
updateJumpRateModelInternal(baseRatePerYear, multiplierPerYear, jumpMultiplierPerYear, kink_); | ||
} | ||
|
||
/** | ||
* @notice Update the parameters of the interest rate model (only callable by owner, i.e. Timelock) | ||
* @param baseRatePerYear The approximate target base APR, as a mantissa (scaled by 1e18) | ||
* @param multiplierPerYear The rate of increase in interest rate wrt utilization (scaled by 1e18) | ||
* @param jumpMultiplierPerYear The multiplierPerBlock after hitting a specified utilization point | ||
* @param kink_ The utilization point at which the jump multiplier is applied | ||
*/ | ||
function updateJumpRateModel(uint baseRatePerYear, uint multiplierPerYear, uint jumpMultiplierPerYear, uint kink_) external { | ||
require(msg.sender == owner, "only the owner may call this function."); | ||
|
||
updateJumpRateModelInternal(baseRatePerYear, multiplierPerYear, jumpMultiplierPerYear, kink_); | ||
} | ||
|
||
/** | ||
* @notice Calculates the utilization rate of the market: `borrows / (cash + borrows - reserves)` | ||
* @param cash The amount of cash in the market | ||
* @param borrows The amount of borrows in the market | ||
* @param reserves The amount of reserves in the market (currently unused) | ||
* @return The utilization rate as a mantissa between [0, 1e18] | ||
*/ | ||
function utilizationRate(uint cash, uint borrows, uint reserves) public pure returns (uint) { | ||
// Utilization rate is 0 when there are no borrows | ||
if (borrows == 0) { | ||
return 0; | ||
} | ||
|
||
return borrows.mul(1e18).div(cash.add(borrows).sub(reserves)); | ||
} | ||
|
||
/** | ||
* @notice Calculates the current borrow rate per block, with the error code expected by the market | ||
* @param cash The amount of cash in the market | ||
* @param borrows The amount of borrows in the market | ||
* @param reserves The amount of reserves in the market | ||
* @return The borrow rate percentage per block as a mantissa (scaled by 1e18) | ||
*/ | ||
function getBorrowRateInternal(uint cash, uint borrows, uint reserves) internal view returns (uint) { | ||
uint util = utilizationRate(cash, borrows, reserves); | ||
|
||
if (util <= kink) { | ||
return util.mul(multiplierPerBlock).div(1e18).add(baseRatePerBlock); | ||
} else { | ||
uint normalRate = kink.mul(multiplierPerBlock).div(1e18).add(baseRatePerBlock); | ||
uint excessUtil = util.sub(kink); | ||
return excessUtil.mul(jumpMultiplierPerBlock).div(1e18).add(normalRate); | ||
} | ||
} | ||
|
||
/** | ||
* @notice Calculates the current supply rate per block | ||
* @param cash The amount of cash in the market | ||
* @param borrows The amount of borrows in the market | ||
* @param reserves The amount of reserves in the market | ||
* @param reserveFactorMantissa The current reserve factor for the market | ||
* @return The supply rate percentage per block as a mantissa (scaled by 1e18) | ||
*/ | ||
function getSupplyRate(uint cash, uint borrows, uint reserves, uint reserveFactorMantissa) public view returns (uint) { | ||
uint oneMinusReserveFactor = uint(1e18).sub(reserveFactorMantissa); | ||
uint borrowRate = getBorrowRateInternal(cash, borrows, reserves); | ||
uint rateToPool = borrowRate.mul(oneMinusReserveFactor).div(1e18); | ||
return utilizationRate(cash, borrows, reserves).mul(rateToPool).div(1e18); | ||
} | ||
|
||
/** | ||
* @notice Internal function to update the parameters of the interest rate model | ||
* @param baseRatePerYear The approximate target base APR, as a mantissa (scaled by 1e18) | ||
* @param multiplierPerYear The rate of increase in interest rate wrt utilization (scaled by 1e18) | ||
* @param jumpMultiplierPerYear The multiplierPerBlock after hitting a specified utilization point | ||
* @param kink_ The utilization point at which the jump multiplier is applied | ||
*/ | ||
function updateJumpRateModelInternal(uint baseRatePerYear, uint multiplierPerYear, uint jumpMultiplierPerYear, uint kink_) internal { | ||
baseRatePerBlock = baseRatePerYear.div(blocksPerYear); | ||
multiplierPerBlock = (multiplierPerYear.mul(1e18)).div(blocksPerYear.mul(kink_)); | ||
jumpMultiplierPerBlock = jumpMultiplierPerYear.div(blocksPerYear); | ||
kink = kink_; | ||
|
||
emit NewInterestParams(baseRatePerBlock, multiplierPerBlock, jumpMultiplierPerBlock, kink); | ||
} | ||
} |
Oops, something went wrong.