Skip to content
This repository was archived by the owner on Jan 18, 2023. It is now read-only.
42 changes: 42 additions & 0 deletions contracts/core/lib/auction-price-libraries/IAuctionPriceCurve.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
/*
Copyright 2018 Set Labs 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;

/**
* @title IAuctionPriceCurve
* @author Set Protocol
*
* The IAuctionPriceCurve interface provides a structured way to interact with any AuctionLibrary
*/

interface IAuctionPriceCurve {

/*
* Calculate the current priceRatio for an auction given defined price and time parameters
*
* @param _auctionStartTime Time of auction start
* @param _auctionStartPrice The price to start the auction at
* @param _curveCoefficient The slope (or convexity) of the price curve
*/
function getCurrentPrice(
uint256 _auctionStartTime,
uint256 _auctionStartPrice,
uint256 _curveCoefficient
)
external
view;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
/*
Copyright 2018 Set Labs 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;

import { SafeMath } from "zeppelin-solidity/contracts/math/SafeMath.sol";

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For the future. Inconsistent spacing. Two lines here


/**
* @title LinearAuctionPriceCurve
* @author Set Protocol
*
* Contract used in rebalancing auctions to calculate price based off of a linear curve
*/

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

None here


contract LinearAuctionPriceCurve {
using SafeMath for uint256;

/*
* Calculate the current priceRatio for an auction given defined price and time parameters
*
* @param _auctionStartTime Time of auction start
* @param _auctionStartPrice The price to start the auction at
* @param _curveCoefficient The slope (or convexity) of the price curve
*/
function getCurrentPrice(
uint256 _auctionStartTime,
uint256 _auctionStartPrice,
uint256 _curveCoefficient
)
external
view
returns (uint256)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

view modifier?

{
// Calculate how much time has elapsed since start of auction and divide by
// timeIncrement of 30 seconds, so price changes every 30 seconds
uint256 elapsed = block.timestamp.sub(_auctionStartTime).div(30);

return _curveCoefficient.mul(elapsed).add(_auctionStartPrice);
}
}
65 changes: 65 additions & 0 deletions contracts/mocks/core/lib/ConstantAuctionPriceCurve.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
/*
Copyright 2018 Set Labs 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;


/**
* @title ConstantAuctionPriceCurve
* @author Set Protocol
*
* Contract used in rebalancing auction testing to return consistent price
*
*/

contract ConstantAuctionPriceCurve {

uint256 public constantPrice;

/*
* Declare price you want this library to return when queried
*
* @param _price The price you want this library to always return
*/
constructor(
uint256 _price
)
public
{
// Set price to be returned by library
constantPrice = _price;
}


/*
* Return constant price amount
*
* @param -- Unused auction start time to conform to IAuctionPriceCurve --
* @param -- Unused auction start price to conform to IAuctionPriceCurve --
* @param -- Unused curve coefficient to conform to IAuctionPriceCurve --
*/
function getCurrentPrice(
uint256,
uint256,
uint256
)
external
view
returns (uint256)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

view

{
return constantPrice;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
require('module-alias/register');

import * as chai from 'chai';
import * as setProtocolUtils from 'set-protocol-utils';
import { Address } from 'set-protocol-utils';
import { BigNumber } from 'bignumber.js';

import { LinearAuctionPriceCurveContract } from '@utils/contracts';
import { Blockchain } from '@utils/blockchain';
import { ERC20Wrapper } from '@utils/erc20Wrapper';
import { CoreWrapper } from '@utils/coreWrapper';
import { RebalancingTokenWrapper } from '@utils/RebalancingTokenWrapper';
import { BigNumberSetup } from '@utils/bigNumberSetup';
import ChaiSetup from '@utils/chaiSetup';
import { DEFAULT_GAS } from '@utils/constants';

BigNumberSetup.configure();
ChaiSetup.configure();
const { SetProtocolUtils: SetUtils } = setProtocolUtils;
const { expect } = chai;


contract('LinearAuctionPriceCurve', accounts => {
const [
ownerAccount,
] = accounts;

let auctionCurve: LinearAuctionPriceCurveContract;

const coreWrapper = new CoreWrapper(ownerAccount, ownerAccount);
const erc20Wrapper = new ERC20Wrapper(ownerAccount);
const blockchain = new Blockchain(web3);
const rebalancingTokenWrapper = new RebalancingTokenWrapper(
ownerAccount,
coreWrapper,
erc20Wrapper,
blockchain
);

beforeEach(async () => {
await blockchain.saveSnapshotAsync();
auctionCurve = await coreWrapper.deployLinearAuctionPriceCurveAsync();
});

afterEach(async () => {
await blockchain.revertAsync();
});

describe('#getCurrentPrice', async () => {
let subjectAuctionStartTime: BigNumber;
let subjectAuctionStartPrice: BigNumber;
let subjectCurveCoefficient: BigNumber;
let subjectCaller: Address;

beforeEach(async () => {
subjectAuctionStartPrice = new BigNumber(500);
subjectCurveCoefficient = new BigNumber (5);
subjectAuctionStartTime = SetUtils.generateTimestamp(0);
subjectCaller = ownerAccount;
});

async function subject(): Promise<BigNumber> {
return auctionCurve.getCurrentPrice.callAsync(
subjectAuctionStartTime,
subjectAuctionStartPrice,
subjectCurveCoefficient,
{ from: subjectCaller, gas: DEFAULT_GAS}
);
}

it('starts with the correct price', async () => {
const returnedPrice = await subject();

expect(returnedPrice).to.be.bignumber.equal(subjectAuctionStartPrice);
});

it('returns the correct price after one hour', async () => {
const timeJump = new BigNumber(3600);
await blockchain.increaseTimeAsync(timeJump);

const returnedPrice = await subject();

const expectedPrice = rebalancingTokenWrapper.getExpectedLinearAuctionPrice(
timeJump,
subjectCurveCoefficient,
subjectAuctionStartPrice
);
expect(returnedPrice).to.be.bignumber.equal(expectedPrice);
});
});
});
13 changes: 12 additions & 1 deletion utils/RebalancingTokenWrapper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,8 @@ import {
ONE_DAY_IN_SECONDS,
DEFAULT_UNIT_SHARES,
DEFAULT_REBALANCING_NATURAL_UNIT,
UNLIMITED_ALLOWANCE_IN_BASE_UNITS
UNLIMITED_ALLOWANCE_IN_BASE_UNITS,
AUCTION_TIME_INCREMENT
} from './constants';

import { CoreWrapper } from './coreWrapper';
Expand Down Expand Up @@ -264,4 +265,14 @@ export class RebalancingTokenWrapper {
const unitShares = issueAmount.div(naturalUnitsOutstanding).round(0, 3);
return {unitShares, issueAmount};
}

public getExpectedLinearAuctionPrice(
elapsedTime: BigNumber,
curveCoefficient: BigNumber,
auctionStartPrice: BigNumber
): BigNumber {
const elaspedTimeFromStart = elapsedTime.div(AUCTION_TIME_INCREMENT).round(0, 3);
const expectedPrice = curveCoefficient.mul(elaspedTimeFromStart).add(auctionStartPrice);
return expectedPrice;
}
}
1 change: 1 addition & 0 deletions utils/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ export const STANDARD_NATURAL_UNIT = ether(1);
export const STANDARD_QUANTITY_ISSUED: BigNumber = ether(10);
export const UNLIMITED_ALLOWANCE_IN_BASE_UNITS = new BigNumber(2).pow(256).minus(1);
export const ZERO: BigNumber = new BigNumber(0);
export const AUCTION_TIME_INCREMENT = new BigNumber(30); // Unix seconds

export const PRIVATE_KEYS = [
'767df558efc63b6ba9a9257e68509c38f5c48d5938a41ab191a9a073ebff7c4f',
Expand Down
2 changes: 2 additions & 0 deletions utils/contracts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import { DetailedERC20Contract } from '../types/generated/detailed_erc20';
import { ERC20WrapperMockContract } from '../types/generated/erc20_wrapper_mock';
import { InvalidReturnTokenMockContract } from '../types/generated/invalid_return_token_mock';
import { KyberNetworkWrapperContract } from '../types/generated/kyber_network_wrapper';
import { LinearAuctionPriceCurveContract } from '../types/generated/linear_auction_price_curve';
import { NoDecimalTokenMockContract } from '../types/generated/no_decimal_token_mock';
import { NoXferReturnTokenMockContract } from '../types/generated/no_xfer_return_token_mock';
import { OrderLibraryMockContract } from '../types/generated/order_library_mock';
Expand Down Expand Up @@ -37,6 +38,7 @@ export {
ERC20WrapperMockContract,
InvalidReturnTokenMockContract,
KyberNetworkWrapperContract,
LinearAuctionPriceCurveContract,
NoDecimalTokenMockContract,
NoXferReturnTokenMockContract,
OrderLibraryMockContract,
Expand Down
15 changes: 15 additions & 0 deletions utils/coreWrapper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import {
AuthorizableContract,
CoreContract,
CoreMockContract,
LinearAuctionPriceCurveContract,
OrderLibraryMockContract,
SetTokenContract,
RebalancingSetTokenContract,
Expand All @@ -22,6 +23,7 @@ const Authorizable = artifacts.require('Authorizable');
const Core = artifacts.require('Core');
const CoreMock = artifacts.require('CoreMock');
const ERC20Wrapper = artifacts.require('ERC20Wrapper');
const LinearAuctionPriceCurve = artifacts.require('LinearAuctionPriceCurve');
const OrderLibrary = artifacts.require('OrderLibrary');
const OrderLibraryMock = artifacts.require('OrderLibraryMock');
const RebalancingSetToken = artifacts.require('RebalancingSetToken');
Expand Down Expand Up @@ -149,6 +151,19 @@ export class CoreWrapper {
);
}

public async deployLinearAuctionPriceCurveAsync(
from: Address = this._tokenOwnerAddress
): Promise<LinearAuctionPriceCurveContract> {
const truffleLinearAuctionPriceCurve = await LinearAuctionPriceCurve.new(
{ from },
);

return new LinearAuctionPriceCurveContract(
web3.eth.contract(truffleLinearAuctionPriceCurve.abi).at(truffleLinearAuctionPriceCurve.address),
{ from, gas: DEFAULT_GAS },
);
}

public async deploySetTokenAsync(
factory: Address,
componentAddresses: Address[],
Expand Down