Skip to content

Commit

Permalink
add GenesisProtocolWrapper.getThresholdForSchemeAndCreator (#368)
Browse files Browse the repository at this point in the history
  • Loading branch information
dkent600 authored Nov 6, 2018
1 parent a906cba commit 70a37cb
Show file tree
Hide file tree
Showing 6 changed files with 109 additions and 14 deletions.
6 changes: 5 additions & 1 deletion lib/utilsInternal.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { promisify } from "es6-promisify";
import { BlockWithoutTransactionData, FilterResult } from "web3";
import { Address, fnVoid } from "./commonTypes";
import { Address, fnVoid, Hash } from "./commonTypes";
import { Utils, Web3 } from "./utils";

/**
Expand Down Expand Up @@ -65,6 +65,10 @@ export class UtilsInternal {
return !address || !Number.parseInt(address, 16);
}

public static isNullHash(hash: Hash): boolean {
return !hash || !Number.parseInt(hash, 16);
}

/**
* Returns promise of the maximum gasLimit that we dare to ever use, given the
* current state of the chain.
Expand Down
99 changes: 91 additions & 8 deletions lib/wrappers/genesisProtocol.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@ import {
ArcTransactionResult,
DecodedLogEntryEvent,
IContractWrapperFactory,
IVotingMachineWrapper
IVotingMachineWrapper,
StandardSchemeParams,
} from "../iContractWrapperBase";
import { ProposalService } from "../proposalService";
import { TransactionService, TxGeneratingFunctionOptions } from "../transactionService";
Expand Down Expand Up @@ -332,13 +333,71 @@ export class GenesisProtocolWrapper extends IntVoteInterfaceWrapper
}

/**
* Return the threshold that is required by a proposal to it shift it into boosted state.
* The computation depends on the current number of boosted proposals created for
* this voting machine by the DAO or other contract, as well as the GenesisProtocol
* parameters thresholdConstA and thresholdConstB.
* @param {GetThresholdConfig} options
* Return the threshold that is required for a proposal to be shifted into the boosted state.
* The computation depends on the current number of boosted proposals that were created for
* this voting machine by the scheme at `schemeInfo.address` for the given `avatarAddress`
* (`avatarAddress` is the `organizationAddress` given to the `propose` method),
* and the GenesisProtocol parameters `thresholdConstA` and `thresholdConstB` which
* are registered on behalf of the given scheme with an avatar's Controller,
* keyed by the given `avatarAddress`.
*
* Thus `avatarAddress` must be an avatar address and this function will not work if
* you pass for `avatarAddress` any other contract address than an avatar, even though
* GenesisProtocol is capable of using those non-avatar contract addresses.
* In those cases, when the organization is not an avatar, you must use `getThresholdFromProposal`
* to obtain the threshold.
*
* Note that there will be a separately-scoped threshold for proposals created for this
* voting machine by any other scheme than the one given.
*
* Note that for Arc.js schemes you can just pass an Arc.js contract wrapper for `schemeInfo`.
*/
public async getThresholdForSchemeAndCreator(
schemeInfo: ThresholdSchemeInfo,
avatarAddress: Address): Promise<BigNumber> {

if (!schemeInfo) {
throw new Error("schemeAddress is not defined");
}

if (!avatarAddress) {
throw new Error("avatarAddress is not defined");
}

const organizationId = this.organizationIdFromProposalCreator(schemeInfo.address, avatarAddress);

const votingMachineInfo = await schemeInfo.getSchemeParameters(avatarAddress);

if (!votingMachineInfo) {
throw new Error("votingMachineInfo is null, avatarAddress may not be an avatar");
}

if (votingMachineInfo.votingMachineAddress !== this.address) {
throw new Error("the scheme is not using this voting machine");
}

const votingMachineParamsHash = votingMachineInfo.voteParametersHash;

if (UtilsInternal.isNullHash(votingMachineParamsHash)) {
throw new Error("avatarAddress does not yield a parameters hash, may not be an avatar");
}

this.logContractFunctionCall("GenesisProtocol.threshold",
{ schemeInfo, avatarAddress, votingMachineParamsHash, organizationId });

return this.contract.threshold(votingMachineParamsHash, organizationId);
}
/**
* Return the threshold that is required for a proposal to be shifted into the boosted state.
* The computation depends on the current number of boosted proposals that were created for
* this voting machine by the scheme that created the given proposal,
* and the GenesisProtocol parameters `thresholdConstA` and `thresholdConstB` which
* are stored with the proposal.
*
* Note that there will be a separately-scoped threshold for proposals created for this
* voting machine by any other scheme than the one that created the given proposal.
*/
public async getThreshold(proposalId: Hash): Promise<BigNumber> {
public async getThresholdFromProposal(proposalId: Hash): Promise<BigNumber> {

if (!proposalId) {
throw new Error("proposalId is not defined");
Expand Down Expand Up @@ -373,7 +432,8 @@ export class GenesisProtocolWrapper extends IntVoteInterfaceWrapper

const organizationId = this.organizationIdFromProposalCreator(schemeAddress, creatorAddress);

this.logContractFunctionCall("GenesisProtocol.getBoostedProposalsCount", creatorAddress);
this.logContractFunctionCall("GenesisProtocol.getBoostedProposalsCount",
{ schemeAddress, creatorAddress, organizationId });

return this.contract.getBoostedProposalsCount(organizationId);
}
Expand Down Expand Up @@ -1352,6 +1412,12 @@ export interface ExecutedGenesisProposal extends GenesisProtocolProposal {
}

export interface GenesisProtocolProposal {
/**
* This is what will appear as `_organization` in voting machine events.
* It is the value passed to `propose` as the optional argument: `organizationAddress`.
* If this argument is set to zero in `propose` then the value will be the msg.sender.
* With proposals created by Arc universal schemes (like GenesisProtocol), this is the avatar address.
*/
creatorAddress: Address;
/**
* in seconds
Expand Down Expand Up @@ -1420,3 +1486,20 @@ export interface GetNumberOfChoicesConfig {
*/
proposalId: string;
}

/**
* Input to `GenesisProtocolWrapper.getThresholdForSchemeAndCreator`. Provides info about a
* proposal-creating scheme that is generating proposals using GenesisProtocol.
*/
export interface ThresholdSchemeInfo {
/**
* address of the scheme
*/
address: Address;
/**
* Returns promise of a `StandardSchemeParams` as the referenced scheme's parameters, as registered
* with the given avatar address.
* @param avatarAddress
*/
getSchemeParameters(avatarAddress: Address): Promise<StandardSchemeParams>;
}
1 change: 1 addition & 0 deletions mkdocs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -286,6 +286,7 @@ nav:
- StandardTokenChangeApprovalOptions : 'api/interfaces/StandardTokenChangeApprovalOptions.md'
- StandardTokenTransferFromOptions : 'api/interfaces/StandardTokenTransferFromOptions.md'
- StandardTokenTransferOptions : 'api/interfaces/StandardTokenTransferOptions.md'
- ThresholdSchemeInfo : 'api/interfaces/ThresholdSchemeInfo.md'
- TokenCapGcParams : 'api/interfaces/TokenCapGcParams.md'
- TransactionReceiptsEventInfo : 'api/interfaces/TransactionReceiptsEventInfo.md'
- TransactionReceiptTruffle : 'api/interfaces/TransactionReceiptTruffle.md'
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@daostack/arc.js",
"version": "0.0.0-alpha.87",
"version": "0.0.0-alpha.88",
"description": "A JavaScript library for interacting with @daostack/arc ethereum smart contracts",
"main": "dist/index.js",
"types": "dist/index.d.ts",
Expand Down
13 changes: 10 additions & 3 deletions test/genesisProtocol.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ describe("GenesisProtocol", () => {
let contributionReward: ContributionRewardWrapper;

const sufficientStake = async (proposalId: Hash, amount: number): Promise<BigNumber> => {
return (await genesisProtocol.getThreshold(proposalId)).add(web3.toWei(amount));
return (await genesisProtocol.getThresholdFromProposal(proposalId)).add(web3.toWei(amount));
};

const createProposal = async (): Promise<Hash> => {
Expand Down Expand Up @@ -542,9 +542,16 @@ describe("GenesisProtocol", () => {
assert(typeof result !== "undefined");
});

it("can call getThreshold", async () => {
it("can call getThresholdFromProposal", async () => {
const proposalId = await createProposal();
const result = await genesisProtocol.getThreshold(proposalId);
const result = await genesisProtocol.getThresholdFromProposal(proposalId);
assert(typeof result !== "undefined");
});

it("can call getThresholdForSchemeAndCreator", async () => {
const result = await genesisProtocol.getThresholdForSchemeAndCreator(
contributionReward,
dao.avatar.address);
assert(typeof result !== "undefined");
});

Expand Down
2 changes: 1 addition & 1 deletion test/redeemer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ describe("Redeemer", () => {
await helpers.vote(result.votingMachine, proposalId, BinaryVoteResult.No, accounts[2]);
await helpers.vote(result.votingMachine, proposalId, BinaryVoteResult.Yes, accounts[3]);

const stakeAmount = (await gp.getThreshold(proposalId)).add(web3.toWei(10));
const stakeAmount = (await gp.getThresholdFromProposal(proposalId)).add(web3.toWei(10));

await (await gp.stakeWithApproval({ amount: stakeAmount, vote: 1, proposalId })).getTxMined();

Expand Down

0 comments on commit 70a37cb

Please sign in to comment.