Skip to content

Commit

Permalink
Add Comp Token and Governor Alpha [Release Candidate 1]
Browse files Browse the repository at this point in the history
This patch builds our official release candidates for the Comp and Governor Alpha systems. We make a number of minor changes from the 2.5 Alpha 2 version, including:

 * Change proposal and quorum thresholds to 1% and 4% respectively
 * Make a number of cosmetic changes and updates to events
 * Add test-net deployments [Ropsten, Goerli]
 * Add additional unit tests, scenarios and formal verification
 * Upgrade saddle to include `saddle console`
 * Upgrade Docker for newest version
  • Loading branch information
hayesgm committed Feb 8, 2020
1 parent f5976a8 commit 55729b3
Show file tree
Hide file tree
Showing 35 changed files with 4,026 additions and 2,828 deletions.
39 changes: 36 additions & 3 deletions .dockerignore
Original file line number Diff line number Diff line change
@@ -1,5 +1,38 @@
allFiredEvents
build
build_
node_modules
scenario/node_modules
test
!test/contracts
*.DS_Store
.env
.certora*
certora_*
coverage/
coverage.json
emv-*/
networks/test.json
networks/test-abi.json
networks/coverage.json
networks/coverage-abi.json
networks/development.json
networks/development-abi.json
networks/coverage-contracts/*
networks/test-contracts/*
networks/*-contracts.json
networks/*-history
networks/*-settings.json
*.DS_Store
test-results.xml
.tsbuilt
yarn-error.log
scenario/build/webpack.js
.scencache
.solcache
.solcachecov
scenario/.tscache
tests
spec
junit.xml
.build
.last_confs
.git
script/certora
30 changes: 11 additions & 19 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,30 +1,22 @@
FROM mhart/alpine-node:11.10.1
FROM mhart/alpine-node:13.8.0

RUN apk update && apk add --no-cache --virtual build-dependencies git python g++ make
RUN yarn global add [email protected]
RUN yarn global add [email protected]
RUN yarn global add typescript
RUN wget https://github.com/ethereum/solidity/releases/download/v0.5.13/solc-static-linux -O /bin/solc && chmod +x /bin/solc

RUN wget https://github.com/ethereum/solidity/releases/download/v0.5.8/solc-static-linux -O /usr/local/bin/solc && \
chmod +x /usr/local/bin/solc

RUN mkdir -p /deploy/compound-protocol/scenario
WORKDIR /deploy/compound-protocol
RUN mkdir -p /compound-protocol
WORKDIR /compound-protocol

# First add deps
ADD ./package.json /deploy/compound-protocol/
ADD ./yarn.lock /deploy/compound-protocol/
RUN yarn install
ADD scenario/package.json /deploy/compound-protocol/scenario
ADD scenario/yarn.lock /deploy/compound-protocol/scenario
RUN ls -la /deploy/compound-protocol
RUN ls -la /deploy/compound-protocol/scenario
RUN cd /deploy/compound-protocol/scenario && yarn install
ADD ./package.json /compound-protocol
ADD ./yarn.lock /compound-protocol
RUN yarn install --lock-file

# Then rest of code and build
ADD . /deploy/compound-protocol
ADD . /compound-protocol

RUN truffle compile
ENV SADDLE_SHELL=/bin/sh
ENV SADDLE_CONTRACTS="contracts/*.sol contracts/**/*.sol"
RUN npx saddle compile

RUN apk del build-dependencies
RUN yarn cache clean
Expand Down
75 changes: 56 additions & 19 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -75,37 +75,27 @@ To run compound, pull the repository from GitHub and install its dependencies. Y

git clone https://github.com/compound-finance/compound-protocol
cd compound-protocol
yarn # or `npm install`

You can then compile and deploy the contracts with:

yarn run deploy

Note: this project does not use truffle migrations. The command above is the best way to deploy contracts. To view the addresses of contracts, please inspect the `networks/development.json` file that is produced as an artifact of that command.
yarn install --lock-file # or `npm install`

REPL
----

The Compound Protocol has a simple scenario evaluation tool to test and evaluate scenarios which could occur on the blockchain. This is primarily used for constructing high-level integration tests. The tool also has a REPL to interact with local the Compound Protocol (similar to `truffle console`).

yarn repl
yarn repl -n development
yarn repl -n rinkeby

> Read CToken cBAT Address
Command: Read CToken cBAT Address
AddressV<val=0xAD53863b864AE703D31b819d29c14cDA93D7c6a6>

You can read more about the scenario runner in the [Scenario Docs](https://github.com/compound-finance/compound-protocol/tree/master/scenario/SCENARIO.md) on steps for using the repl.

Deployment
----------

The easiest way to deploy some Erc20 tokens, cTokens and a Comptroller is through scenario scripts.

Testing
-------
Mocha contract tests are defined under the [test directory](https://github.com/compound-finance/compound-protocol/tree/master/test). To run the tests run:
Jest contract tests are defined under the [tests directory](https://github.com/compound-finance/compound-protocol/tree/master/tests). To run the tests run:

yarn run test
yarn test

Integration Specs
-----------------
Expand All @@ -121,13 +111,13 @@ Code Coverage
-------------
To run code coverage, run:

yarn run coverage
yarn coverage

Linting
-------
To lint the code, run:

yarn run lint
yarn lint

Docker
------
Expand All @@ -140,9 +130,56 @@ To run in docker:
# Run a shell to the built image
docker run -it compound-protocol /bin/sh

From within a docker shell, you can interact locally with the protocol via ganache and truffle:

```bash
/compound-protocol # yarn console -n goerli
Using network goerli https://goerli-eth.compound.finance
Saddle console on network goerli https://goerli-eth.compound.finance
Deployed goerli contracts
comptroller: 0x627EA49279FD0dE89186A58b8758aD02B6Be2867
comp: 0xfa5E1B628EFB17C024ca76f65B45Faf6B3128CA5
governorAlpha: 0x8C3969Dd514B559D78135e9C210F2F773Feadf21
maximillion: 0x73d3F01b8aC5063f4601C7C45DA5Fdf1b5240C92
priceOracle: 0x9A536Ed5C97686988F93C9f7C2A390bF3B59c0ec
priceOracleProxy: 0xd0c84453b3945cd7e84BF7fc53BfFd6718913B71
timelock: 0x25e46957363e16C4e2D5F2854b062475F9f8d287
unitroller: 0x627EA49279FD0dE89186A58b8758aD02B6Be2867

> await comp.methods.totalSupply().call()
'10000000000000000000000000'
```

Console
-------

After you deploy, as above, you can run a truffle console with the following command:

yarn console -n goerli

This command will start a saddle console conencted to Goerli testnet (see [Saddle README](https://github.com/compound-finance/saddle#cli)):

```javascript
Using network goerli https://goerli.infura.io/v3/e1a5d4d2c06a4e81945fca56d0d5d8ea
Saddle console on network goerli https://goerli.infura.io/v3/e1a5d4d2c06a4e81945fca56d0d5d8ea
Deployed goerli contracts
comptroller: 0x627EA49279FD0dE89186A58b8758aD02B6Be2867
comp: 0xfa5E1B628EFB17C024ca76f65B45Faf6B3128CA5
governorAlpha: 0x8C3969Dd514B559D78135e9C210F2F773Feadf21
maximillion: 0x73d3F01b8aC5063f4601C7C45DA5Fdf1b5240C92
priceOracle: 0x9A536Ed5C97686988F93C9f7C2A390bF3B59c0ec
priceOracleProxy: 0xd0c84453b3945cd7e84BF7fc53BfFd6718913B71
timelock: 0x25e46957363e16C4e2D5F2854b062475F9f8d287
unitroller: 0x627EA49279FD0dE89186A58b8758aD02B6Be2867
> await comp.methods.totalSupply().call()
'10000000000000000000000000'
```

Discussion
----------

For any concerns with the protocol, visit us on [Discord](https://compound.finance/discord) to discuss.
For any concerns with the protocol, open an issue or visit us on [Discord](https://compound.finance/discord) to discuss.

For security concerns, please email [[email protected]](mailto:[email protected]).

_© Copyright 2020, Compound Labs, Inc._
_© Copyright 2020, Compound Labs_
2 changes: 1 addition & 1 deletion contracts/Governance/Comp.sol
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ contract Comp is EIP20Interface {
/// @notice A record of states for signing / validating signatures
mapping (address => uint) public nonces;

/// @notice An event thats emitted when an account changes their delegate
/// @notice An event thats emitted when an account changes its delegate
event DelegateChanged(address indexed delegator, address indexed fromDelegate, address indexed toDelegate);

/// @notice An event thats emitted when a delegate account's vote balance changes
Expand Down
32 changes: 18 additions & 14 deletions contracts/Governance/GovernorAlpha.sol
Original file line number Diff line number Diff line change
Expand Up @@ -24,13 +24,16 @@ contract GovernorAlpha {
string public constant name = "Compound Governor Alpha";

/// @notice The number of votes in support of a proposal required in order for a quorum to be reached and for a vote to succeed
function quorumVotes() public pure returns (uint) { return 600000e18; } // 600,000 = 6% of Comp
function quorumVotes() public pure returns (uint) { return 400000e18; } // 400,000 = 4% of Comp

/// @notice The number of votes required in order for a voter to become a proposer
function proposalThreshold() public pure returns (uint) { return 400000e18; } // 400,000 = 4% of Comp
function proposalThreshold() public pure returns (uint) { return 100000e18; } // 100,000 = 1% of Comp

/// @notice The maximum number of actions that can be included in a proposal
function proposalMaxOperations() public pure returns (uint) { return 10; } // 10 actions

/// @notice The delay before voting on a proposal may take place, once proposed
function votingDelay() public pure returns (uint) { return 1; }
function votingDelay() public pure returns (uint) { return 1; } // 1 block

/// @notice The duration of voting on a proposal, in blocks
function votingPeriod() public pure returns (uint) { return 17280; } // 3 days in blocks
Expand Down Expand Up @@ -128,10 +131,10 @@ contract GovernorAlpha {
bytes32 public constant BALLOT_TYPEHASH = keccak256("Ballot(uint256 proposalId,bool support)");

/// @notice An event emitted when a new proposal is created
event NewProposal(uint id, string description);
event ProposalCreated(uint256 id, address proposer, address[] targets, uint256[] values, string[] signatures, bytes[] calldatas, string description);

/// @notice An event emitted when a vote has been cast on a proposal
event VoteCast(uint proposalId, bool support, uint votes);
event VoteCast(address voter, uint proposalId, bool support, uint votes);

/// @notice An event emitted when a proposal has been canceled
event ProposalCanceled(uint id);
Expand All @@ -140,7 +143,7 @@ contract GovernorAlpha {
event ProposalQueued(uint id, uint eta);

/// @notice An event emitted when a proposal has been executed in the Timelock
event ProposalExecuted(uint id, uint eta);
event ProposalExecuted(uint id);

constructor(address timelock_, address comp_, address guardian_) public {
timelock = TimelockInterface(timelock_);
Expand All @@ -152,6 +155,7 @@ contract GovernorAlpha {
require(comp.getPriorVotes(msg.sender, block.number.sub(1)) > proposalThreshold(), "GovernorAlpha::propose: proposer votes below proposal threshold");
require(targets.length == values.length && targets.length == signatures.length && targets.length == calldatas.length, "GovernorAlpha::propose: proposal function information arity mismatch");
require(targets.length != 0, "GovernorAlpha::propose: must provide actions");
require(targets.length <= proposalMaxOperations(), "GovernorAlpha::propose: too many actions");

uint latestProposalId = latestProposalIds[msg.sender];
if (latestProposalId != 0) {
Expand Down Expand Up @@ -180,7 +184,7 @@ contract GovernorAlpha {
proposals[newProposal.id] = newProposal;
latestProposalIds[newProposal.proposer] = newProposal.id;

emit NewProposal(newProposal.id, description);
emit ProposalCreated(newProposal.id, msg.sender, targets, values, signatures, calldatas, description);
return newProposal.id;
}

Expand All @@ -207,7 +211,7 @@ contract GovernorAlpha {
for (uint i = 0; i < proposal.targets.length; i++) {
timelock.executeTransaction.value(proposal.values[i])(proposal.targets[i], proposal.values[i], proposal.signatures[i], proposal.calldatas[i], proposal.eta);
}
emit ProposalExecuted(proposalId, proposal.eta);
emit ProposalExecuted(proposalId);
}

function cancel(uint proposalId) public {
Expand All @@ -226,7 +230,7 @@ contract GovernorAlpha {
}

function getActions(uint proposalId) public view returns (address[] memory targets, uint[] memory values, string[] memory signatures, bytes[] memory calldatas) {
Proposal memory p = proposals[proposalId];
Proposal storage p = proposals[proposalId];
return (p.targets, p.values, p.signatures, p.calldatas);
}

Expand All @@ -236,8 +240,8 @@ contract GovernorAlpha {

function state(uint proposalId) public view returns (ProposalState) {
require(proposalCount >= proposalId && proposalId > 0, "GovernorAlpha::state: invalid proposal id");
Proposal memory proposal = proposals[proposalId];
if (proposal.canceled == true) {
Proposal storage proposal = proposals[proposalId];
if (proposal.canceled) {
return ProposalState.Canceled;
} else if (block.number <= proposal.startBlock) {
return ProposalState.Pending;
Expand Down Expand Up @@ -270,10 +274,10 @@ contract GovernorAlpha {
}

function _castVote(address voter, uint proposalId, bool support) internal {
require(state(proposalId) == ProposalState.Active, "GovernorAlpha::castVote: voting is closed");
require(state(proposalId) == ProposalState.Active, "GovernorAlpha::_castVote: voting is closed");
Proposal storage proposal = proposals[proposalId];
Receipt storage receipt = proposal.receipts[voter];
require(receipt.hasVoted == false, "GovernorAlpha::castVote: voter already voted");
require(receipt.hasVoted == false, "GovernorAlpha::_castVote: voter already voted");
uint96 votes = comp.getPriorVotes(voter, proposal.startBlock);

if (support) {
Expand All @@ -286,7 +290,7 @@ contract GovernorAlpha {
receipt.support = support;
receipt.votes = votes;

emit VoteCast(proposalId, support, votes);
emit VoteCast(voter, proposalId, support, votes);
}

function __acceptAdmin() public {
Expand Down
Loading

0 comments on commit 55729b3

Please sign in to comment.