Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Min duration #421

Merged
merged 5 commits into from
May 22, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
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