Skip to content

Commit

Permalink
Min duration (#421)
Browse files Browse the repository at this point in the history
* Implement minDuration

* Test fix

* Test fixes

* minDuration tests

* Remove .only
  • Loading branch information
HardlyDifficult committed May 22, 2020
1 parent e7a4fb3 commit 620b33b
Show file tree
Hide file tree
Showing 9 changed files with 452 additions and 130 deletions.
46 changes: 36 additions & 10 deletions contracts/DecentralizedAutonomousTrust.sol
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ contract DecentralizedAutonomousTrust
uint _revenueCommitmentBasisPoints,
uint _feeBasisPoints,
uint _minInvestment,
uint _openUntilAtLeast
uint _minDuration
);

/**
Expand Down Expand Up @@ -166,10 +166,8 @@ contract DecentralizedAutonomousTrust
/// automatically funneled and held into the buyback_reserve expressed in basis points.
uint public investmentReserveBasisPoints;

/// @notice The earliest date/time (in seconds) that the DAT may enter the `CLOSE` state, ensuring
/// that if the DAT reaches the `RUN` state it will remain running for at least this period of time.
/// @dev This value may be increased anytime by the control account
uint public openUntilAtLeast;
/// @dev unused slot which remains to ensure compatible upgrades
uint private __openUntilAtLeast;

/// @notice The minimum amount of `currency` investment accepted.
uint public minInvestment;
Expand Down Expand Up @@ -200,6 +198,15 @@ contract DecentralizedAutonomousTrust
/// @notice The address to send tokens on pay. If zero, the caller may choose.
address public overridePayTo;

/// @notice The minimum time before which the c-org contract cannot be closed once the contract has
/// reached the `run` state.
/// @dev When updated, the new value of `minimum_duration` cannot be earlier than the previous value.
uint public minDuration;

/// @notice Initialized at `0` and updated when the contract switches from `init` state to `run` state
/// with the current timestamp.
uint public runStartedOn;

modifier authorizeTransfer(
address _from,
address _to,
Expand Down Expand Up @@ -390,6 +397,7 @@ contract DecentralizedAutonomousTrust
{
emit StateChange(state, STATE_RUN);
state = STATE_RUN;
runStartedOn = block.timestamp;
}
else
{
Expand Down Expand Up @@ -446,6 +454,22 @@ contract DecentralizedAutonomousTrust
)
);
}

/// @notice A temporary function to set `runStartedOn`, to be used by contracts which were
/// already deployed before this feature was introduced.
/// @dev This function will be removed once known users have called the function.
function initializeRunStartedOn(
uint _runStartedOn
) external
{
require(msg.sender == control, "CONTROL_ONLY");
require(state == STATE_RUN, "ONLY_CALL_IN_RUN");
require(runStartedOn == 0, "ONLY_CALL_IF_NOT_AUTO_SET");
require(_runStartedOn <= block.timestamp, "DATE_MUST_BE_IN_PAST");

runStartedOn = _runStartedOn;
}

function getChainId(
) private pure
returns (uint id)
Expand All @@ -467,7 +491,7 @@ contract DecentralizedAutonomousTrust
bool _autoBurn,
uint _revenueCommitmentBasisPoints,
uint _minInvestment,
uint _openUntilAtLeast
uint _minDuration
) public
{
// This require(also confirms that initialize has been called.
Expand Down Expand Up @@ -496,8 +520,8 @@ contract DecentralizedAutonomousTrust
require(_minInvestment > 0, "INVALID_MIN_INVESTMENT");
minInvestment = _minInvestment;

require(_openUntilAtLeast >= openUntilAtLeast, "OPEN_UNTIL_MAY_NOT_BE_REDUCED");
openUntilAtLeast = _openUntilAtLeast;
require(_minDuration >= minDuration, "MIN_DURATION_MAY_NOT_BE_REDUCED");
minDuration = _minDuration;

if(beneficiary != _beneficiary)
{
Expand All @@ -522,7 +546,7 @@ contract DecentralizedAutonomousTrust
_revenueCommitmentBasisPoints,
_feeBasisPoints,
_minInvestment,
_openUntilAtLeast
_minDuration
);
}

Expand Down Expand Up @@ -704,6 +728,8 @@ contract DecentralizedAutonomousTrust
{
emit StateChange(state, STATE_RUN);
state = STATE_RUN;
runStartedOn = block.timestamp;

// Math worst case:
// MAX_BEFORE_SQUARE * MAX_BEFORE_SQUARE * MAX_BEFORE_SQUARE/2
// / MAX_BEFORE_SQUARE * 2
Expand Down Expand Up @@ -1022,7 +1048,7 @@ contract DecentralizedAutonomousTrust
else if(state == STATE_RUN)
{
// Collect the exitFee and close the c-org.
require(openUntilAtLeast <= block.timestamp, "TOO_EARLY");
require(minDuration + runStartedOn <= block.timestamp, "TOO_EARLY");

exitFee = estimateExitFee(msg.value);

Expand Down
190 changes: 111 additions & 79 deletions helpers/deployDat.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
const { constants, helpers } = require("hardlydifficult-eth");
const { constants } = require("hardlydifficult-eth");

// Original deployment used 2.0.8 for the DAT and 2.2.0 for the whitelist
const cOrgAbi208 = require("../versions/2.0.8/abi.json");
Expand Down Expand Up @@ -39,61 +39,84 @@ module.exports = async function deployDat(
},
options
);
// console.log(`Deploy DAT: ${JSON.stringify(callOptions, null, 2)}`);

if (useProxy) {
// ProxyAdmin
contracts.proxyAdmin = await proxyAdminArtifact.new({
from: callOptions.control,
});
console.log(`ProxyAdmin deployed ${contracts.proxyAdmin.address}`);
}

// DAT
const datContract = await datArtifact.new({
from: callOptions.control,
});
console.log(`DAT template deployed ${datContract.address}`);

let datProxy;
if (useProxy) {
const originalDatContract = new web3.eth.Contract(cOrgAbi208.dat);
const originalDat = await originalDatContract
.deploy({
data: cOrgBytecode208.dat,
})
.send({
from: callOptions.control,
gas: constants.MAX_GAS,
});
if (upgrade) {
const originalDatContract = new web3.eth.Contract(cOrgAbi208.dat);
const originalDat = await originalDatContract
.deploy({
data: cOrgBytecode208.dat,
})
.send({
from: callOptions.control,
gas: constants.MAX_GAS,
});

datProxy = await proxyArtifact.new(
originalDat._address, // logic
contracts.proxyAdmin.address, // admin
[], // data
{
from: callOptions.control,
}
);
console.log(`DAT proxy deployed ${datProxy.address}`);
datProxy = await proxyArtifact.new(
originalDat._address, // logic
contracts.proxyAdmin.address, // admin
[], // data
{
from: callOptions.control,
}
);

contracts.dat = new web3.eth.Contract(cOrgAbi208.dat, datProxy.address);

await contracts.dat.methods
.initialize(
callOptions.initReserve,
callOptions.currency,
callOptions.initGoal,
callOptions.buySlopeNum,
callOptions.buySlopeDen,
callOptions.investmentReserveBasisPoints,
callOptions.name,
callOptions.symbol
)
.send({ from: callOptions.control, gas: constants.MAX_GAS });
await contracts.dat.methods
.initializePermit()
.send({ from: callOptions.control, gas: constants.MAX_GAS });
} else {
datProxy = await proxyArtifact.new(
datContract.address, // logic
contracts.proxyAdmin.address, // admin
[], // data
{
from: callOptions.control,
}
);

contracts.dat = new web3.eth.Contract(cOrgAbi208.dat, datProxy.address);
contracts.dat = await datArtifact.at(datProxy.address);

await contracts.dat.methods
.initialize(
await contracts.dat.initialize(
callOptions.initReserve,
callOptions.currency,
callOptions.initGoal,
callOptions.buySlopeNum,
callOptions.buySlopeDen,
callOptions.investmentReserveBasisPoints,
callOptions.setupFee,
callOptions.setupFeeRecipient,
callOptions.name,
callOptions.symbol
)
.send({ from: callOptions.control, gas: constants.MAX_GAS });
await contracts.dat.methods
.initializePermit()
.send({ from: callOptions.control, gas: constants.MAX_GAS });
callOptions.symbol,
{ from: callOptions.control, gas: constants.MAX_GAS }
);
}
} else {
contracts.dat = datContract;

Expand Down Expand Up @@ -122,12 +145,6 @@ module.exports = async function deployDat(
}
);
contracts.dat = await datArtifact.at(datProxy.address);
} else {
contracts.dat = await helpers.truffleContract.at(
web3,
cOrgAbi208.dat,
datProxy.address
);
}
}

Expand All @@ -138,38 +155,59 @@ module.exports = async function deployDat(
const whitelistContract = await whitelistArtifact.new({
from: callOptions.control,
});
console.log(`Whitelist template deployed ${whitelistContract.address}`);

if (useProxy) {
const originalWhitelistContract = new web3.eth.Contract(
cOrgAbi220.whitelist
);
const originalWhitelist = await originalWhitelistContract
.deploy({
data: cOrgBytecode220.whitelist,
})
.send({
if (upgrade) {
const originalWhitelistContract = new web3.eth.Contract(
cOrgAbi220.whitelist
);
const originalWhitelist = await originalWhitelistContract
.deploy({
data: cOrgBytecode220.whitelist,
})
.send({
from: callOptions.control,
gas: constants.MAX_GAS,
});
whitelistProxy = await proxyArtifact.new(
originalWhitelist._address, // logic
contracts.proxyAdmin.address, // admin
[], // data
{
from: callOptions.control,
}
);

contracts.whitelist = new web3.eth.Contract(
cOrgAbi220.whitelist,
whitelistProxy.address
);

await contracts.whitelist.methods
.initialize(contracts.dat.address)
.send({
from: callOptions.control,
gas: constants.MAX_GAS,
});
} else {
whitelistProxy = await proxyArtifact.new(
whitelistContract.address, // logic
contracts.proxyAdmin.address, // admin
[], // data
{
from: callOptions.control,
}
);

contracts.whitelist = await whitelistArtifact.at(
whitelistProxy.address
);

await contracts.whitelist.initialize(contracts.dat.address, {
from: callOptions.control,
gas: constants.MAX_GAS,
});
whitelistProxy = await proxyArtifact.new(
originalWhitelist._address, // logic
contracts.proxyAdmin.address, // admin
[], // data
{
from: callOptions.control,
}
);
console.log(`Whitelist proxy deployed ${whitelistProxy.address}`);

contracts.whitelist = new web3.eth.Contract(
cOrgAbi220.whitelist,
whitelistProxy.address
);
await contracts.whitelist.methods.initialize(contracts.dat.address).send({
from: callOptions.control,
gas: constants.MAX_GAS,
});
}
} else {
contracts.whitelist = whitelistContract;

Expand All @@ -190,24 +228,19 @@ module.exports = async function deployDat(
contracts.whitelist = await whitelistArtifact.at(
whitelistProxy.address
);
} else {
contracts.whitelist = await helpers.truffleContract.at(
web3,
cOrgAbi220.whitelist,
whitelistProxy.address
);
}
}
callOptions.whitelistAddress = contracts.whitelist.address;
await contracts.whitelist.updateJurisdictionFlows(
[1, 4, 4],
[4, 1, 4],
[1, 1, 1],
{
from: callOptions.control,
}
promises.push(
contracts.whitelist.updateJurisdictionFlows(
[1, 4, 4],
[4, 1, 4],
[1, 1, 1],
{
from: callOptions.control,
}
)
);
// console.log(`Deployed whitelist: ${contracts.whitelist.address}`);

promises.push(
contracts.whitelist.approveNewUsers([callOptions.control], [4], {
Expand Down Expand Up @@ -257,7 +290,6 @@ module.exports = async function deployDat(
from: callOptions.control,
}
);
console.log(`Vesting contract deployed ${contract.address}`);

contracts.vesting.push(contract);

Expand Down

0 comments on commit 620b33b

Please sign in to comment.