This repository has been archived by the owner on Sep 27, 2022. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 53
[Under Audit] Add Bucket-Lender #357
Merged
Merged
Changes from 1 commit
Commits
Show all changes
22 commits
Select commit
Hold shift + click to select a range
052153c
add bucketlender
2bfab08
more changes
3a79068
add WETH9
399f4b4
test EthWrapper
121e039
more tests
7b9a5ac
prevent withdrawing from the critical bucket if it is also the curren…
aef6239
remove extra console.log statements
5691896
more changes
2654dae
add events
9dd6e38
make suggested changes
bbd8040
move function, add comment
ab6d83a
remove extra 'Ownable' (is included in 'HasNoEther')
b870ea3
revert change to withdraw()
3cae0fa
remove linting errors
6fa2ca5
change tests to not use round numbers
ba81917
add BucketLenderFactory
a434b6b
add tests, fix withdrawExcess
12b2c24
make changes
e8d165c
add back semicolons
e9e3116
merge
d5a0a82
move test files
07494ef
split into LoanOfferingParser
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
107 changes: 107 additions & 0 deletions
107
contracts/margin/external/BucketLender/BucketLenderFactory.sol
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,107 @@ | ||
/* | ||
|
||
Copyright 2018 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.4.24; | ||
pragma experimental "v0.5.0"; | ||
|
||
import { Ownable } from "zeppelin-solidity/contracts/ownership/Ownable.sol"; | ||
import { BucketLender } from "./BucketLender.sol"; | ||
|
||
|
||
/** | ||
* @title BucketLenderFactory | ||
* @author dYdX | ||
* | ||
* Contract that allows anyone to deploy a BucketLender contract by sending a transaction. | ||
*/ | ||
contract BucketLenderFactory { | ||
|
||
// ============ Events ============ | ||
|
||
event BucketLenderCreated( | ||
address indexed creator, | ||
address at, | ||
bytes32 positionId | ||
); | ||
|
||
// ============ State Variables ============ | ||
|
||
// Address of the Margin contract for the dYdX Margin Trading Protocol | ||
address public DYDX_MARGIN; | ||
|
||
// ============ Constructor ============ | ||
|
||
constructor( | ||
address margin | ||
) | ||
public | ||
{ | ||
DYDX_MARGIN = margin; | ||
} | ||
|
||
// ============ Public Functions ============ | ||
|
||
/** | ||
* Deploy a new BucketLender contract to the blockchain | ||
* | ||
* @param positionId Unique ID of the position | ||
* @param heldToken Address of the token held in the position as collateral | ||
* @param owedToken Address of the token being lent by the BucketLender | ||
* @param parameters Values corresponding to: | ||
* | ||
* [0] = number of seconds per bucket | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. nit: to be consistent with |
||
* [1] = interest rate | ||
* [2] = interest period | ||
* [3] = maximum loan duration | ||
* [4] = margin-call timelimit | ||
* [5] = numerator of minimum heldToken-per-owedToken | ||
* [6] = denominator of minimum heldToken-per-owedToken | ||
* | ||
* @param marginCallers Accounts that are permitted to margin-call positions (or cancel the margin call) | ||
* @return The address of the new BucketLender contract | ||
*/ | ||
function createBucketLender( | ||
bytes32 positionId, | ||
address heldToken, | ||
address owedToken, | ||
uint32[7] parameters, | ||
address[] marginCallers | ||
) | ||
external | ||
returns (address) | ||
{ | ||
address newBucketLender = new BucketLender( | ||
DYDX_MARGIN, | ||
positionId, | ||
heldToken, | ||
owedToken, | ||
parameters, | ||
marginCallers | ||
); | ||
|
||
Ownable(newBucketLender).transferOwnership(msg.sender); | ||
|
||
emit BucketLenderCreated( | ||
msg.sender, | ||
newBucketLender, | ||
positionId | ||
); | ||
|
||
return newBucketLender; | ||
} | ||
} |
116 changes: 116 additions & 0 deletions
116
test/margin/external/bucketlender/TestBucketLenderFactory.js
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,116 @@ | ||
const chai = require('chai'); | ||
const expect = chai.expect; | ||
chai.use(require('chai-bignumber')()); | ||
const BigNumber = require('bignumber.js'); | ||
|
||
const Margin = artifacts.require("Margin"); | ||
const HeldToken = artifacts.require("TokenA"); | ||
const OwedToken = artifacts.require("TokenB"); | ||
const BucketLender = artifacts.require("BucketLender"); | ||
const BucketLenderFactory = artifacts.require("BucketLenderFactory"); | ||
|
||
const { transact } = require('../../../helpers/ContractHelper'); | ||
const { ADDRESSES, BYTES32 } = require('../../../helpers/Constants'); | ||
|
||
contract('BucketLenderFactory', () => { | ||
|
||
// ============ Before/After ============ | ||
|
||
beforeEach('set up contracts', async () => { | ||
}); | ||
|
||
// ============ Constructor ============ | ||
|
||
describe('Constructor', () => { | ||
it('sets constants correctly', async () => { | ||
const marginAddress = ADDRESSES.TEST[0]; | ||
const factory = await BucketLenderFactory.new(marginAddress); | ||
const dydxMargin = await factory.DYDX_MARGIN.call(); | ||
expect(dydxMargin).to.be.eq(marginAddress); | ||
}); | ||
}); | ||
|
||
// ============ Functions ============ | ||
|
||
describe('createBucketLender', () => { | ||
it('succeeds', async () => { | ||
const positionId = BYTES32.TEST[0]; | ||
const bucketTime = new BigNumber(123); | ||
const interestRate = new BigNumber(456); | ||
const interestPeriod = new BigNumber(789); | ||
const maxDuration = new BigNumber(101112); | ||
const callTimelimit = new BigNumber(131415); | ||
const numerator = new BigNumber(161718); | ||
const denominator = new BigNumber(192021); | ||
const marginCaller = ADDRESSES.TEST[0]; | ||
const notMarginCaller = ADDRESSES.TEST[1]; | ||
|
||
const factory = await BucketLenderFactory.new(Margin.address); | ||
|
||
const newBucketLender = await transact( | ||
factory.createBucketLender, | ||
positionId, | ||
HeldToken.address, | ||
OwedToken.address, | ||
[ | ||
bucketTime, | ||
interestRate, | ||
interestPeriod, | ||
maxDuration, | ||
callTimelimit, | ||
numerator, | ||
denominator | ||
], | ||
[ | ||
marginCaller | ||
] | ||
); | ||
|
||
const bucketLender = await BucketLender.at(newBucketLender.result); | ||
|
||
const [ | ||
bl_margin, | ||
bl_positionId, | ||
bl_heldToken, | ||
bl_owedToken, | ||
bl_bucketTime, | ||
bl_interestRate, | ||
bl_interestPeriod, | ||
bl_maxDuration, | ||
bl_callTimelimit, | ||
bl_numerator, | ||
bl_denominator, | ||
bl_marginCallerOkay, | ||
bl_notMarginCallerNotOkay, | ||
] = await Promise.all([ | ||
bucketLender.DYDX_MARGIN.call(), | ||
bucketLender.POSITION_ID.call(), | ||
bucketLender.HELD_TOKEN.call(), | ||
bucketLender.OWED_TOKEN.call(), | ||
bucketLender.BUCKET_TIME.call(), | ||
bucketLender.INTEREST_RATE.call(), | ||
bucketLender.INTEREST_PERIOD.call(), | ||
bucketLender.MAX_DURATION.call(), | ||
bucketLender.CALL_TIMELIMIT.call(), | ||
bucketLender.MIN_HELD_TOKEN_NUMERATOR.call(), | ||
bucketLender.MIN_HELD_TOKEN_DENOMINATOR.call(), | ||
bucketLender.TRUSTED_MARGIN_CALLERS.call(marginCaller), | ||
bucketLender.TRUSTED_MARGIN_CALLERS.call(notMarginCaller), | ||
]); | ||
|
||
expect(bl_margin).to.be.eq(Margin.address); | ||
expect(bl_positionId).to.be.eq(positionId); | ||
expect(bl_heldToken).to.be.eq(HeldToken.address); | ||
expect(bl_owedToken).to.be.eq(OwedToken.address); | ||
expect(bl_bucketTime).to.be.bignumber.eq(bucketTime); | ||
expect(bl_interestRate).to.be.bignumber.eq(interestRate); | ||
expect(bl_interestPeriod).to.be.bignumber.eq(interestPeriod); | ||
expect(bl_maxDuration).to.be.bignumber.eq(maxDuration); | ||
expect(bl_callTimelimit).to.be.bignumber.eq(callTimelimit); | ||
expect(bl_numerator).to.be.bignumber.eq(numerator); | ||
expect(bl_denominator).to.be.bignumber.eq(denominator); | ||
expect(bl_marginCallerOkay).to.be.eq(true); | ||
expect(bl_notMarginCallerNotOkay).to.be.eq(false); | ||
}); | ||
}); | ||
}); |
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
you should index the
positionId
this will likely be a thing people search by