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

Merge release 5 to master #8475

Merged
merged 8 commits into from
Aug 20, 2021
2 changes: 1 addition & 1 deletion .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ defaults: &defaults
contract-defaults: &contract-defaults
<<: *defaults
environment:
RELEASE_TAG: core-contracts.v4
RELEASE_TAG: core-contracts.v5

e2e-defaults: &e2e-defaults
<<: *defaults
Expand Down
2 changes: 1 addition & 1 deletion packages/protocol/contracts/governance/Validators.sol
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,7 @@ contract Validators is
* @return The storage, major, minor, and patch version of the contract.
*/
function getVersionNumber() external pure returns (uint256, uint256, uint256, uint256) {
return (1, 2, 0, 1);
return (1, 2, 0, 2);
}

/**
Expand Down
38 changes: 29 additions & 9 deletions packages/protocol/contracts/stability/GrandaMento.sol
Original file line number Diff line number Diff line change
Expand Up @@ -75,11 +75,12 @@ contract GrandaMento is
address payable exchanger;
// The stable token involved in this proposal. This is stored rather than
// the stable token's registry ID in case the contract address is changed
// while a stable token deposit
// after a proposal is created, which could affect refunding or burning the
// stable token.
address stableToken;
// The state of the exchange proposal.
ExchangeProposalState state;
// Whether CELO is being sold and stableToken is being bought.
// Whether the exchanger is selling CELO and buying stableToken.
bool sellCelo;
// The amount of the sell token being sold. If a stable token is being sold,
// the amount of stable token in "units" is stored rather than the "value."
Expand All @@ -100,6 +101,11 @@ contract GrandaMento is
// is being sold that has demurrage enabled, the original value when the stable
// tokens were deposited cannot be calculated.
uint256 celoStableTokenExchangeRate;
// The veto period in seconds at the time the proposal was created. This is kept
// track of on a per-proposal basis to lock-in the veto period for a proposal so
// that changes to the contract's vetoPeriodSeconds do not affect existing
// proposals.
uint256 vetoPeriodSeconds;
// The timestamp (`block.timestamp`) at which the exchange proposal was approved
// in seconds. If the exchange proposal has not ever been approved, is 0.
uint256 approvalTimestamp;
Expand Down Expand Up @@ -252,8 +258,15 @@ contract GrandaMento is
sellAmount: storedSellAmount,
buyAmount: buyAmount,
celoStableTokenExchangeRate: celoStableTokenExchangeRate,
vetoPeriodSeconds: vetoPeriodSeconds,
approvalTimestamp: 0 // initial value when not approved yet
});
// StableToken.unitsToValue (called within getSellTokenAndSellAmount) can
// overflow for very large StableToken amounts. Call it here as a sanity
// check, so that the overflow happens here, blocking proposal creation
// rather than when attempting to execute the proposal, which would lock
// funds in this contract.
getSellTokenAndSellAmount(exchangeProposals[exchangeProposalCount]);
// Push it into the array of active proposals.
activeProposalIdsSuperset.push(exchangeProposalCount);
// Even if stable tokens are being sold, the sellAmount emitted is the "value."
Expand Down Expand Up @@ -310,11 +323,13 @@ contract GrandaMento is
// Require the appropriate state and sender.
// This will also revert if a proposalId is given that does not correspond
// to a previously created exchange proposal.
require(
(proposal.state == ExchangeProposalState.Proposed && proposal.exchanger == msg.sender) ||
(proposal.state == ExchangeProposalState.Approved && isOwner()),
"Sender cannot cancel the exchange proposal"
);
if (proposal.state == ExchangeProposalState.Proposed) {
require(proposal.exchanger == msg.sender, "Sender must be exchanger");
} else if (proposal.state == ExchangeProposalState.Approved) {
require(isOwner(), "Sender must be owner");
} else {
revert("Proposal must be in Proposed or Approved state");
}
// Mark the proposal as cancelled. Do so prior to refunding as a measure against reentrancy.
proposal.state = ExchangeProposalState.Cancelled;
// Get the token and amount that will be refunded to the proposer.
Expand All @@ -330,7 +345,7 @@ contract GrandaMento is
/**
* @notice Executes an exchange proposal that's been approved and not vetoed.
* @dev Callable by anyone. Reverts if the proposal is not in the Approved state
* or vetoPeriodSeconds has not elapsed since approval.
* or proposal.vetoPeriodSeconds has not elapsed since approval.
* @param proposalId The identifier of the proposal to execute.
*/
function executeExchangeProposal(uint256 proposalId) external nonReentrant {
Expand All @@ -339,7 +354,7 @@ contract GrandaMento is
require(proposal.state == ExchangeProposalState.Approved, "Proposal must be in Approved state");
// Require that the veto period has elapsed since the approval time.
require(
proposal.approvalTimestamp.add(vetoPeriodSeconds) <= block.timestamp,
proposal.approvalTimestamp.add(proposal.vetoPeriodSeconds) <= block.timestamp,
"Veto period not elapsed"
);
// Mark the proposal as executed. Do so prior to exchanging as a measure against reentrancy.
Expand Down Expand Up @@ -602,6 +617,11 @@ contract GrandaMento is
* @param newVetoPeriodSeconds The new value for the veto period in seconds.
*/
function setVetoPeriodSeconds(uint256 newVetoPeriodSeconds) public onlyOwner {
// Hardcode a max of 4 weeks.
// A minimum is not enforced for flexibility. A case of interest is if
// Governance were to be set as the `approver`, it would be desirable to
// set the veto period to 0 seconds.
require(newVetoPeriodSeconds <= 4 weeks, "Veto period cannot exceed 4 weeks");
vetoPeriodSeconds = newVetoPeriodSeconds;
emit VetoPeriodSecondsSet(newVetoPeriodSeconds);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{}
105 changes: 105 additions & 0 deletions packages/protocol/releaseData/versionReports/release5-report.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
{
"oldArtifactsFolder": "/home/circleci/app/packages/protocol/build/core-contracts.v4/contracts",
"newArtifactsFolder": "/home/circleci/app/packages/protocol/build/core-contracts.v5/contracts",
"exclude": "/.*Test|Mock.*|I[A-Z].*|.*Proxy|MultiSig.*|ReleaseGold|SlasherUtil|UsingPrecompiles/",
"report": {
"contracts": {
"GrandaMento": {
"changes": {
"storage": [],
"major": [
{
"contract": "GrandaMento",
"type": "NewContract"
}
],
"minor": [],
"patch": []
},
"versionDelta": {
"storage": "=",
"major": "+1",
"minor": "0",
"patch": "0"
}
},
"UsingRegistryV2": {
"changes": {
"storage": [],
"major": [
{
"contract": "UsingRegistryV2",
"type": "NewContract"
}
],
"minor": [],
"patch": []
},
"versionDelta": {
"storage": "=",
"major": "+1",
"minor": "0",
"patch": "0"
}
},
"StableToken": {
"changes": {
"storage": [],
"major": [],
"minor": [],
"patch": [
{
"contract": "StableToken",
"type": "DeployedBytecode"
}
]
},
"versionDelta": {
"storage": "=",
"major": "=",
"minor": "=",
"patch": "+1"
}
},
"StableTokenEUR": {
"changes": {
"storage": [],
"major": [],
"minor": [],
"patch": [
{
"contract": "StableTokenEUR",
"type": "DeployedBytecode"
}
]
},
"versionDelta": {
"storage": "=",
"major": "=",
"minor": "=",
"patch": "+1"
}
},
"Validators": {
"changes": {
"storage": [],
"major": [],
"minor": [],
"patch": [
{
"contract": "Validators",
"type": "DeployedBytecode"
}
]
},
"versionDelta": {
"storage": "=",
"major": "=",
"minor": "=",
"patch": "+1"
}
}
},
"libraries": {}
}
}
Loading